Photo by pnoeric
いま、PhotoShareで使うために、高速なEvent Driven方式のネットワークライブラリ、EventMachineを調べています。
このEventMachine、ほとんどの場合はサーバを作るときに使われていますが、HTTPクライアントの機能も実装されており、実はクローラの様な物を作るときにも利用することができます。
今回はこっちを使いたかったのですが、ググってもほとんど情報が出てこなかったので、Seattle.rbで相談したところ、Aaronさん(RubyKaigi 2008でプレゼンしているのをustで見てコンタクトしました)からサンプルが貰えたので、それを元に、同時接続する様にしてみました。
このコードだけだと役には立ちませんが、情報が少なかったので参考に上げておきます。
require 'rubygems'
require 'eventmachine'
CONCURRENCY = 2
TARGET_URL = 'http://localhost:3000/'
def create_connection
puts ">>>> create"
uri = URI.parse(TARGET_URL)
request = Net::HTTP::Get.new(uri.request_uri)
client = EventMachine::Protocols::HttpClient.send(:request,
:host => uri.host,
:port => uri.port,
:request_obj => request)
client.callback do |result|
$queue.delete client
$queue << create_connection if $queue.size < CONCURRENCY
puts ">>>> callback"
p result
end
client.errback do
# TODO
end
client
end
$queue = []
EventMachine.run do
CONCURRENCY.times do
$queue << create_connection
end
end

maimuzo
自分もクローラーを使いたくて調べてた所だったのでとても参考になりました。
これって、最大クライアント数(CONCURRENCY)までHTTPリクエストを並列実行する部分のソースですよね。
こんなに簡単にできるんだ。
TARGET_URLをキューから持ってくるようにして、resultのパースを自分で書けば(ここも便利なgemとかあるんだろうか)、比較的簡単にできそうな気がしてきました。
skynetと絡ませたら面白そうですね。
masuidrive
そうですね。うちは別ポートでキューにURLを突っ込めるようにしたいなと思ってます。
HTMLのパースなら、Hpricotあたりが有名だと思います。
skynetってなんですか?
maimuzo
skynetはgoogleのMapReduceをrubyで実装したgemです。
http://skynet.rubyforge.org/
ただ、どうもコードをマップするのではなく、データをマップするようなので、あらかじめコードをワーカに配置しておかなければならないようですけどね。(よく理解してないんですけどね^^)
EC2などで必要なときだけインスタンス立ち上げて、マップでクロール対象URLを蒔いて、結果を集計すれば個人でも計算可能量がものすごく増加すると思うので使ってみたいのですが、どういう風に使えばいいのかイマイチピンとこないのです。
ググると日本語ではこれぐらいしか出てこないので困っています。
http://www.moongift.jp/2008/06/skynet/
http://www.infoq.com/jp/news/2008/02/ruby-mapreduce-skynet
GEM_HOMEの中のexampleが一番参考になりそうですが、読み解くのに時間がかかりそうです…