Anemoneのストレージを変更するシリーズ、ついでにSQLite3とMongoDBも書いておきます。
AnemoneでSQLite3を利用する
AnemoneでSQLite3を利用するには、オプションで:storage => Anemone::Storage::SQLite3()と指定するだけです。引数を渡さなければ、anemone.dbという形式のsqlite3ファイルが作成されます。プログラムとしては、次のような形ですね。
require 'anemone' urls = [] urls.push("http://www.yahoo.co.jp") opts = { :storage => Anemone::Storage::SQLite3(), :obey_robots_txt => true, :depth_limit => 0 } Anemone.crawl(urls, opts) do |anemone| anemone.on_every_page do |page| puts page.url p page.doc.xpath("//title/text()").to_s if page.doc end end
SQLite3を使った場合の嬉しいところは、2回目以降の起動でも既読スキップが有効になる点です。これは、初期化処理でPStoreと違いファイルの削除なども行わず、テーブル作成時も既存テーブルがあればちゃんと残している点です。
def initialize(file) @db = ::SQLite3::Database.new(file) create_schema end def create_schema @db.execute_batch <<SQL create table if not exists anemone_storage ( id INTEGER PRIMARY KEY ASC, key TEXT, data BLOB ); create index if not exists anemone_key_idx on anemone_storage (key); SQL end
一方で、既読スキップはURLのみで判断しています。訪問後、N日の場合は再取得といった処理はできません。何故なら、前回取得時の日時情報を持っていないからです。
def has_key?(url) !!@db.get_first_value('SELECT id FROM anemone_storage WHERE key = ?', url.to_s) end
この辺りは、少し改善したいですね。
AnemoneでMongoDBを利用する
AnemoneでMongoDBを利用する場合も、オプションで:storage => Anemone::Storage::MongoDB()と指定するだけです。前提として、ローカルにMongoDBのデーモンが起動されている必要があります。
require 'anemone' urls = [] urls.push("http://www.yahoo.co.jp") opts = { :storage => Anemone::Storage::MongoDB(), :depth_limit => 0 } Anemone.crawl(urls, opts) do |anemone| anemone.on_every_page do |page| puts page.url puts page.doc.xpath("//title/text()").to_s if page.doc end end
MongoDBで利用するDB名やCollection名も変更可能ですが、DB名の変更の方法は微妙です。mongoのGemを呼び元でrequireして、DBを作成の上で渡す必要があります。
require 'anemone' require 'mongo' opts = { :storage => Anemone::Storage::MongoDB(Mongo::Connection.new.db('crawler'),"documents") }
AnemoneのStorageクラスで、下記のような処理をしている為です。
def self.MongoDB(mongo_db = nil, collection_name = 'pages') require 'anemone/storage/mongodb' mongo_db ||= Mongo::Connection.new.db('anemone') raise "First argument must be an instance of Mongo::DB" unless mongo_db.is_a?(Mongo::DB) self::MongoDB.new(mongo_db, collection_name) end
こんな感じの方が、使い易いのではと思います。
def self.MongoDB(db_name = nil, collection_name = 'pages') db_name ||= "anemone mongo_db = Mongo::Connection.new.db(db_name)
ちなみに、AnemoneのMongoDBは、初期化処理でCollectionを削除しています。その為、2回目以降の処理で既読スキップは出来ません。(必要であれば、コメントアウトするなり対処しましょう。)
def initialize(mongo_db, collection_name) @db = mongo_db @collection = @db[collection_name] @collection.remove @collection.create_index 'url' end
まとめ
帯に短したすきに長し
See Also:
Ruby製のクローラー Anemoneでストレージをファイルに変更する
Ruby製の構文解析ツール、Nokogiriの使い方 with Xpath
Ruby製のクローラー Anemoneの文字化け対策
あらためてRuby製のクローラー、"anemone"を調べてみた
オープンソースのRubyのWebクローラー"Anemone"を使ってみる
JavaScriptにも対応出来るruby製のクローラー、Masqueを試してみる
複数並行可能なRubyのクローラー、「cosmicrawler」を試してみた
- 作者: るびきち,佐々木拓郎
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2014/08/25
- メディア: 大型本
- この商品を含むブログ (1件) を見る
Spidering hacks―ウェブ情報ラクラク取得テクニック101選
- 作者: Kevin Hemenway,Tara Calishain,村上雅章
- 出版社/メーカー: オライリー・ジャパン
- 発売日: 2004/05
- メディア: 単行本
- 購入: 52人 クリック: 904回
- この商品を含むブログ (103件) を見る