Web::Scraperを使って、物件一覧をGoogle Mapsにマッピング
福岡ファミリー向け物件特集!: ファミリー物件を見ていて、これはいいな、RSS登録するか。
と思ったのですが、このRSSはどうやら福岡の不動産情報探し・お部屋探しサイト「ムビマップ福岡」:こだわりの物件特集[賃貸版]: 物件一覧のようで、僕にはいらん情報も混じっておりました。
で、話題のWeb::Scraperでスクレイピングしてみるか。ついでに取得した一覧はGoogle Mapsにマッピングしてやるか。
というエントリです。
http://fooo.name/ からURL一覧を取り出すのにWeb::Scraper使ったけど、これは良いね
scraper http://fooo.name/accounts/otsune
してsでソース見てそれっぽくXPath書いてdumpして、データが取れてたらcでソース出して終了。イカス。
を参考にさせてもらいました。
まずは、
$ scraper http://www.movimap.net/kodawariblog/family/
して
scraper> s
してソースをざーっと斜め読み。
取ってきたい情報のXPathを考える。
scraper> process '//div[@class="box"]/div[@class="box01"]/h3/a', 'link[]' => '@href', 'title[]' => 'TEXT'
これでどげんじゃろかと、出力してみる。
scraper> y
すると、
--- link: - !!perl/scalar:URI::http http://www.movimap.net/kodawariblog/2007/10/post_134.html - !!perl/scalar:URI::http http://www.movimap.net/kodawariblog/2007/08/post_33.html .... title: - +*。+純和風♪駅が近いので通勤・通学、奥様のショッピングにも便利なんデスヨ~(人・∀・*)+。*+ - ☆鴻巣山のふもとの静かな暮らし☆ ....
おし、これはおげ。
続いて住所情報が欲しいので、
scraper> process '//div[@class="box"]/div[@class="box02"]/p', 'address[]' => 'TEXT'
そして、
scraper> y
その結果が、
--- address: - '■□加藤邸(桜台) 福岡県筑紫野市桜台1丁目7-11 □■ +*○。+純和風のとても素敵なお家です!広さは4LDKと広々!駐車場も一台付いていまーす +。○*+ ' - ■□グレイス長丘 福岡市南区長丘5-8-18□■ ♪♪駐車場2台取れます♪♪ .... link: - !!perl/scalar:URI::http http://www.movimap.net/kodawariblog/2007/10/post_134.html - !!perl/scalar:URI::http http://www.movimap.net/kodawariblog/2007/08/post_33.html .... title: - +*。+純和風♪駅が近いので通勤・通学、奥様のショッピングにも便利なんデスヨ~(人・∀・*)+。*+ - ☆鴻巣山のふもとの静かな暮らし☆ ....
これで、address, title, linkとそれぞれの配列にデータが入った事を確認したところで、
scraper> c
とタイプすると、
#!/usr/local/bin/perl
use strict;
use Web::Scraper;
use URI;
my $uri = URI->new("http://www.movimap.net/kodawariblog/family/");
my $scraper = scraper {
process '//div[@class="box"]/div[@class="box02"]/p', 'address[]' => 'TEXT';
};
my $result = $scraper->scrape($uri);
とコードを自動生成してくれます!
でも、最初の方に設定したXPathが出てこないみたいなので、ひとまず、
scraper> process '//div[@class="box"]/div[@class="box02"]/p', 'address[]' => 'TEXT'; process '//div[@class="box"]/div[@class="box01"]/h3/a', 'link[]' => '@href', 'title[]' => 'TEXT';
scraper> c
#!/usr/local/bin/perl
use strict;
use Web::Scraper;
use URI;
my $uri = URI->new("http://www.movimap.net/kodawariblog/family/");
my $scraper = scraper {
process '//div[@class="box"]/div[@class="box02"]/p', 'address[]' => 'TEXT'; process '//div[@class="box"]/div[@class="box01"]/h3/a', 'link[]' => '@href', 'title[]' => 'TEXT';
};
my $result = $scraper->scrape($uri);
とやりました。
<追記:2007-11-15 09:01>
scraper> c all
とすれば良いだけでした。miyagawaさんありがとうございました!
<追記ここまで>
後はこの生成されたコードをコピペして、適当に配列をごにょごにょして、TTへ丸投げ。
movimap_scrape.pl
#!/usr/local/bin/perl
use strict;
use warnings;
use Web::Scraper;
use Data::Dumper;
use Template;
use URI;
my $uri = URI->new("http://www.movimap.net/kodawariblog/family/");
my $scraper = scraper {
process '//div[@class="box"]/div[@class="box01"]/h3/a',
'link[]' => '@href', 'title[]' => 'TEXT';
process '//div[@class="box"]/div[@class="box02"]/p',
'address[]' => 'TEXT';
};
my $result = $scraper->scrape($uri);
my @list;
for my $i ( 0 .. scalar @{$result->{"address"}} - 1 ){
my $data = $result->{"address"}->[$i];
$data =~ s/^x{25a0}x{25a1}.*?[ d]+(.+)?x{25a1}x{25a0}.+$/$1/;
push @list, {
address => $data,
link => $result->{"link"}->[$i],
title => $result->{"title"}->[$i],
};
}
my $tt = Template->new({
INCLUDE_PATH => ".", EVAL_PERL => 1
});
$tt->process("webscraper_googlemap.tt", { result => @list });
webscraper_googlemap.tt
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>scraper http://www.movimap.net/kodawariblog/family/</title>
<script src="http://maps.google.com/maps?file=api&v=2&key=***"
type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
var lat = 33.58981
var lng = 130.39878
var map = null;
var geocoder = null;
function load() {
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map"));
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(lat, lng), 12);
geocoder = new GClientGeocoder();
[% FOREACH item = result %]
geocoder.getLatLng(
"[% item.address %]",
function(point){
if (point){
var marker = new GMarker(point);
map.addOverlay(marker);
GEvent.addListener(marker, 'click', function() {
marker.openInfoWindowHtml("<h4><a href='[% item.link %]'>[% item.title %]</a></h4>");1
});
}
}
);
[% END %]
}
}
//]]>
</script>
</head>
<body onload="load()" onunload="GUnload()">
<div id="map" style="width: 80%; height: 400px"></div>
</body>
こんだけで簡単にGoogle Mapsへのマッピングが完了。
住所を抜き取る正規表現はかなりあやしいです。住所に何らかの定義をしてくれると助かるのだけどなぁ。
<追記:2007-11-15 19:18>
このへっぽこな正規表現の解決策をエントリしました。Geography::AddressExtract::Japanを使って住所抽出 jmalaさん、Yappoさんに感謝!
<追記ここまで>
出来上がったHTMLファイルはこんな感じ。
http://cgfm.jp/~cota/sandbox/webscraper_googlemap.html
僕もスクレイピング脳に少しだけ近づけた気がします。



