2014年9月23日火曜日

Seleniumを利用してWEBの操作を自動化

※追記
Seleniumを直叩きするより、Capybaraを通して実行した方がいいかもしれない。
http://alpha-netzilla.blogspot.jp/2016/03/crawler.html



目的
Seleniumを利用してWEBのGUI操作(UI:User Interface部分)を自動化する。
※GUIでのオペレーションを自動化するためにSikuliも最近ではよく使われる。
ただし両者は実装も利用用途も異なるため使い道は見極める必要がある。



環境、事前準備
・ Rubyのインストール
今回はRubyからSeleniumを操作するため、Rubyを使えるようにしておくこと。

インストール後、windows環境であれば以下からパスを指定する。
コントールパネル ->
システムの詳細設定 ->
詳細設定 ->
環境変数 ->
ユーザの環境変数 ->
変数 ->
Path   C:\Users\user\Ruby**\bin


・ Selenium Webdriverのインストール
SeleniumのWebDriverをRubyへ組み込む。
gemを使ってパッケージングされたライブラリを入れてしまえばよい。
# gem install selenium-webdriver


・ Selenium IDE(Firefoxのプラグイン)のインストール
GUIでのマウス操作を記録させるために便利である。
Selenium IDEの項にダウンロードページがある。

ダウンロード後、Firefoxを起動させ、Selenium IDEをアドオンとしてインストールさせておく。


・ ChromeDriverのインストール
ChromeDriverとはwire protocolを実装したスタンドアローンサーバである。
Chromeがインストールされていないと利用できない。

ダウンロード元と、実行ファイルの置き場所は公式マニュアルを参照。


・ ヘッドレスブラウザの用意
ツールを実行すると指定したChromeなり、Firefoxのブラウザが立ち上がる。
ブラウザを立ち上げないで試験を実施する必要性が出る場合もあるだろう。
PhantomJSというヘッドレスブラウザを使えば、実ブラウザの立ち上げを回避できる。
WebKitをベースとしているため、実ブラウザと機能面でほぼ遜色はない。



事前知識
WEBの要素をたどり、それをコード化していくのだが、
HTML、XMLのデータツリーノードをどうやって調べればよいだろうか。

簡便な手段は大きく2通りある。

1. Firefoxのプラグインとして組み込んだ、Selenium IDEを使う方法
firefoxを起動
ツール ->
Launch Selenium Bulder ->
Selenium 2
※Record mouseoversのチェックは必要がなければ外しておく

操作が終われば、
Stop recording ->
File ->
Export ->
Ruby

これだけでRubyコードが生成される。


2. Chromeブラウザのデベロッパーツールの利用
特別なモジュールのインストールは不要である。

ブラウザ上で右クリック ->
要素を検証 ->
Elements内のコードをマウスでたどれば
WEB画面上の要素を網掛けしてくれる。

マウスで操作する要素のXPathを知りたければ、
コード上で右クリック ->
Copy XPath
で分かる。


1は楽だが複雑な操作をキャプチャする場合に痒いところに手が届きにくいところがある。
そういった場合に2の手順でHTMLを解析していく、という使い方がいいだろうか。



コード例
どのようにコードを記述するかは見てもらえればすぐにわかるだろう。
html(xml)を例示しながらそれを操作する方法を記載する。
### モジュール読み込み
require 'Rubygems'
require 'Selenium-webdriver'


### ブラウザ起動(3つ目は実ブラウザがなくても実行可能)
wd = Selenium::WebDriver.for :chrome
# wd = Selenium::WebDriver.for :firefox
# wd = Selenium::WebDriver.for :phantomjs


### URL参照(下記どちらでもよい)
wd.navigate.to "http://example.com/"
wd.get "http://example.com/"


### フォーム操作(選択、文字列のクリア、そして文字列入力)
# <input id="account" name='account' type='text'>account</input>
# <input id="password" name='password' type='text'>password</input>

wd.find_element(:id, "account").click
wd.find_element(:id, "account").clear
wd.find_element(:id, "account").send_keys("myaccount")
wd.find_element(:id, "password").click
wd.find_element(:id, "password").clear
wd.find_element(:id, "password").send_keys("mypassword")


#### リンク操作
## 要素(element)で指定する場合
# <div id="entrance">
#   <ul class="home">
#     <li><a href="/login">LOGIN</a></li>
#   </ul>
# </div>

wd.find_element(:link, 'LOGIN').click
# or 
wd.find_element(:link_text, 'LOGIN').click

## xpathで属性(attribute)を指定する場合
wd.find_element(:xpath, '//a[@href='/login']').click

## CSSセレクタで指定する場合
wd.find_element(:css, #entrance ul.home).click


### ファイルのアップロード
# <input type="file" name="data">
wd.find_element(:name, "data").send_keys("c:/hoge.txt")


### インラインフレームの切りかえ
# <iframe class="frame" src="/frame"></iframe>
wd.switch_to.frame(wd.find_element(:class,"frame"))


### ウインドウの切り替え
# <a href="new_window.html" target="_blank">new window</a>
wd.switch_to.window(wd.window_handles.last)


### ウインドウを閉鎖(ウインドウの操作権を先に戻しておく)
wd.switch_to.window(wd.window_handles.last)
execute_script("return window.close();")


### マウス移動
el = wd.find_element(:id, "some_id")
wd.action.move_to(el).perform


### クリック
el = wd.find_element(:id, "some_id")
wd.action.click(el).perform
# or
wd.action.double_click(el).perform


### ドラッグアンドドロップ
el1 = wd.find_element(:id, "some_id1")
el2 = wd.find_element(:id, "some_id2")
wd.action.drag_and_drop(el1, el2).perform


### 警告、案内等のポップアップダイアログへの対処
alert = wd.switch_to.alert()
alert.accept
# or 
alert.dismiss()


### 終了処理
wd.quit


参考
WebDriver: Advanced Usage