[Ruby] gems: Webクローラ anemone を使ってみる

ブログの調査を自動化できないかと思い、anemone を調べてみました。

[markdown]
> * [chriskite/anemone · GitHub](https://github.com/chriskite/anemone)
> * [Anemone – Ruby Web-Spider Framework](http://anemone.rubyforge.org/)

公式サイトのサンプルをいろいろといじったり調べたりしたところ、ひとまず下記の2点を解決する必要がありそう。

* クロールの対象ページが多くても、動作に支障がないようにしたい。
* 指定した URL 以下にクロールを限定したい。

## anemone と MongoDB をインストールする

anemone の標準では、メモリーにデータを保存するため、アクセス先のページが多いと支障が出てくるとのこと。
これを回避するためにストレージを利用するようで、定番は MongoDB のようなので、先人に習ってインストールを行います。

> * [仕事帳: Webクローラフレームワーク Anemone の紹介](http://work.blog.eggplant.org.uk/2011/03/web-anemone.html)
> * [ruby – Getting all URLs using anemone gem (very large site) – Stack Overflow](http://stackoverflow.com/questions/18367170/getting-all-urls-using-anemone-gem-very-large-site)

### MongoDB のインストール

下記のとおり、インストールしました。

> * [MongoDB: Homebrew でインストールする | deadwood](https://www.d-wood.com/blog/2014/01/23_5330.html)

### Gemfile

bundler で入れてみます。

“`prettyprinted
% bundle init
“`

“`ruby:Gemfile
# 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”
“`

“`prettyprinted
% bundle
“`

### option

anemone のオプションを利用して、振る舞いを調整します。
オプションはこんなものがあるようです。

> * [chriskite/anemone · GitHub](https://github.com/chriskite/anemone)

“`ruby:/lib/anemone/core.rb
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 を使うようなサンプルを探して見ました。

> * [Anemone gem (ruby) で指定したURLだけクロールする方法 – Qiita [キータ]](http://qiita.com/tady/items/8a954dfcd03521f8a200)

ありがたいことにそのまま目的を果たせそうなので、利用してみます。

## サンプル

まとめてみると、こんな形になりました。

“`ruby:anemone.rb
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
“`

### 実行結果

“`prettyprinted
% ruby anemone.rb
“http://www.example.com/”
“Example Domain”
“`

## MongoDB の内容を確認する

ストレージとして利用した MongoDB にどんなデータが入ったのか確認してみます。

“`prettyprinted
% 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 が担当している。

> * [Nokogiri](http://nokogiri.org/)
> * [Nokogiri の基本(翻訳版)](http://www.engineyard.co.jp/blog/2012/getting-started-with-nokogiri/)
> * [Nokogiri を使った Rubyスクレイピング [初心者向けチュートリアル] – 酒と泪とRubyとRailsと](http://morizyun.github.io/blog/ruby-nokogiri-scraping-tutorial/)

著作権。

> * [Rubyとか使ってクローリングやスクレイピングするノウハウを公開してみる! – 病みつきエンジニアブログ](http://yamitzky.hatenablog.com/entry/2013/12/31/034821)
[/markdown]