NaClの石飛です。
全国の様々な場所にライブを見に行くことが趣味です。
そんな時会場までの道順などは調べるのですが周辺の施設についてはあまり調べず、いざ会場まで行ってみるとコンビニがすぐ近くになくて困ることなどもあります。
そこで施設名を渡すと周辺施設の件数や名前をWebAPI呼び出しを通して返してくれるスクリプトを書いてみたので紹介します。
まず、施設名から地図上の緯度経度を取得します。
これには、Geocoding API が提供しているAPIを利用します。
require 'open-uri'
require 'rexml/document'
require 'json'
geocoding_uri = "http://www.geocoding.jp/api/?#{URI.encode_www_form({q: ARGV.join(' ')})}"
location = REXML::Document.new(open(geocoding_uri).read).elements['result'].elements['coordinate']
あらかじめ必要なライブラリをrequireしておきます。
対象とする施設名はコマンドライン引数で渡すこととします。
このスクリプトでは入力出力共に文字コードはUTF-8を想定しています。
また、スペース区切りで名称を指定することで目的地を正確に指定できるようにします。
例えば「株式会社ネットワーク応用通信研究所」で検索した場合、松江本社と東京支社の2つの建物が該当しますが、このAPIでは東京支社の情報が返されます。「島根 株式会社ネットワーク応用通信研究所」とスペース区切りで指定すると松江本社の情報が返されます。
このAPIのレスポンスはXMLで返されます。
緯度と経度はそれぞれresults > coordinate
にlat
とlng
という名前で設定されています。
ここで取得した緯度と経度は次に利用する周辺施設APIで使用します。
周辺施設の検索にはGoogle Places API Web Serviceを利用します。
APIの利用には、あらかじめAPIキーの取得が必要です。
またこのAPIには 24時間あたりのリクエスト数は1000件 までという制限があります(それを超える場合はクレジットカード認証を行うことで24時間に15,000件に引き上げることもできます)。
リクエスト数はGoogle Developers Consoleより確認することができます。
place_types = {
convenience_store: 'コンビニ',
restaurant: '飲食店'
}
place_params = {
key: APIKEY,
location: "#{location.elements['lat'].text},#{location.elements['lng'].text}",
radius: 300,
types: place_types.keys.join('|'),
language: 'ja'
}
place_uri = URI.parse("https://maps.googleapis.com/maps/api/place/nearbysearch/json?#{URI.encode_www_form(place_params)}")
key
には取得したAPIキーを、location
には先程取得した緯度と経度をカンマ区切りで指定します。
radius
には指定したlocation
から検索する範囲をメートルで指定します。ここでは例として300を指定します。
types
には取得する周辺施設のカテゴリを指定します。
指定可能な値はここから参照できます。
今回はコンビニと飲食店を対象とします。
あとからカテゴリごとに出力する際日本語で表示したいため、place_typesというハッシュに日本語とセットで値を設定しておきます。
types
は|
区切りで複数指定することが可能です。
language
には検索結果を取得する言語を指定します。
上記で指定した条件を元にAPIを呼び出します。
results = {}
JSON.parse(open(place_uri).read)['results'].each do |result|
place_types.keys.each do |type|
if result['types'].include?(type.to_s)
results[type] ||= []
results[type] << result
end
end
end
こちらのAPIのレスポンスはJSONで返されます。
検索結果のresults
配列に周辺施設の情報が1件ずつ格納されて返されます。
どの種別に該当する建物であるかという情報をtypes
という配列で持っているため指定した種別のどれに該当したのかを判定し種別ごとに施設情報を分類します。
place_types.each do |type, type_name|
places = results[type]
puts "#{type_name}: #{places ? places.count : 0}件"
if places
places.each do |place|
puts "* #{place['name']}"
end
end
end
最後にカテゴリごとに取得した施設数と施設名を表示します。
$ ruby place_search.rb 島根 株式会社ネットワーク応用通信研究所
コンビニ: 2件
* ローソン 松江総合体育館前店
* ファミリーマート松江学園南店
飲食店: 9件
* CoCo壱番屋 松江学園通り店
* The伊太利屋garden
* かつふじ
* スパイス王国 カレーキング Curry King 松江店
* 拉麺屋神楽松江店
* スターレオ
* STAR LEO
* ナマステ・ガネーシャ松江店
* Indian Spice Curry
とりあえず今回は近くにどのような施設があるか把握することを目的としていたため最低限の情報のみ表示しています。
レスポンスにはその他にも周辺施設の位置情報やユーザーによる評価、写真等の情報も含まれていますので、さらなる絞込も行えます。
今回はWebAPIで周辺施設検索のスクリプトを作成してみました。
その他にも最近は様々な便利WebAPIが提供されているためもっと活用していきたいと思いました。