JavaScript が使われているサイトのスクレイピングなどに役立つ Watir Webdriver 。しょっちゅう使っているのでこれに関する記事を書きたいと思いつつ書いてなかったのですが、今回
ruby - JavaScript が実行された後の HTML を取得したい - スタック・オーバーフロー
へ勢いで回答した内容をそこに留めておくのがもったいない気になったので、こちらへもコピペしておきます。
Watir Webdriver の具体的な使い方
StackOverflow 日本版へのログイン( StackExchange のメールアドレス&パスワードを使用)を、 pry 環境下で Watir Webdriver と PhantomJS を使って行ってみます。
さらに( Nokogiri の使い方の例として)私が回答した記事のタイトル(現時点で5つあります)を取得してみます
require 'nokogiri' #=> true require 'watir-webdriver' #=> true browser = Watir::Browser.new(:phantomjs) # ブラウザオブジェクト(?)を生成 #=> #<Watir::Browser:0x..fe8d4c9dbde437598 url="about:blank" title=""> browser.goto("http://ja.stackoverflow.com/") # 目的のサイトへ移動 #=> "http://ja.stackoverflow.com/" browser.a(:xpath, '/html/body/div[4]/div/div[3]/div[1]/span/a[2]').click # ログイン画面へのリンクをクリック(XPath はもちろん略して '//div[4]/div/div[3]/div[1]/span/a[2]' とかにも出来ます) #=> [] # PhantomJS では不要だが Chrome などでは必要な項目 browser.p(:xpath, '//div[@id="se-signup-legend"]/p').click # emailフィールドなどが見えない状況なので見えるようにする。 #=> [] email = browser.text_field(:name, "email") # emailフィールドの要素取得 #=> #<Watir::TextField:0x..f9b0836120579f650 located=false selector={:name=>"email", :tag_name=>"input or textarea", :type=>"(any text type)"}> email.value = "riocampos@xxx.com" # email 入力 #=> "riocampos@xxx.com" password = browser.text_field(:name, "password") # passwordフィールドの要素取得 #=> #<Watir::TextField:0x35892c3f7283a538 located=false selector={:name=>"password", :tag_name=>"input or textarea", :type=>"(any text type)"}> password.value = "xxxxxxxxxxxx" # パスワード入力 #=> "xxxxxxxxxxxx" browser.form(:id, 'se-login-form').submit # ログインフォームを送信 #=> nil # これで StackOverflow にログイン出来ました browser.a(:xpath, '//div[@class="topbar-links"]/a').click # マイページへのリンクをクリック #=> [] answer_table_html = browser.table(:xpath, '//table[@class="user-answers lines"]').html; # 自分の回答履歴の表示されている部分のテーブル要素を取得して HTML に変換 ## HTML が返ってくる(省略) answer_table_doc = Nokogiri::HTML.parse(answer_table_html); # Nokogiri::HTML オブジェクトに変換 ## (返値省略) answer_table_doc.xpath('//td[@class="answer-hyperlink"]/a').map { |anchor| anchor.text } # 回答履歴の件名を配列で取得 #=> ["ディレクトリではないはずなのに、“Is a directory” というエラーが出る", # "JavaScript が実行された後の HTML を取得したい", # "rubyのeachを使用したファイルの結合方法について", # "プログラミング言語または英語圏の新語のリストを配布しているサイトを探しています", # "RubyGems 自体を削除したい"] browser.quit # ブラウザオブジェクトを削除 #=> true
上記では使用しませんでしたが、デバッグの際に役立つのがスクリーンショットです。
browser.screenshot.save("top.png")
のようにすると png ファイルで保存できます(ファイル形式は残念ながら png 限定です)。
なお、 自動作業を行う場合には PhantomJS を使いますが、ローカルで実行する場合や試行錯誤の状況では (ChromeDriver をインストールした環境下での)Chrome や (SafariDriver をインストールした環境下での)Safari などを使った方が格段にラクだと思います。それぞれブラウザインスタンスを生成する際に
browser = Watir::Browser.new(:chrome) browser = Watir::Browser.new(:safari)
とすれば良いです。