railsを覚えるより前に、簡単なphpを覚えた方がいいと思っている昼寝王子です。 今日は、ruby + seleniumでgoogleの検索結果を取得するコードを紹介します。
googleの検索結果は、jsなどが動いてhtmlが生成されているので単なるopen-uriなどでは取得が大変難しいです。そこで、使うのがseleniumです。seleniumではブラウザを実際に操作してスクレイピングを行うので、取得ができるのです。 今回はGoogleの検索結果をクローリングして見たいと思います。
今回は、「伝説の勇者の伝説」というキーワードをGoogle検索し、最初4ページのタイトルを取得するというものを作りたいと思います。
Gemfile
gem 'selenium-webdriver'
gem 'nokogiri'
google-crawler.rb
require 'nokogiri'
require 'selenium-webdriver'
class Crawler
def get_title_text(driver)
#Nokogiriを用いてHTMLをパースする
doc = Nokogiri::HTML.parse(driver.page_source, nil, 'utf-8')
#ユーザー名を取得
doc.css('h3.r').each do |h3|
puts h3.text
end
end
def main
ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
#ブラウザ立ち上げモード
#caps = Selenium::WebDriver::Remote::Capabilities.chrome('chromeOptions' => {args: ["--user-agent=#{ua}", 'window-size=1280x800']})
#ヘッドレスモード
caps = Selenium::WebDriver::Remote::Capabilities.chrome('chromeOptions' => {args: ["--headless","--no-sandbox", "--disable-setuid-sandbox", "--disable-gpu", "--user-agent=#{ua}", 'window-size=1280x800']})
driver = Selenium::WebDriver.for :chrome, desired_capabilities: caps
#googleのトップページに移動
driver.navigate.to "https://www.google.co.jp/"
#google検索フォームに値を入力
driver.execute_script("document.getElementById('lst-ib').value = '株式会社ルーター'")
#検索ボタンをクリック
driver.execute_script("document.getElementsByName('btnK')[0].click()")
3.times{|i|
get_title_text(driver)
driver.execute_script("document.getElementById('pnnext').click()")
sleep 2
}
get_title_text(driver)
end
end
Crawler.new.main
bundle installする
$ bundle install --path .bundle
クローラーの実行
$ bundle exec ruby google-crawler.rb
伝説の勇者の伝説 - Wikipedia
TVアニメ「伝説の勇者の伝説」公式サイト
伝説の勇者の伝説 | 富士見書房
伝説の勇者の伝説〈1〉昼寝王国の野望 (富士見ファンタジア文庫) | 鏡 貴也 ...
大伝説の勇者の伝説 (16) 昼寝男の結婚 (ファンタジア文庫) | 鏡 貴也 ...
大伝説の勇者の伝説17 団子娘の出す答え (ファンタジア文庫) | 鏡 貴也 ...
Amazon.co.jp: 伝説の勇者の伝説1 昼寝王国の野望 (富士見ファンタジア ...
伝説の勇者の伝説 - アニヲタWiki(仮) - アットウィキ
伝説の勇者の伝説 - アニメ視聴リンク集
・
・
・
上記のように、タイトルが取得できているでしょうか?
簡単な解説をします。
#googleのトップページに移動
driver.navigate.to "https://www.google.co.jp/"
#google検索フォームに値を入力
driver.execute_script("document.getElementById('lst-ib').value = '株式会社ルーター'")
#検索ボタンをクリック
driver.execute_script("document.getElementsByName('btnK')[0].click()")
ここでは、Googleのトップページに移動&検索を行なっています。 2行目は、seleniumのメソッドを用いてgoogleのトップページに移動してます。 4行目,6行目は、seleniumを通じてJacaScriptを実行しています。 ※JacaScriptの内容がわからない人は、今度書くJavaScriptの記事を読んでください。
#Nokogiriを用いてHTMLをパースする
doc = Nokogiri::HTML.parse(driver.page_source, nil, 'utf-8')
#ユーザー名を取得
doc.css('h3.r').each do |h3|
puts h3.text
end
ここでは、検索後のページ情報をパースして取得しています。 2行目は、HTMLのパースでおなじみのNokogiriを使用しています。今まではここに「open-uri」等で取得したHTMLを渡していたと思いますが、今回はchrome ヘッドレスが開いているページのHTMLを渡したいので、driver.page_sourceメソッドを用いています。 4行目〜6行目は、selenium関係なくNokogiriでHTMLのパースを行なっています。 ※seleniumにも、HTMLから特定の要素の取得ができますが、Nokogiriを使った方が比較的簡単に実装できます。
3.times{|i|
get_title_text(driver)
driver.execute_script("document.getElementById('pnnext').click()")
sleep 2
}
get_title_text(driver)
ここでは、ページングを行なっています。googleのサイトのhtmlコードを見ると、「次へ」というボタンはリンク要素になっています。そのため、これをクリックすることで次のページに移動することができます。 クリックをするにはJavaScriptを用います。
今回に限らずクローラーは相手のサーバーに対して負荷をかけてしまいます。 Googleの場合は、あまりクローリングしすぎるとブロックされ、しばらく情報が取得できなくなってしまいます。 クローラーを開発する際には、sleepを挟むこと、過度に取得しすぎないことは心に留めておきましょう。