西松屋を探せ! python+googlemap

先日、ちょっと札幌に行ってきました。
少し時間があったので、嫁が行きたいと言ってた西松屋に行くことにしました。
しかし、札幌の地理がよくわからないので、西松屋店舗案内をみても、どこが近いのかよくわからないのです。

じゃぁ、グーグルマップにマーカーたてちゃおう!

もちろんpythonから。

1.データの準備

lxml・・・ほどのものはないので、ブラウザからコピペして、名前、住所、他を抽出します。

[text]
旭川永山店 旭川市永山二条4丁目1-20 (0166)46-2832 AM10:00~PM8:00

[/text]

こんなのが沢山ある感じ。
これを適当にsplitして住所を触れるようにする。

2.google maps api

 次に、google maps api web serviceを使って緯度経度を取得する。
 こんな感じでアクセスするとjsonで位置情報を返してくれる。

[text]
http://maps.googleapis.com/maps/api/geocode/json?address=%E5%8C%97%E6%B5%B7%E9%81%93&sensor=false&language=ja
[/text]

[text]
{
"results" : [
{
"address_components" : [
{
"long_name" : "北海道",
"short_name" : "北海道",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "日本",
"short_name" : "JP",
"types" : [ "country", "political" ]
}
],
"formatted_address" : "日本, 北海道",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 45.52302160,
"lng" : 146.36840770
},
"southwest" : {
"lat" : 41.35212590,
"lng" : 139.33429950
}
},
"location" : {
"lat" : 43.06461470000001,
"lng" : 141.34680740
},
"location_type" : "APPROXIMATE",
"viewport" : {
"northeast" : {
"lat" : 45.11592539999999,
"lng" : 145.44470790
},
"southwest" : {
"lat" : 40.94229570,
"lng" : 137.24890690
}
}
},
"types" : [ "administrative_area_level_1", "political" ]
}
],
"status" : "OK"
}
[/text]

というわけで、これを使って1のデータの住所から緯度経度を取得しまくる。

3.HTML出力。テンプレートを使ってみる jinja2

Flaskなどで使われているテンプレートエンジン jinja2 を使って、2で取得した緯度経度を出力します。

tmpl.html
[html]
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3&sensor=false"></script>
<script type="text/javascript">

var map;
var g_infowindow = null;
var markers = new Array(
{% for item in items %}
{ name: "{{item.name}}",
latlng: new google.maps.LatLng({{item.lat}}, {{item.lng}}),
content: "{{item.content}}"
}{{ "," if not loop.last }}
{% endfor %}
);

function initialize() {
if (markers.length == 0){
return false;
}

var myOptions = {
zoom: 10,
center: markers[0]["latlng"],
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

for (i=0; i<markers.length; i++){ 
make_marker(map,
markers[i]["name"],
markers[i]["latlng"],
markers[i]["content"]
);
}

}

function make_marker(map, name, latlng, content){
var marker = new google.maps.Marker({
position:latlng,
map:map,
title:name,
draggable:false
});

var infowindow = new google.maps.InfoWindow({
content: content
});

google.maps.event.addListener(marker, ‘click’, function(event){
if (g_infowindow) g_infowindow.close()
infowindow.open(map, marker);
g_infowindow = infowindow;
});
}
</script>

</head>
<body onload="initialize()">
  <div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>

[/html]

このhtmlファイルのテンプレートの部分はmarkersの宣言だけです・・・。
テンプレート使う意味はほぼありませんが、Flaskなしでjinja2を使ってみたかったんです。

このテンプレートを使う処理は以下のような感じです。

[python]
from jinja2 import Template

# data にデータのリストがあるとする。

# テンプレートを読み込む
with open("tmpl.html", "r") as f:
template = Template(f.read().decode(‘utf-8’))

# テンプレート変数を使って描画
html = template.render(items=data)

# できあがったhtmlを書き込み。
with open("output.html", "w") as f:
f.write(html.encode(‘utf-8’))
[/python]

別のgoogle maps apiを使う方法

 google maps api web serviceを使わなくても、google.maps.Geocoderを使えばjavascriptで住所から緯度経度を取得できます。

[javascript]
geocoder = new google.maps.Geocoder();
geocoder.geocode({address: "住所"}, callback_function);
[/javascript]

geocodeに渡す住所のリストを回して、geocodeを呼んで、コールバックでマーカー作ってもOKです。
こっちの方だとpythonでやることはほとんどない。
(まぁ、そもそも最初からpythonを使う必要なんてなかったけど。)

できあがったのはこんな感じ

最終的に東店が近かったので行ってきました。
目当ての物はなかったみたいですけどね!

参考