iwathiの/var/log

生活と仕事の効率化が趣味。

Javascript利用の動的なページのスクレイピング Ruby + Selenium

Type

ズボラな人にとってはおなじみ

自働化に便利なWebスクレイピングのやり方の備忘録

Webスクレイピングとは

Webページの情報を抜き出すことをスクレイピングという

Webスクレイピング

Webスクレイピングとは、WebサイトからWebページのHTMLデータを収集して、特定のデータを抽出、整形し直すことである。 なお、「スクレイピング」(scraping)とは元々「削る」や「こすり落とす」といった意味の英語である。

(Webスクレイピングとは (Web scraping) ウェブスクレイピング: - IT用語辞典バイナリ)

定期的に情報が更新されるのを自分で見に行かなくても情報を拾ってくれるので便利 PerlとかPythonとかRubyとかのスクリプト言語を使っている人にとってはおなじみかと

更にURL入れるだけでスクレイピングしてくれるサービスまであるみたい
nelog.jp

便利な世の中だなー

Webスクレイピングでやりたいこと

けど、どこかにログインして情報を取得したいってときにはちょっと使えなそう

できたとしてもユーザIDとかパスワードとかを他のサービスに保管しとくって怖いし

ということで

Webスクレイピングで行いたいことをまとめると

  1. ログインページへのログイン

  2. JavaScript利用のページからデータを取得

  3. ログイン先での操作

実装

技術選択

言語

今年はRubyを勉強するときめているのでRuby

ライブラリ

スクレイピングするためのメジャーな方法はNokogiriを使うこと

morizyun.github.io

ただ今回の必要要件として「JavaScript利用のページからデータを取得」があるので

Nokogiriだと難しそう(できないことはない?)

Perlとかの場合でもMechanizeだと難しそう

qiita.com

なので今回はSeleniumを使って実現していく

下記を参考にさせていただきましたー

qiita.com

実行環境

ライブラリのインストールは下記をするだけ

gem install selenium-webdriver

後はコード内からrequire 'selenium-webdriver'してあげればOK

ログインページへのログイン

ログインの流れとしては

  1. Seleniumの起動
  2. ログインするページへアクセス
  3. ログインするページのユーザ・パスワード部分に情報を入力
  4. ログインボタンを押す

これを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とかに変更する

driver = Selenium::WebDriver.for :firefox

ログインするページへアクセス

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に保管してグラフ化するとか やると情報の見える化ができて便利だったりすると思う

とりあえず以上