[Ruby] gems: Webクローラ anemone を使ってみる
ブログの調査を自動化できないかと思い、anemone を調べてみました。
公式サイトのサンプルをいろいろといじったり調べたりしたところ、ひとまず下記の2点を解決する必要がありそう。
- クロールの対象ページが多くても、動作に支障がないようにしたい。
- 指定した URL 以下にクロールを限定したい。
Contents
anemone と MongoDB をインストールする
anemone の標準では、メモリーにデータを保存するため、アクセス先のページが多いと支障が出てくるとのこと。
これを回避するためにストレージを利用するようで、定番は MongoDB のようなので、先人に習ってインストールを行います。
MongoDB のインストール
下記のとおり、インストールしました。
Gemfile
bundler で入れてみます。
% bundle init
# A sample Gemfile
source "https://rubygems.org"
gem "anemone", "~> 0.7.2"
gem "nokogiri", "~> 1.6.1"
gem "mongo", "~> 1.9.2"
gem "bson_ext", "~> 1.9.2"
% bundle
option
anemone のオプションを利用して、振る舞いを調整します。
オプションはこんなものがあるようです。
DEFAULT_OPTS = {
# run 4 Tentacle threads to fetch pages
:threads => 4,
# disable verbose output
:verbose => false,
# don't throw away the page response body after scanning it for links
:discard_page_bodies => false,
# identify self as Anemone/VERSION
:user_agent => "Anemone/#{Anemone::VERSION}",
# no delay between requests
:delay => 0,
# don't obey the robots exclusion protocol
:obey_robots_txt => false,
# by default, don't limit the depth of the crawl
:depth_limit => false,
# number of times HTTP redirects will be followed
:redirect_limit => 5,
# storage engine defaults to Hash in +process_options+ if none specified
:storage => nil,
# Hash of cookie name => value to send with HTTP requests
:cookies => nil,
# accept cookies from the server and send them back?
:accept_cookies => false,
# skip any link with a query string? e.g. http://foo.com/?u=user
:skip_query_strings => false,
# proxy server hostname
:proxy_host => nil,
# proxy server port number
:proxy_port => false,
# HTTP read timeout in seconds
:read_timeout => nil
}
focus_crawl method
指定したURL以下をクロールさせるために、focus_crawl という method を使うようなサンプルを探して見ました。
ありがたいことにそのまま目的を果たせそうなので、利用してみます。
サンプル
まとめてみると、こんな形になりました。
require 'rubygems'
require 'bundler/setup'
Bundler.require
options = {
:user_agent => "AnemoneCrawler/0.0.1",
:storage => Anemone::Storage.MongoDB,
:delay => 1,
:depth_limit => 1,
}
Anemone.crawl("http://www.example.com/", options) do |anemone|
anemone.focus_crawl do |page|
page.links.keep_if { |link|
link.to_s.match(/test/)
}
end
anemone.on_every_page do |page|
if page.doc
p page.url.to_s
p page.doc.at('title').inner_html
end
end
end
実行結果
% ruby anemone.rb
"http://www.example.com/"
"Example Domain"
MongoDB の内容を確認する
ストレージとして利用した MongoDB にどんなデータが入ったのか確認してみます。
% mongo
MongoDB shell version: 2.4.9
connecting to: test
> show dbs;
anemone 0.203125GB
local 0.078125GB
> use anemone;
switched to db anemone
> show collections;
pages
system.indexes
> db.pages.find();
{ "_id" : ObjectId("52d54b1b4ced2ab4af3c12dd"), "url" : "http://www.example./", "headers" : BinData(0,"BAh7BkkiEWNvbnRlbnQtdHlwZQY6BkVUWwZJIgAGOwBU"), "data" : BinData(0,"BAhVOg9PcGVuU3RydWN0ewA="), "body" : null, "links" : [ ], "code" : null, "visited" : null, "depth" : 0, "referer" : "", "redirect_to" : "", "response_time" : null, "fetched" : false }
補遺
取得したデータの Parse は Nokogiri が担当している。
著作権。