プログラマでありたい

おっさんになっても、プログラマでありつづけたい

Capybara+PhantomJS+Nokogiriを利用してスクレイピング

CapybaraとPhantomJS、Nokogiriを利用してのクローラー・スクレイピングの紹介です。

PhantomJSとは?



f:id:dkfj:20150214123247p:plain
 PhantomJSは、ヘッドレスブラウザと呼ばれるWebKitのエミュレータです。ヘッドレスブラウザとは、GUIではなくCUIから利用できるブラウザでプログラムから呼ばれます。UIのテストツールとしてSeleniumのようなサービスがあります。Seleniumはブラウザを直接操作するので、環境依存や動作が重いといった幾つかの問題点があります。そこでよく利用されるのがPhantomJSです。Seleniumに比べて、軽量というメリットがあります。RubyからPhantomJSを扱うライブラリとして、Poltergeistがあります。

Capybaraとは?



 Capybaraは、WebシステムのUI層のテストをサポートするためのライブラリです。主にDSL機能とDriver機能があり、テストフレームワークやブラウザ&ブラウザシミュレータを透過的に扱うことができます。
f:id:dkfj:20150214123816p:plain

Nokogiriとは?



f:id:dkfj:20140415021125p:plain
 Nokogiriは、Rubyで実装されたHTML/XMLの構文解析器(パーサー)です。Rubyの構文解析器としてはデファクト・スタンダードで、スクレイピングする際の必須のツールとなっています。Rubyで実装されたクローラー・スクレイピングライブラリの大部分は、内部的にNokogiriを利用しています。使い方の詳細は、下記のリンクを参照していただければと思います。
Ruby製の構文解析ツール、Nokogiriの使い方 with Xpath

PhantomJSとCapybaraのインストール



 PhantomJSのインストールは、Windowsでは少し面倒くさいことが多いです。PhantomJSのサイトからダウンロードしてパスを通すことが必要です。Mac+HomeBrewであれば、下記のコマンドでインストールできると思います。

brew install phantomjs

 その後に、PoltergeistやCapybaraをインストールします。

gem install nokogiri
gem install poltergeist
gem install capybara

 Windowsのnokogiriのインストールはハマる確率が高いです。ビルド済みのgemをダウンロードする方をお勧めします。x86-mingw32(32ビット版)もしくは x64-mingw32(64ビット版)と書かれているものがWindowsようです。
※最近、64ビット版も提供されるようになったようですね。

スクレイピング



 下記がCapybaraとPhantomjsとNokogiriを使ったサンプルスクリプトです。

require 'capybara'
require 'capybara/dsl'
require 'capybara/poltergeist'

class Scrape
  #DSLのスコープを別けないと警告がでます
  include Capybara::DSL

  def initialize()
    Capybara.register_driver :poltergeist_debug do |app|
      Capybara::Poltergeist::Driver.new(app, :inspector => true)
    end

    Capybara.default_driver = :poltergeist
    Capybara.javascript_driver = :poltergeist
  end

  def visit_site
    page.driver.headers # => {}
    #ユーザエージェントの設定(必要に応じて)
    page.driver.headers = { "User-Agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36" }
    #リファラーの偽装(特に不要)
    #page.driver.add_headers("Referer" => "http://yahoo.co.jp")
    page.driver.headers
    visit('http://www.yahoo.co.jp')
    #スクリーンショットで保存
    page.save_screenshot('screenshot.png', :full => true)
    #within(:xpath, "//*[@id='toipcsfb']/div[1]/ul[1]") do
    #Nokogirオブジェクトの作成
    doc = Nokogiri::HTML.parse(page.html)
    puts doc.title
  end
end

scrape = Scrape.new
scrape.visit_site

ポイントとしては、次のとおりです。
・Capybara DSLのスコープを別ける
  しないと、次のように警告でますよ
  including Capybara::DSL in the global scope is not recommended!
・Nokogiriを使ってる
  Capybaraの記法に慣れていない場合は、Nokogiriを作ってしまうのも1つの手です。
  無駄が多いけど

このサンプルでは、面倒くさいのでJavaScriptによって動的に構築された部分とってませんが。。。

まとめ



 JavaScriptバリバリのサイトからスクレイピングしたい場合、PhantomJSはお勧めです。少し重いものの、Seleniumでブラウザを動かすより断然軽量です。またブラウザのインストールが不要なので、サーバサイドで動かすことも容易です。今、PhantomJSをAWS Lambdaで動かそうかなと試しています。これが出来ればかなり面白いことが出来そうですね。
 この辺りの話をまとめた、「Rubyによるクローラー開発技法」という本を出しています。ひたすらクローリングとスクレイピングしているので、何か参考になることがあればと思います。


See Also:
『Rubyによるクローラー開発技法』を書きました
RubyでWebスクレイピングの話をしてきました。第1回Webスクレイピング勉強会@東京
Ruby製の構文解析ツール、Nokogiriの使い方 with Xpath
あらためてRuby製のクローラー、"anemone"を調べてみた
オープンソースのRubyのWebクローラー"Anemone"を使ってみる