マッシュアップ日記(4) Smatchの結果をGoogleMapsにプロット
大井宏友です。
マッシュアップ日記の4回目は、Smatch WEBサービスと地図をMash Upしてみようと思います。Smatch WEBサービスは緯度経度を返してくれませんが、大まかな住所は返してくれるので、それを使って地図上にプロットします。
そのまえに…
Smatch WEBサービスがバージョンアップ!
7月7日付でSmatch物件検索WEBサービスのバージョン2がリリースされました。 Version1との違いは
- 結果がRSSではなく、(オリジナルの)XMLになった。
- クエリーの文字コードでUTF8も使えるようになった(Version1でも使えます)
といったところのようです。結果がXMLになり、詳細ページへのURLや画像URLが加わり、
さらに価格や間取りなども独立したタグで返ってくるようになりました。RSSではなかなかやりようがなかったので、
(リクルートらしからぬ)すばやい対応に感謝したいです。
Smatch WEBサービスの詳細は公式サイトをご確認ください。
サンプルサイト
こちらをご覧ください。
http://tatamilab.jp/~ooi1/GoogleSample4.html
このサンプルは、ページ上部のプルダウンメニューで選択した条件でSmatch物件検索WEBサービスを実行して、 その結果をGoogle Mapsに表示します。
仕組み
- プルダウンメニューの値をAjaxでサーバ側CGIに投げる。
- 「東京都」というクエリー、検索結果は最大50件としてSmatchWEBサービスを実行。
- 実行結果の<title>のうち、一番右側の文字列を住所とみなし、Geocoderで住所から緯度経度を取得。
- JSONでJavaScriptに返す。
- JSONを解釈して地図上にGMarkerを追加していく
Smatchの物件検索ではかなりたくさんの結果が取得できるのですが、 それを全てMapにプロットするとブラウザが落ちてしまうため、CGI側で50件という制限をしています。また、 Smatch物件検索では地域を指定することはできないので、代わりに検索クエリーとして「東京都」を指定しています。 そのため検索結果を見るとたまに東京都以外の物件が含まれることもあるのですが、今回は仕方がないとしました。
Geocoderは、CSISシンプルジオコーディング実験を利用しています。 すばらしい機能を公開していただいて非常に感謝しております。
サーバ側の処理
#!/usr/bin/perl
#
#Smatch Webサービスを利用して情報を取得するサンプル
#XMLをJSONに変換
#Geocoderで住所から緯度経度取得
#
#大井宏友@たたみラボ
#2006/07/10 初版
#使用するPerlモジュール
use strict;
use utf8;
use LWP::Simple;
use XML::Simple;
$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
use JSON;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
#結果の入れ物を用意。
my $results = [];
#GEOCODERを定義
my $baseUrl = 'http://geocode.csis.u-tokyo.ac.jp/cgi-bin/simple_geocode.cgi?';
my $fixParm = '&charset=UTF8';
#GETパラメータを取得
my $q = new CGI;
my $se = $q->param('SE');
my $kamin = $q->param('KAMIN');
my $kamax = $q->param('KAMAX');
my $getparam = '&SE=' . $se . '&KAMIN=' . $kamin . '&KAMAX=' . $kamax;
#SmatchWEBサービス呼ぶ
my $pref = "東京都";
my $query = &urlencode($pref);
my $ws_url = 'http://search.smatch.jp/smatch/getBukkenInfo_utf8.do?CNT=50&KM=0&V=2&QUERY=' . $query . $getparam;
my $fa_res = get($ws_url);#WEBサービスをリクエスト
#結果を分解
my $xmlsimple = XML::Simple->new();
my $sm_results = $xmlsimple->XMLin($fa_res, ForceArray => ['item']);
if($sm_results->{resultset}){
foreach my $offer (@{$sm_results->{resultset}{item}}){
#titleの末尾が住所だとする
$offer->{title} =~ /|(.+)/;
my @title = split(/ +/, $1);
my $address = $title[@title - 1];
#Geocoderで緯度経度を取得
my $addressQuery = &urlencode($address);#住所の文字列をURLエンコード
my $res = get($baseUrl."addr=".$addressQuery.$fixParm."&series=ADDRESS");#Geocoderを呼ぶ
#返ってきたXMLをパース
my $resXML = XML::Simple->new->XMLin($res, ForceArray => ['candidate']);
if($resXML->{candidate}){
#緯度経度が返ってきたときだけ結果を処理する
$offer->{address} = $address;
my $firstCand = $resXML->{candidate}[0];#緯度経度が複数返ってくるときがあるが、最初のだけ使う
$offer->{lat} = $firstCand->{latitude};
$offer->{lon} = $firstCand->{longitude};
#結果用配列に追加
push(@{$results}, $offer);
}
}
}
#結果をJsonで返す
my $resJs = objToJson($results);
utf8::encode($resJs);
print "Content-Type: text/javascript; charset=utf-8\n\n";
print $resJs."\n";
#urlエンコード
sub urlencode {
my($str) = @_;
utf8::encode(($str));
$str =~ s/(\W)/'%'.unpack("H2", $1)/ego;
$str =~ tr/ /+/;
return $str;
}
JavaScript側の処理
Ajaxリクエストの部分でgetパラメーターを渡している箇所や、 Ajaxでサーバ側処理が終わるまで処理中のアニメGIFを表示するところ以外は、フロムエーのときとほぼ同じです。 詳細はソースをご覧ください。

