Mechanizeでのスクレイピング時、アクセス元IPアドレスを分散させる
2014年12月17日Ruby Advent Calendar 2014 17日目
Ruby Advent Calendar 2014、17日目の記事になります。
スクレイピング時にアクセス元のIPアドレスを分散させたい
ConoHa VPSではVPS1契約ごとに最大16個の追加IPアドレスを購入できます。1つあたり200円と安価で、最安のプランで契約し追加IPアドレスを16個オプションで追加すれば、17個のIPアドレスを持つVPSサーバーの出来上がりです。月額4,180円で、1IPアドレスあたり月額約246円です。非常に安価ですね。
さて、スクレイピング時にアクセス元のIPアドレスを分散させたいということは割とあるかと思います。その是非はここでは置いておくとして、ConoHa VPSを利用することで安価にその土壌となるサーバーを入手できることがわかりました。ただし、Rubyにおいてスクレイピングに有用なgemであるMechanizeには、指定のネットワークインターフェイスを経由してHTTPアクセスを行うといった機能は付いていません。そこで今回はMechanizeにて任意のネットワークインターフェイスにてスクレイピングを行う方法を解説します。
コード
require 'mechanize' module Benrify refine Net::HTTP::Persistent do alias_method :connection_for_origin, :connection_for attr_accessor :local_host attr_accessor :local_port def connection_for uri conn = connection_for_origin uri if conn.local_host != @local_host || conn.local_port != @local_port conn.local_host = @local_host conn.local_port = @local_port conn.finish end conn end end refine Mechanize do def bind(local_host = nil, local_port = nil) @agent.http.local_host = local_host @agent.http.local_port = local_port end end end using Benrify
これだけです。Net::HTTP::Persistentを上書きすることで実現します。クラスの拡張にはRefinementsを使いましょう。
使用例
require 'mechanize' module Benrify # 省略 end using Benrify def test(address = nil) $a ||= Mechanize.new $a.bind address if address res = $a.get 'http://wtfismyip.com/text' res.body.strip end local_addresses = Socket.getifaddrs.select{|it| it.addr.ipv4? }.select{|it| /(?:eth|en)\d+(?::\d+)?/ =~ it.name } puts 'Try: default' puts 'Got: ' + test puts '-' * 20 local_addresses.each do |it| puts "Try: #{it.addr.ip_address}(#{it.name})" puts 'Got: ' + test(it.addr.ip_address) puts '-' * 20 end
Socket.getifaddrsでネットワークインターフェイスの一覧が取得できるので、そこから好きなものを選んでMechanize.bindメソッドにて割り当てを行うだけです。
この例では、ethもしくはenで始まる全てのインターフェイスを取得し、それらをそれぞれMechanize.bindした上でhttp://wtfismyip.com/textの内容を取得・表示しています。
http://wtfismyip.com/は、アクセス元のIPアドレスを表示してくれるウェブサービスです。XMLやJSON、プレインテキストなどの各種フォーマットでレスポンスを返してくれるURLも用意されており便利ですね。
おわり
スクレイピング時にアクセス元のIPアドレスを複数に分散させたい、ただし複数のサーバーを用意しそれらを管理する構成を作るほどの規模ではないし、予算も抑えたい。そういった場合にこのような手法が有用かと思います。通常こういったアクセス元IPアドレスの分散を行う場合は面倒なqueueの管理が必要かと思いますが、この方法を用いれば割と雑に組んでもそれなりに動くものができて便利です。
ConoHa VPS以外にもIPアドレスを追加購入できるVPSサーバーなどがあったら是非教えてください。