郵便番号マップ作成記 (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}]"

続く。