施設名から経緯度を一括自動取得する方法

今さら感のある話題ですが、経緯度の公開されていない放射線量の自治体公開データから、住所や経緯度を一括で取得するやり方の説明をします。使用言語は Python です。Python 以外の言語でも、同じやり方でできるはず。1600 箇所の可視化4400 箇所の可視化のときに使った方法です。

福島県が経緯度を公開してくれれば良かったのですが、例えばこの PDFのように、施設名しか公開してくれませんでした。そのときの文句は「4 月 19 日に福島県災害対策本部原子力班と電話した内容」に書きました。

1. 「iタウンページ」で住所を取得

NTT の提供するiタウンページを使用すると、施設名から住所を取得できます。例えば福島市立御山小学校の場合だと、こんな感じで検索すれば住所が表示されます。同名の小学校が存在する可能性もあるので、「福島県」や「福島市立」などを入れておくと正確に取得できます。

2. Google Maps で経緯度を取得

次に、取得した住所から経緯度に直すには Google Maps を使います。御山小学校の場合は住所が「福島県福島市御山字長滝1-1」ですので、これを引数に渡してこんな感じで情報を取ります。そうすると、うまく見つかった場合には「140.4585484, 37.7786954」という数値が取得できます。検索が失敗する場合もあります。

3. 使った Python Script

まずは元の PDFAcrobat なりで開いた後に少し手を加えて、次のような CSV を作ります。

http://www.pref.fukushima.jp/j/schoolmonitamatome.pdf
,,,,,※測定値(μSv/h)
市町村,No.,区分,調査地点,調査月日,1m高さ,1cm高さ
福島市,1,公立小学校,福島市立御山小学校,2011/04/05,4.9,6.3
福島市,2,公立小学校,福島市立三河台小学校,2011/04/05,3.3,4.1
福島市,3,公立小学校,福島市立松川小学校,2011/04/05,2.3,2.7
福島市,4,公立小学校,福島市立下川崎小学校,2011/04/05,4.2,4.9
福島市,5,公立小学校,福島市立水原小学校,2011/04/05,2.1,2.7
福島市,6,公立小学校,福島市立金谷川小学校,2011/04/05,3.1,3.8

これを、次の Python script で読み込みます*1

# -*- coding: utf-8 -*-

import codecs
import urllib2
import os

f = codecs.open('school.csv', 'r', 'utf')

for line in f.readlines()[3:]:
    name = line.split(',')[3]
    town = line.split(',')[0]

    if name.find(u'市立') >= 0:
        split_name = name.replace(u'市立', u'市立 ').split(' ')
    elif name.find(u'町立') >= 0:
        split_name = name.replace(u'町立', u'町立 ').split(' ')
    elif name.find(u'村立') >= 0:
        split_name = name.replace(u'村立', u'村立 ').split(' ')
    else:
        split_name = (name, '')

    try:
        url = u'http://itp.ne.jp/result/?kw=' + urllib2.quote(u'福島県'.encode('shift_jis')) + '+' + urllib2.quote(town.encode('shift_jis')) + '+' + urllib2.quote(split_name[0].encode('shift_jis')) + '+' + urllib2.quote(split_name[1].encode('shift_jis'))
    except:
        print name
        continue
    
    fp = urllib2.urlopen(url)
    html = fp.read()

    tmp = open('tmp.txt', 'w')
    tmp.write(html)

    tmp = codecs.open('tmp.txt', 'r', 'shift-jis')

    flag = False

    for tmpline in tmp.readlines():
        if tmpline.find('class="icn"') >= 0:
            address = tmpline.split(u' ')[1].split('<a')[0]
            flag = True
            break

    if not flag:
        print name
        continue

    url = u"http://maps.google.com/maps/geo?q=" + address + u"+" + u"+福島県+日本&output=json&sensor=false"

    fp = urllib2.urlopen(url.encode("utf-8"))
    html = fp.read()

    for v in html.split("\n"):
        if v.find("coordinates") >= 0:
            break

    try:
        lng, lat = v.split("[ ")[1].split(", 0 ]")[0].split(", ")
        lng, lat = float(lng), float(lat)
    except:
        lng, lat = float('nan'), float('nan')

    print "%s\t%s\t%f\t%f" % (name, address, lat, lng)

そうすると、次のような出力が得られます。このやり方で 4400 箇所の 9 割以上は自動で経緯度の取得ができました。残った地点は、有志の皆さんのご協力で手入力で頑張りました。

福島市立御山小学校	福島県福島市御山字長滝1−1	37.778695	140.458548
福島市立三河台小学校	福島県福島市三河南町17−7	37.757742	140.453800
福島市立松川小学校	福島県福島市松川町字南諏訪原31−1	37.656167	140.464370
福島市立下川崎小学校	福島県福島市松川町沼袋字戸ノ内832−3	37.644727	140.500220
福島市立水原小学校	福島県福島市松川町水原字戸ノ内31	37.665687	140.420651
福島市立金谷川小学校	福島県福島市松川町浅川字陳場21	37.683573	140.465394

*1:当時、急いで勢い任せで書いたのを記事用にちょこっと修正しただけなので、もっと綺麗に書けます。