【Perl】WWW::Mechanize と Web::Scraper で PASMO の利用履歴を得る(その2)


【Perl】WWW::Mechanize と Web::Scraper で PASMO の利用履歴を得る(その1)
http://blog.remora.cx/2010/10/get-pasmo-history-with-perl.html

前回に引き続き、ページの解析を行う。まずは Firebug をインストールしておこう。

Firebug :: Add-ons for Firefox
https://addons.mozilla.org/ja/firefox/addon/1843/

Firebug で確認

101002-0001.png

前回得られたページを sample.html と言うファイル名で保存しているとする。このページを Firefox で開いて中身を確認する(以下の SS のページはすべてサンプルファイルのものである。)



101010-0001.png

“SF 残額履歴”欄の適当な行を右クリックして“要素を調査”をクリックすると、該当する場所が Firebug で表示される。



101002-0004.png

図にあるように <tr> タグに該当する部分を右クリックし“XPath をコピー”を選ぶと、目的の項目を表す XPath が得られる。


この例ではこのとき、クリップボードに以下のものが入っているはずだ。

/html/body/form/table[2]/tbody/tr[13]/td/table/tbody/tr[4]

scraper コマンドで確認

以下の記述は次のサイトを参考にした。

use Web::Scraper; – 今日のCPANモジュール
http://e8y.net/mag/013-web-scraper/

Web::Scraper モジュールをインストールすると、scraper と言うコマンドラインユーティリティが一緒にインストールされる。これはコマンドラインから対話的に Web::Scraper の試験ができる優れものだ。プロンプトから次のように入力して起動する。

$ scraper sample.html
scraper>

前節でコピーした XPath 式を使って次のように入力する。

scraper> process '/html/body/form/table[2]/tbody/tr[13]/td/table/tbody/tr[4]', WARN
scraper>

これは、読み込んだ HTML を指定した XPath 式で解析し、該当するタグを表示する命令だ。しかし、このときは何も表示されないだろう。なぜなら、XPath 式に含まれる“<tbody>”タグは Firefox が勝手に挿入したものなのだ。ちょっといじってもう一度実行する。

scraper> process '/html/body/form/table[2]/tr[13]/td/table/tr[4]', WARN
<tr bgcolor="#D0D0D0"><td>0930</td><td>バス</td><td>横浜市B</td><td> </td><td></td><td align="right">**30</td></tr>
scraper>

今度はきちんと表示された。この後に何度も試して、なるべく簡便な XPath 式になるようにしてみる。

scraper> process '//tr[@bgcolor="#D0D0D0"]', WARN
<tr bgcolor="#D0D0D0"><td>0930</td><td>バス</td><td>横浜市B</td><td> </td><td></td><td align="right">**30</td></tr>
<tr bgcolor="#D0D0D0"><td>0925</td><td>入</td><td>横浜</td><td>出</td><td>新横浜</td><td align="right">*560</td></tr>
<tr bgcolor="#D0D0D0"><td>0920</td><td>現金</td><td>横浜</td><td> </td><td></td><td align="right">1000</td></tr>
scraper>

該当する <tr> タグには必ず“bgcolor="#D0D0D0"”という属性がついているのでここまで簡単にできた。

process 関数の最後に付いている“WARN”は、実際のスクリプトでは使えない。結果を変数に収納して後から使えるようにする(process 関数の詳しい書式については後述)。

scraper> process '//tr[@bgcolor="#D0D0D0"]', 'items[]' => "HTML"
scraper>

c”コマンドをタイプすると、最後に実行した process コマンドを使った Perl スクリプトが表示される。これをファイルに保存しておこう。

scraper> c
ここにコードが表示される
scraper>
#!/opt/local/bin/perl
use strict;
use Web::Scraper;
use URI;
my $file = \do { my $file = "sample.html"; open my $fh, $file or die "$file: $!"; join '', <$fh> };
my $scraper = scraper {
process '//tr[@bgcolor="#D0D0D0"]', 'items[]' => "HTML";
};
my $result = $scraper->scrape($file);
use YAML; print Dump $result;
$ perl sample.pl
---items:
- '<td>0930</td><td>バス</td><td>横浜市B</td><td> </td><td></td><td align="right">**30</td>'
- '<td>0925</td><td>入</td><td>横浜</td><td>出</td><td>新横浜</td><td align="right">*560</td>'
- '<td>0920</td><td>現金</td><td>横浜</td><td> </td><td></td><td align="right">1000</td>'

scraper 関数の詳細

Web::Scraper によるスクレイピングは次のようにして行う。

my $result = scraper {
process <CSS式 or XPath式>, '保存先のキー名' => '保存形式';
}->scrape( 解析するHTML );

'保存形式' には次のものを指定できる。

TEXT
該当するタグに含まれるテキストだけを吐く。通常はこれを使う。
HTML
該当するタグの HTML コードを丸ごと吐く。
@属性名
該当するタグの指定された属性値を吐く。
サブルーチンリファレンス
該当するタグの HTML::Element オブジェクトインスタンスを引数に与えて実行される。
scrape コマンド
scrape した結果を更に scrape する。

最後の項目が重要だ。今回は一度目の scrape で得られた以下の結果について、更に <td> タグの中身を配列で得たい。

<tr bgcolor="#D0D0D0"><td>0930</td><td>バス</td><td>横浜市B</td><td> </td><td></td><td align="right">**30</td></tr>
<tr bgcolor="#D0D0D0"><td>0925</td><td>入</td><td>横浜</td><td>出</td><td>新横浜</td><td align="right">*560</td></tr>
<tr bgcolor="#D0D0D0"><td>0920</td><td>現金</td><td>横浜</td><td> </td><td></td><td align="right">1000</td></tr>

次回は scraper コマンドを入れ子にすることでこれを解決しよう。(続く)

コメントを残す