Rubyを使って住所から緯度経度を求めてみよう！

# はじめに
今考えているアプリで住所から緯度経度を求める必要があり、ちょうど ~~再就職のために~~ Rubyの勉強をしているので試してみました。
geocodingをするなら __Google Maps API__ を直ぐに思い付きましたが、下記の様な制限があり、利用制限が比較的緩い __Yahoo!ジオコーダAPI__ を使ってみます。

[Google Geocoding API - 利用制限](https://developers.google.com/maps/documentation/geocoding/?hl=ja#Limits)
> Google Geocoding API 使用時のクエリ制限として、1 日あたりの位置情報リクエストが 2,500 回に制限されています（Google Maps API for Business をご利用の場合は、1 日あたり 100,000 件までリクエストを実行できます）。

ちなみに[ジオコーディング](http://ja.wikipedia.org/wiki/%E3%82%B8%E3%82%AA%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0 "ジオコーディング - Wikipedia")とは
> ジオコーディング（英語: geocoding）は、各種情報に対して、関連する地理座標（典型的には緯度・経度）を付加すること、およびこれに関する技術やソフトウェアをいう。付加された地理座標のことをジオコードと称する。

# 準備
1. __Yahoo!ジオコーダAPI__ を使う場合に __Yahoo! JAPAN ID__ が必要なため持っていない人は[ここ](https://account.edit.yahoo.co.jp/registration?.src=www&.done=http%3A%2f%2fwww.yahoo.co.jp "Yahoo! JAPAN ID登録")で作成して下さい。
2. __Yahoo!ジオコーダAPI__ を使う場合は、事前に __アプリケーションID__ を発行する必要があります。 __アプリケーションID__ の発行については[ここ](http://developer.yahoo.co.jp/start/ "Yahoo!デベロッパーネットワークご利用ガイド")を参照して下さい。

# APIの概要
1.住所から緯度経度を求める __Yahoo!ジオコーダAPI__ については[ここ](http://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/geocoder.html "Yahoo!ジオコーダAPI")を参照して下さい
2.緯度経度から住所を求める __Yahoo!リバースジオコーダAPI__ については[ここ](http://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/reversegeocoder.html "Yahoo!リバースジオコーダAPI")を参照して下さい

# さてコーディング
 __Google Maps API__ との比較もしてみましょう。

```ruby:geocoder_test.rb
require 'net/http'
require 'json'

BASE_URL_GOOGLE_MAP = "http://maps.google.com/maps/api/geocode/json"
BASE_URL_YOLP_GEOCODER = "http://geo.search.olp.yahooapis.jp/OpenLocalPlatform/V1/geoCoder"
BASE_URL_YOLP_REVERSE_GEOCODER = "http://reverse.search.olp.yahooapis.jp/OpenLocalPlatform/V1/reverseGeoCoder"
APP_ID_YAHOO = "取得したアプリケーションIDを記述する"

# Google Map API
def geocode_google_map(address)

  puts "Geocode by Google Map API"

  address = URI.encode(address)
  hash = Hash.new
  reqUrl = "#{BASE_URL_GOOGLE_MAP}?address=#{address}&sensor=false&language=ja"
  response = Net::HTTP.get_response(URI.parse(reqUrl))

  # レスポンスコードのチェック
  # 詳細は http://magazine.rubyist.net/?0013-BundledLibraries
  case response
  # 200 OK
  when Net::HTTPSuccess then
    data = JSON.parse(response.body)
    hash['lat'] = data['results'][0]['geometry']['location']['lat']
    hash['lng'] = data['results'][0]['geometry']['location']['lng']
  # それ以外
  else
    hash['lat'] = 0.00
    hash['lng'] = 0.00
  end

  return hash

end

# Yahoo!ジオコーダAPI
def geocode_yolp(address)
  
  puts "Geocode by Yahoo!ジオコーダAPI"

  address = URI.encode(address)
  hash = Hash.new

  # 出力形式にJSONを指定する
  reqUrl = "#{BASE_URL_YOLP_GEOCODER}?appid=#{APP_ID_YAHOO}&query=#{address}&output=json"
  response = Net::HTTP.get_response(URI.parse(reqUrl))

  # レスポンスコードのチェック
  # 詳細は http://magazine.rubyist.net/?0013-BundledLibraries
  case response
  # 200 OK
  when Net::HTTPSuccess then
    data = JSON.parse(response.body)
    #p status # for DEBUG
    # YOLPでの座標情報は緯度経度に分かれていない（カンマ区切りの）ため分解する
    coordinates = data['Feature'][0]['Geometry']['Coordinates'].split(/,\s?/)
    hash['lat'] = coordinates[1].to_f # 緯度
    hash['lng'] = coordinates[0].to_f # 経度
  # それ以外
  else
    hash['lat'] = 0.00
    hash['lng'] = 0.00
  end

  return hash

end

# Yahoo!リバースジオコーダAPI
def reverse_geocode_yolp(coordinates)
  
  puts "Reverse Geocode by Yahoo!リバースジオコーダAPI"

  lat = coordinates['lat'].to_s
  lng = coordinates['lng'].to_s

  # 出力形式にJSONを指定する
  reqUrl = "#{BASE_URL_YOLP_REVERSE_GEOCODER}?appid=#{APP_ID_YAHOO}&lat=#{lat}&lon=#{lng}&output=json"

  #p reqUrl # for DEBUG
  response = Net::HTTP.get_response(URI.parse(reqUrl))

  # レスポンスコードのチェック
  # 詳細は http://magazine.rubyist.net/?0013-BundledLibraries
  case response
  # 200 OK
  when Net::HTTPSuccess then
    data = JSON.parse(response.body)
    #p status # for DEBUG
    address = data['Feature'][0]['Property']['Address']
  # それ以外
  else
    address = "住所が取得出来ません"
  end

end

puts "========================================================="
p geocode_google_map("東京都港区芝公園4‐2‐8")
puts "========================================================="
coordinates = geocode_yolp("東京都港区芝公園4‐2‐8")
p coordinates
p reverse_geocode_yolp(coordinates)
puts "========================================================="

```

# 実行結果

```
$ ruby geocoder_test.rb
=========================================================
Geocode by Google Map API
{"lat"=>35.6587039, "lng"=>139.7454081}
=========================================================
Geocode by Yahoo!ジオコーダAPI
{"lat"=>35.65870316, "lng"=>139.74540779}
Reverse Geocode by Yahoo!リバースジオコーダAPI
"東京都港区芝公園４丁目２－８"
=========================================================
$
```

# まとめ
「Yahoo! Open Local Platform」の __ジオコーダAPI__ と __リバースジオコーダAPI__ の紹介でした。