2009年03月18日
郵便番号マップ作成記 (2) - ジオコーディングで経度緯度を求める
第1回 では郵便番号データをデータベースに格納するところまでを作った。今回は住所から緯度経度を求めていこう。ビジュアライズのための下準備は今回で完了だ。
ジオコーディング API は何を使おう
ジオコーディングとは、住所や名所から緯度経度を求めること。世の中にはいくつかジオコーディングの API が存在するが、今回は Google が提供する ジオコーディング API を選択した。
理由はGoogle が提供するという安心感と、1日あたり1万5千回まで OK と太っ腹なところ。REST で利用できるのも魅力的だった。
いざ実行
スクリプトをがーっと書いてひたすら実行する。
require 'EntrySchema'
require 'cgi'
require 'open-uri'
$URL = "http://maps.google.com/maps/geo?"
Code.find_all_by_low("0000").each do |code|
# 経度緯度を既に求めていたら次
next unless code.lat.nil? and code.lng.nil?
# URL を求める
q = code.pref + code.city
url = $URL + {"q" => q, "output" => "xml"}.map { |key, value|
"#{CGI.escape(key)}=#{CGI.escape(value)}"
}.join("&")
# 読み取る
open(url) do |f|
xml = f.read
puts xml
doc = REXML::Document.new(xml)
# coordinates タグの中身を読み取る
latlng = REXML::XPath.first(doc.root, '//coordinates').text
lng, lat = latlng.split(/,/)
code.lng = lng.to_f
code.lat = lat.to_f
puts "#{q} #{lng} #{lat}"
end
# 保存
code.save
# 3秒スリープしておく
sleep(3)
end
エラー処理は特にやってないので、例外が起きたらそこで止まる。データ量も多くないので、止まってたらそのときに手作業で対応すればよいだろう。
途中、「岡山市北区」でエラーになった。「Google さん、しっかりしてよー」と調べてみたら…
北区(きたく)は岡山県岡山市が2009年4月1日の政令指定都市移行に伴い設置を決めた4つの行政区のうちの一つ
とのことらしい。
まだ存在してない区ならば、取得できなくても仕方がない…。
岡山市の4つの区については Google Maps で検索して、見つかった適当なデータから緯度経度を直接 INSERT して対応しておいた。
DB の中身を JSON で出力
さて、これで緯度経度のデータが出揃った。JavaScript で扱いやすいように、JSON データとして出力しておく。
これも簡単なスクリプトを書いて実現した。住所に \ が含まれることはないので凝った JSON 化は不要だろう。何も考えず使い捨てな勢いで出力コードを書いておいた。
require 'EntrySchema'
json = Code.find_all_by_low("0000").map { |code|
%Q|{"lat" : #{code.lat}, "lng" : #{code.lng}, "name" : "#{code.pref}#{code.city}", "code
" : "#{code.high}"}|
}.join(",\n")
puts "[#{json}]"
続く。