2009-09-23

pythonさんでジオコーディングと逆ジオコーディング

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
場所の名前から緯度経度取得するジオコーディングをpythonでやってみました。

google mapを利用します。
ジオコーディングに関しては、
http://code.google.com/intl/ja/apis/maps/documentation/services.html#Geocoding_Direct
に書いてあります。

コードは以下のような感じです。
google app engineで利用することを前提にしているので
urlfetchを使っていますが、そうでないならばそこを置き換える必要があります。

# -*- coding: utf-8; -*-
import xml.etree.ElementTree as etree
import urllib
from google.appengine.api import urlfetch

#場所名から緯度経度取得
def geocoding(addr):
url = 'http://maps.google.com/maps/geo?'
url = url + 'key=' + 'グーグルマップAPIのキー'
url = url + '&sensor=false'
url = url + '&output=xml'
url = url + '&q=' + urllib.quote(addr.encode('utf-8'))
result = urlfetch.fetch(url)
if result.status_code != 200:
return None
dom = etree.fromstring(result.content)
namespace ='http://earth.google.com/kml/2.0'
code = dom.findtext('.//{%s}code' % namespace)
if code != "200":
return None
point = dom.findtext('.//{%s}coordinates' % namespace)
if point == None :
return None
tmp = point.split(',')
ret = {}
ret['lon'] = tmp[0]
ret['lat'] = tmp[1]
return ret


緯度経度から場所の名称を取得する逆ジオコーディングもgoogle map apiでできることを
http://creco.net/2009/03/07/implement_google_reverse_geocoding_api/
で知りましたので、こちらも試してみました。

コードは以下のような感じです。
取得できる場所の名称が道路名だったり郵便番号だったりするケースを除外するためにAddressDetailsのAccuracyを確認する必要があるのですが、AddressDetailsのネームスペースが他と違っているので、そこが注意ポインツです。
しばらく気づかずにAddressDetailsの情報が取れなくて悩んでしまいました。

# -*- coding: utf-8; -*-
import xml.etree.ElementTree as etree
import urllib
from google.appengine.api import urlfetch

#緯度経度から場所名取得
def regeocoding(lat,lon):
url = 'http://maps.google.com/maps/geo?'
url = url + 'key=' + 'グーグルマップAPIのキー'
url = url + '&hl=ja'
url = url + '&oe=UTF8'
url = url + '&output=xml'
url = url + '&q=' + str(lat) + ',' + str(lon)
result = urlfetch.fetch(url)
if result.status_code != 200:
return None
logging.info(result.content)
dom = etree.fromstring(result.content)
namespace ='http://earth.google.com/kml/2.0'
code = dom.findtext('.//{%s}code' % namespace)
if code != "200":
return None
for placemark in dom.findall('.//{%s}Placemark' % namespace):
ad = placemark.find('.//{urn:oasis:names:tc:ciq:xsdschema:xAL:2.0}AddressDetails')
if ad.get("Accuracy") == "5" or ad.get("Accuracy") == "6":
continue
else :
addr = placemark.findtext('.//{%s}address' % namespace)
break
addr = addr.replace(u'日本', '', 1)
return addr
コメントを投稿