perlのWeb::Scraperみたいな記述で、ページの中からデータを取り出すwebscraper.jsという小さなjavascriptのライブラリに、要素をてきとうに渡したらてきとうにXPathを作って動いてくれるwebscraperp.jsというのを書きました。なんで最後にpをつけたかは思い出せません...
webscraperp.jsを読み込んでFirebugコンソールで使います。
はじめに店舗検索結果(住所・店名・条件から探す)を開いてブックマークレットでwebscraperp.jsをロードします。
つぎにFirebugのコマンドラインでWebScraperPのインスタンスを作ってaddFieldContainsTextで取り出したい項目が含んでいるテキストを指定していきます。

try {
var p = new WebScraperP(document);
p.addFieldContainsText( "銀座松屋通り店", "name" );
p.addFieldContainsText( "3-7-14", "address");
p.addFieldContainsText( "松屋デパートの裏", "station");
p.addFieldContainsText( "月〜木: 7:00 〜 22:30", "opentime");
p.scrape();
}
catch(e){console.log(e)}
指定されたテキストを含む要素のうち、一番はじめに出てくる要素を基準にしてXPathが作られて、そのXPathのデータを元にして前回作ったWeb::Scraperのjavascriptバージョンwebscraper.jsでページからデータが取り出すしくみになっています。

WebScraperPはaddFieldContainsTextされた要素をもとにてきとうなXPathを生成しているわけですが、そのXPathはgetWebScraperRule()で得らるので、これをJSONの文字列にして保存しておけば次回はWebScraperPなしでWebScraperにこのJSONを渡すことでデータを取り出すことができます。

Web::Scraperでするためのperlのコードを出力するメソッドもつけました。
try {
var p = new WebScraperP(document);
p.addFieldContainsText( "銀座松屋通り店", "name" );
p.addFieldContainsText( "3-7-14", "address");
p.addFieldContainsText( "松屋デパートの裏", "station");
p.addFieldContainsText( "月〜木: 7:00 〜 22:30", "opentime");
var code = p.getWebScraperPerlCode();
copy(code);
}
catch(e){console.log(e)}
取り出したい要素を追加したあとでgetWebScraperPerlCode()を呼ぶと
use URI;
use Web::Scraper;
my $scraper = scraper {
process '//div[contains(concat(" ",@class," "),concat(" ","Table01"," "))]',
'paragraphes[]' => scraper {
process '//strong',
'name' => 'TEXT';
process '//tr[2]//p',
'address' => 'TEXT';
process '//tr[4]//td[2]',
'station' => 'TEXT';
process '//tr[5]//p[1]',
'opentime' => 'TEXT';
};
};
my $result = $scraper->scrape( URI->new("http://www.starbucks.co.jp/search/result_store.php" ) );
こうなって帰ってくるのでそのままperlのスクリプトにはって使ってもいいです。
ほかはebay検索結果とYahoo!電話帳 検索結果でしか試していませんが、いい感じで動いています。
でもXPathを生成するときに、変化に対して強く、人間にとっての可読性が高いXPathを生成するのは困難です。XPathのロケーションステップごとに可読性の評価を行ってその和が小さい/大きいでXPathを生成する関数を作るのは楽ではありませんし、そもそも人間にとってどういう記述が読みやすいのかを定義するのはたいへんな作業になります。そうやって可読性の高いXPathを生成できるようになったとしても、そもそもターゲットにしているHTML自体にclassやidが設定されていないとやはりproximity positionを使ったXPathを生成することになります。
今回のように自動で生成したXPathをスクリプトに渡すときに、生成されたXPathに可読性が必要でしょうか。XPathの可読性は、それを人間が読んで編集、修正する可能性があるときには必要ですが、人間が編集することがなく、スクリプトがそれを評価するだけであれば必要ありません。生成されたXPathで生成されるデータが正しいものであることを確認できるようにテストを組み、テストが失敗したときにはXPathを生成するプログラムを修正し、正しいXPathを生成させるような体制があって人間がXPathを直接みる必要性をなくせばXPathに可読性がある必要はなくなります。
ちょうど、人間にとって理解しやすく表現力の高いプログラミング言語で記述した処理を、コンパイラが解釈して生成する機械語に可読性を求められないのと同様、XPathをとりまくまわりの環境が整っていれば自動生成されるXPathに可読性は必ずしも必要ないのかなと感じます。
トラックバック元エントリにこのエントリへのリンクがない場合はトラックバックを受け付けません。
http://labs.gmo.jp/mt/mt-tb.cgi/203
comments