perlでWebクライアント (3) Seleniumを使う
前回の続きです。
前回はWWW::Mechanizeの使用を試みましたが、
色々と調べた結果、ボタンがJavaScriptになっているものは
JavaScript部分を自分で実装する必要があり、
難易度が高く挫折してしまう人が多いとのことでした。
自分はWebの知識がほとんどないので、これに代わる簡単な方法はないものかと
探していたところ見つけたのが、SeleniumというWebテストツールを使う方法でした。
PerlにはTest::WWW::Seleniumというモジュールがあるので、これを使えばいけそうですね。
SeleniumはもともとWebアプリケーションのテストを自動的に行うもので、
例えば・・・
1.テキストボックスに数値を入れてボタンを押す。 2.遷移したページで「このボタンをクリック」というリンクを探してクリックする 3.遷移先は1.で入れた値を計算して表示するページ。そのページに正しい値が表示されているかチェックする
といったことが可能です。
今回自分がやりたいことは
1.フォームにIDとパスワードを入れる 2.ボタン(JavaScriptで実行されるもの。今回の最大の敵)を押す 3.遷移先のページにあるテキストボックスに単語を入力 4.検索ボタンを押す 5.画面に出力された結果から必要な情報を取り出しcsvとかで出力
というものです。どうでしょう、Seleniumを使えばなんとなくできそうですね。
それではさっそくSeleniumを導入してみましょう。
プラットフォームはWindowsです。
Seleniumを使用するための構成は以下の図のようになります。
各アプリケーションのバージョン
当方のバージョンを書いておきます。すべてWindowsです。
Firefox | 15.0.1 |
Selenium IDE | 1.7.3 |
Selenium IDE:Perl Formatter | 1.0.3 |
Selenium RC | 2.25.0 |
JDK | 1.6.0_23 |
Firebug | 1.10.3 |
Firefox周りのインストール
FirefoxとFirefoxのアドオンSelenium IDEとPerl Formatterをインストールしてください。
http://www.mozilla.jp/firefox/
Selenium IDEはFirefoxで行った一連の操作(テストケースと呼びます)の
記録、編集、デバッグを行うことができます。
Perl FormatterはSelenium IDEのテストケースをPerlのスクリプトとして出力するものです。
このスクリプトを実行すればSelenium IDEのテストが実行されるというわけです。
Selenium RCのインストール
Selenium RCはテストをするホストで動作します。
テストケースが始まるとIE、Firefox、chromeなどのブラウザを起動してテストを実施します。
Selenium RCが任意のブラウザをキックできるので、1つテストケースを用意
すれば様々なブラウザでテストすることが可能となります。
selenium RCはJavaで動作しますので、先にJavaを入れておいてください。
入れるのはJREではなく、JDKですよ。
http://www.oracle.com/technetwork/java/javase/downloads/jdk7u7-downloads-1836413.html
続いてSelenium RCをダウンロードして任意のディレクトリ配置してください。
http://seleniumhq.org/download/
Selenium RCを起動しましょう。
C:\tempにjarファイルをダウンロードしたとすると
java -jar "C:\temp\selenium-server-standalone-2.25.0.jar" -interactive
と、コマンドプロンプトから実行してサーバを起動してください。
以下のように出力されるはずです。ポート4444でサーバ起動したことがわかりますね。
ファイアウォールは通しておいてください。
2012/09/19 21:21:59 org.openqa.grid.selenium.GridLauncher main 情報: Launching a standalone server 21:21:59.343 INFO - Java: Sun Microsystems Inc. 19.0-b09 : 21:21:59.546 INFO - Started SocketListener on 0.0.0.0:4444 21:21:59.546 INFO - Started org.openqa.jetty.jetty.Server@14a9972 Entering interactive mode... type Selenium commands here (e.g: cmd=open&1=http://www.yahoo.com)
環境変数PATHにFirefoxのモジュールがある場所を通す
Firefoxが以下のようにインストールされている場合
C:\Program Files\Mozilla Firefox\firefox.exe
環境変数PATHには以下を追加します。
C:\Program Files\Mozilla Firefox
Webページの構成
次に、対象となるWebページの構成を見てみましょう。
Webページの情報はFirefoxのアドオンFirebug等で調査しています。
ログインページは以下のようになっています。
IDとパスワードを入力してログインボタンを押下します。
やってみよう
PerlのSeleniumモジュールと通して上述した処理を自動化します。
商品名には「ピアノ教本」と入れて検索をしています。
まずはSelenium IDEを使用して、Seleniumに与える指示内容を作成しましょう。
ログインページに移動してSelenium IDEを起動してください。
Firefoxの[ツール]→[Selenium IDE]
Selenium IDEが起動すると、ブラウザ上で行った操作が自動的に
記録されていくはずです。当方の環境で、上で説明した操作を行った結果は以下のようになります。
なぜか、IDとパスワードの入力については反応してくれませんでした。。。
が、出力したPerlスクリプトにIDとパスワードを入力するコードを追加
すればいいので特に問題はないでしょう。
Perlコードは以下のように辿って出力してください。
Selenium IDEの[ファイル]→[テストケースをエクスポート]→[Perl]
出力されたコードです。
use strict; use warnings; use Time::HiRes qw(sleep); use Test::WWW::Selenium; use Test::More "no_plan"; use Test::Exception; my $sel = Test::WWW::Selenium->new( host => "localhost", port => 4444, browser => "*chrome", browser_url => "http://www.sample.com/" ); $sel->click_ok("id=LoginBtn"); $sel->wait_for_page_to_load_ok("30000"); $sel->type_ok("id=SearchWord", "ピアノ教本"); $sel->click_ok("name=SearchSubmit"); $sel->wait_for_page_to_load_ok("30000");
ここにIDとパスワードを入力するコードを加えましょう。
IDを「taiyaki」、パスワードを「hogehogepass」とします。
またchromeもfirefoxに変えときましょう。(これは変えなくてもいいのかな?)
変更後のコードは以下のようになります。
use strict; use warnings; use Time::HiRes qw(sleep); use Test::WWW::Selenium; use Test::More "no_plan"; use Test::Exception; my $sel = Test::WWW::Selenium->new( host => "localhost", port => 4444, browser => "*firefox", browser_url => "http://www.sample.com/" ); $sel->type_ok("id=LoginID", "taiyaki"); $sel->type_ok("id=LoginPasswd", "hogehogepass"); $sel->click_ok("id=LoginBtn"); $sel->wait_for_page_to_load_ok("30000"); $sel->type_ok("id=SearchWord", "ピアノ教本"); $sel->click_ok("name=SearchSubmit"); $sel->wait_for_page_to_load_ok("30000");
このperlスクリプトをファイルに出力して実行すれば、
自動的にFirefoxが起動し、IDとパスワードが入力され、
次々とページが遷移していくでしょう。
このコードだけだと、検索結果が表示された直後にFirefoxがkillされてしまいます。
必要に応じて以下のコードでページ情報を取得してファイル出力するなどの処理を追加してくださいね。
@html = $sel->get_body_text();
また毎回Firefoxを起動/killするのが嫌だという人は
ログインするコードの後をwhile文などで囲って定期的に
検索→結果取得を繰り返すようにしましょう。
コードとしては以下のようになるでしょうか。
ここでは検索ページのURLを「http://www.sample.com/search」としています。
use strict; use warnings; use Time::HiRes qw(sleep); use Test::WWW::Selenium; use Test::More "no_plan"; use Test::Exception; my $sel = Test::WWW::Selenium->new( host => "localhost", port => 4444, browser => "*firefox", browser_url => "http://www.sample.com/" ); $sel->type_ok("id=LoginID", "taiyaki"); $sel->type_ok("id=LoginPasswd", "hogehogepass"); $sel->click_ok("id=LoginBtn"); $sel->wait_for_page_to_load_ok("30000"); while(1) { $sel->type_ok("id=SearchWord", "ピアノ教本"); $sel->click_ok("name=SearchSubmit"); $sel->wait_for_page_to_load_ok("30000"); # ここで情報を取得してファイルに追記 my @html = $sel->get_body_text(); # ページを検索ページに戻しておく $sel->open_ok( "/search" ); # 1時間後に検索 sleep( 3600 ); }
あまりエラーケースが考えられていませんが、
とりあえず動作させるだけならこれで十分だと思います。
自分もまだわからない部分が多いのですが、また機会をみていろいろと紹介したいと思います。
参考ページ
世界一わかりやすい Selenium IDE 入門
http://d.hatena.ne.jp/rti7743/20090913/
日常茶飯事
http://mity.blog85.fc2.com/blog-entry-345.html
はたけアーカイブ mechanizeに変わる方法を考えてみた
http://hatakazu.hatenablog.com/entry/2012/06/10/083928
Selenium IDE: Perl Formatter
https://addons.mozilla.org/ja/firefox/addon/selenium-ide-perl-formatter/
Test::WWW::Selenium
http://search.cpan.org/~lukec/Test-WWW-Selenium-1.13/lib/WWW/Selenium.pm