Javascript利用の動的なページのスクレイピング Ruby + Selenium
ズボラな人にとってはおなじみ
Webスクレイピングとは
Webページの情報を抜き出すことをスクレイピングという
Webスクレイピング
Webスクレイピングとは、WebサイトからWebページのHTMLデータを収集して、特定のデータを抽出、整形し直すことである。 なお、「スクレイピング」(scraping)とは元々「削る」や「こすり落とす」といった意味の英語である。
定期的に情報が更新されるのを自分で見に行かなくても情報を拾ってくれるので便利 PerlとかPythonとかRubyとかのスクリプト言語を使っている人にとってはおなじみかと
更にURL入れるだけでスクレイピングしてくれるサービスまであるみたい
nelog.jp
便利な世の中だなー
Webスクレイピングでやりたいこと
けど、どこかにログインして情報を取得したいってときにはちょっと使えなそう
できたとしてもユーザIDとかパスワードとかを他のサービスに保管しとくって怖いし
ということで
Webスクレイピングで行いたいことをまとめると
ログインページへのログイン
JavaScript利用のページからデータを取得
ログイン先での操作
実装
技術選択
言語
ライブラリ
スクレイピングするためのメジャーな方法はNokogiriを使うこと
ただ今回の必要要件として「JavaScript利用のページからデータを取得」があるので
Nokogiriだと難しそう(できないことはない?)
Perlとかの場合でもMechanizeだと難しそう
なので今回はSeleniumを使って実現していく
下記を参考にさせていただきましたー
実行環境
ライブラリのインストールは下記をするだけ
gem install selenium-webdriver
後はコード内からrequire 'selenium-webdriver'してあげればOK
ログインページへのログイン
ログインの流れとしては
- Seleniumの起動
- ログインするページへアクセス
- ログインするページのユーザ・パスワード部分に情報を入力
- ログインボタンを押す
これをSeleniumでコードにおこすとこんな感じ
require 'selenium-webdriver' require 'net/http' require 'uri' id = 'YOUR ID' password = 'YOUR PASSWORD' URL='YOUR TARGET URL' driver = Selenium::WebDriver.for :firefox driver.navigate.to URL driver.manage.timeouts.implicit_wait = 30 driver.find_element(:name, 'login_id').send_keys(id) driver.find_element(:name, 'password').send_keys(password) sleep(5) driver.find_element(:css, "td.id > form > input[type=\"image\"]").click driver.switch_to.frame("setting_window") sleep(10) INFORMATION = driver.find_element(:xpath, "//table[2]/tbody/tr[2]/td[1]").text puts INFORMATION driver.quit
Seleniumの起動
ここでブラウザを選んだりできる firefoxを使ってるのであればこのまま Chromeだったら:chromeとかに変更する
ログインするページへアクセス
navidate.toで指定のURLへアクセスをしてくれる
driver.navigate.to URL
driver.manage.timeouts.implicit_wait = 30
ログインするページのユーザ・パスワード部分に情報を入力
下記のフォーマットでDOMから情報を取得する
find_element(指定方法, 指定名)
指定方法
id, name, class 等を指定
指定名
要素の名前を指定
基本的にこの関数を使ってアクションを起こしたい要素を選択し アクションを指定していく
なので「文字列を入力する」アクションをする場合 下記の関数を使用する
send_keys(文字列)
なので例えば
<input class="login_text" name="login_id" >
というところからに文字列を入力したい場合
driver.find_element(:name, 'login_id').send_keys(id)
パスワードも同じ
driver.find_element(:name, 'password').send_keys(password)
ログインボタンを押す
ログインボタンを押す場合も 要素を選択して アクションを指定
今回はClickというアクションを指定
driver.find_element(:css, "td.id > form > input[type=\"image\"]").click
ログイン先での操作
フレームを変更する場合は以下の関数を使用
switch_to.frame(フレーム名)
driver.switch_to.frame("setting_window")
またリンクをClickするといった動作は ログインボタンを押すのと一緒でclickを使用することで実現可能
JavaScript利用のページからデータを取得
JavaScript利用のページだと若干待つ必要がある場合もあるので 急ぎでなければSleep()とかで待ってあげるといいと思うその後 要素を選択して、情報を取得する
情報を取得する場合も基本的に選択方法は一緒 ただid, nameとかで一意に選択は 指定方法を:xpathにして指定名をフルパスで指定する必要がある
情報の取得はtextを使用
INFORMATION = driver.find_element(:xpath, "//table[2]/tbody/tr[2]/td[1]").text
後は普通にputsとかで表示可能
puts INFORMATION
$ 123456
Seleniumの終了
動作が終わったらseleniumを終了する
driver.quit
ざっくりとはこんな感じ 使い方は簡単なので色々と自働化するのに便利 抜いた情報をThingSpeakに保管してグラフ化するとか やると情報の見える化ができて便利だったりすると思う
とりあえず以上