Ruby + SeleniumでヘッドレスChromeを動かしてWEBページをスクレイピングする

yahoo_store_apiという自作gemがありまして、認証の際にリフレッシュトークンを発行してくれるのですが、このリフレッシュトークンがすぐに期限が切れる……。

期限が切れると毎回、

  • Yahooアカウントでログインして
  • 認証コードを発行して
  • コード上でイニシャライズして
  • リフレッシュトークンを発行して
  • それを変数もしくは環境変数に代入して

といった作業が発生します😢

コード上の作業はともかく、毎回ブラウザからログインして認証コードをコピペしてとか面倒なので、RubyでSelenium Webdriver + ヘッドレスChromeを使って自動化してみました。

📝 環境

  • MacOS High Sierra 10.13.2
  • ruby 2.5.0
  • chrome 64.0
  • chromedriver 2.35
  • selenium 3.9.0

※ちなみにkeyやidなどは環境変数(dotenv)でマスクしてありますので、適宜読み替えしてくださいませ。

🔪 下準備

まず、ヘッドレスChromeを使うので、Chromeが必要です。https://www.google.co.jp/chrome/index.htmlからダウンロードしておきます。

あとドライバーを入れておく必要があるので、brewでサクっとインストール。

$ brew install chromedriver

あとは適当にプロジェクトディレクトリでgem i bundler && bundle initでもすれば準備完了です。

🚗 実際に動くコードをかく

必要なgemをインストールします。

gem 'selenium-webdriver'
gem 'chromedriver-helper'

bundle installしたら、さっそくseleniumとchromeの初期設定を書きます。

options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('--headless')
driver = Selenium::WebDriver.for :chrome, options: options

これだけで自由にページの移動や入力、クリックなどができるようになります。

試しにGoogleにアクセスし、スクリーンショットを撮ってみます。

driver.navigate.to 'https://www.google.co.jp/'
driver.save_screenshot './google.png'

無事にいけました🎉

入力してクリックして認証させてみる

目的のYahooの認証とコードの取得をします。urlの準備をし、実際に繋いでみてスクリーンショットを撮ります。

yahoo_application_id = ENV['YAHOO_APPLICATION_ID']
YAHOO_AUTH_URL = "https://auth.login.yahoo.co.jp/yconnect/v1/authorization?response_type=code+id_token&client_id=#{yahoo_application_id}&state=foobar&redirect_uri=oob&nonce=hogehoge"
driver.navigate.to YAHOO_AUTH_URL
driver.save_screenshot './yahoo-1.png'

いけてますね。なので、次はIDを入力します。

IDの入力先などを調べる時は、ChromeのWEBデベロッパーツールのDOMインスペクターなどで該当のinput要素を調べてみます。

すると、<input type="text" name="login" id="username" value="" spellcheck="false" class=" hasBtnClear" data-rapid_p="1">と、name属性がloginという事が分かりました。あとついでに「次へ」ボタンも同様にDOMインスペクターでname属性などを調べておきます。

調べたinputに入力し、buttonをクリックするコードを書きます。

element = driver.find_element(:name, 'login')
element.send_keys(ENV['YAHOO_USER_ID'])
driver.find_element(:name, 'btnNext').click
driver.save_screenshot './yahoo-2.png'

いい感じです😄

パスワードも入力し、ログインします。

element = driver.find_element(:name, 'passwd')
element.send_keys(ENV['YAHOO_USER_PASSWORD'])
driver.find_element(:name, 'btnSubmit').click
driver.save_screenshot './yahoo-3.png'

すると、認証コードが表示されました。

最後にこの表示されているエレメントの中身を取得します。

code = driver.find_element(:class, 'dispCode').text

こんな感じでブラウザの自動化とWEBスクレイピングを書いてみました。昔はPhantomJSとかで不安定だったり設定がたくさんあったりで大変でしたが、今は安定してるしスクリーンショットも楽に取れるし便利になりました👏

今回書いたコードをGitHub(t4traw/selenium_chrome_sample)にpushしておきます。よかったら参考にしてみてください。

それでは。