open-uri で google place API を使ってお店情報を取得 (opensslではまったよ)
Step1 ブラウザからAPIを発行してみる
まずはGoogle APIs Consoleで使用したAPIをEnableし、Keyを取得します。
ここではまったのですが、Google place APIはGoogle MAP APIを有効にしても使えません。
Service一覧の下の方に Places API というのがあるのでそいつを有効にする必要があります。
あとは、APIドキュメントにしたがってURLを作成してブラウザのアドレスバーに入れるだけ。
下記はJSONで東京駅周辺のお店データを取るときの例です。
※ プレイス検索だとロケーション情報を入れないといけなくて面倒なので、キーワードだけで行けるオートコンプリート(テキストサーチでもOK)を使っています。
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=Japan&sensor=false&types=establishment&key=<上で取得したキー>
ちなみ、失敗するとこんなのが帰ってきます(autocompleteの場合)。
{ "predictions" : [], "status" : "REQUEST_DENIED" }
search, textsearchの場合の失敗はこんなの。
{ "html_attributions" : [], "results" : [], "status" : "REQUEST_DENIED" }
これが帰ってきた場合は、下記をチェックしてみましょう。
これら二つがOKだったら、URLのどこかに間違いがあるのでそれを探しましょう。
私の場合は、&の1つが?になっていたのに気が付かず、ずっと悩んでいました。。。
Step2 Rubyから取得してみる
こんなんを書いてRubyから取得してみます。
require "open-uri" url = "https://maps.googleapis.com/maps/api/place/autocomplete/json?input=Japan&sensor=false&types=establishment&key=MyKey" open(url) do |f| puts f.read end
実行すると早速エラー終了。
C:/Ruby193p392/lib/ruby/1.9.1/net/http.rb:799:in `connect': SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (OpenSSL::SSL::SSLError)
Google先生に聞いてみたところ、opensslにルート証明書の在り処を教えてあげないといけないらしい。
教え方は簡単で、環境変数 SSL_CERT_FILE にファイルのフルパスを設定するだけ。
> set SSL_CERT_FILE=c:\cer\route_for_google.cer
みたいな感じです。
ここではまったのが「どのルート証明書を指定すれば良いのか」という事。
Chromeの 設定 -> 詳細設定の表示 -> 証明書の管理 を選択すると、このPCにインストールされている証明書が沢山見られるのですが、適当に選んでファイルにExportして、SSL_CERT_FILEに設定しても上記エラーが出るだけ。
あちこち拝見してまわったところ、以下の手順で、接続したいhttpsサイトのルート証明書を特定できることがわかりました。
- ブラウザで、接続したいサイトに接続(今回の例だと https://maps.googleapis.com/...)
- Chromeだと入力したアドレスの左側、IEだと右側に鍵アイコンがでるので、それをクリックし証明書情報を表示
- 証明パスを選択し、ルート(ツリーの一番上)をクリック。
- 証明書の表示 -> 表示 -> ファイルにコピー -> Base64 encoded... で適当な名前でファイルにコピー
この手順で作成したルート証明書を SSL_CERT_FILEに指定したところ、Rubyからも無事お店データを取得できました。
ちなみに、例のURLですとこんなのが帰ってきます。
{ "predictions" : [ { "description" : "日本東京都港区虎ノ門3丁目8 Japan Sword", "id" : "be51b9a3c66c42a334004177a659217b74892204", "matched_substrings" : [ { "length" : 5, "offset" : 15 } ], ......