Tech Racho エンジニアの「?」を「!」に。
  • IT Tips
  • Ruby / Rails以外の開発一般

Google Maps APIでGOTOイートしたつもり

ごあいさつ

10月にBPSに入社しましたえんどうと申します。何回目かの転職ですが勤務地が変わるとランチの新規開拓が楽しいですね。ところがテレワークなのでまだ1度しか出社していません。仕事以外でも以前のようにどこかに行くのも難しい状況が続いています。そこで・・・

こういうのを作ります

店名も値段も口コミも表示しないで写真だけ並べて選ぶUIを発明したのですがナントカグラムってものが既にありました。

表示する画像はGoogleマップに投稿されたものです。権利関係が調べきれていませんので念の為ぼかしを入れています。

Google Maps API

今さら?と突っ込まれそうですがプログラミング言語を問わず使えるように、素のAPIとそのJSONのレスポンスを使ってやってみます。

リクエスト数に応じて課金が発生します。
毎月$200分の無料枠がありますので開発の利用では費用が発生することはないと思います。
key含めてコミットしてしまったり、key付きのURLを公にしてしまうと思わぬ出費となりますのでご注意ください。

準備

1. キーの生成

詳細は割愛してキャプチャ中心で失礼します。

  • 必要ならコンソールの利用開始を行い支払いアカウントの設定をします。プロジェクトを作成します。

参考: GoogleCloudConsole

  • PlacesAPIを有効にします

「+APIとサービスの有効化」

 

PlacesAPIを有効に

 

  • 意図しない課金を防ぐためにリクエストの上限を設定します

  • API keyを発行します

上部の「+認証情報を作成」からAPIキーを作成すると、リストにキーが表示されます。

ようやく実行!

準備ができたので実行します。

1. 近くのラーメン屋

ちょっと前の「OK, Google」 のCMのようですが「近くのラーメン屋」です。

特定の場所を起点にして検索できるNearby Searchを使ってみます。

弊社所在地の半径1kmにある「ラーメン」のキーワードで場所を検索してみます。
YOUR_API_KEY のところに先ほど取得したkeyを設定してください。

https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=35.6925059,139.6874533&radius=1000&language=ja&type=restaurant&keyword=ラーメン&key=YOUR_API_KEY

このようなデータが取れました。店舗が特定できる情報は {} でプレースホルダ化しています。

{
"results": [
{
"business_status": "OPERATIONAL",
"geometry": {
"location": {
"lat": {lat},
"lng": {lng}
},
"viewport": {
"northeast": {
"lat": {lat},
"lng": {lng}
},
"southwest": {
"lat": {lat},
"lng": {lng}
}
}
},
"icon": "https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png",
"name": {店舗名},
"opening_hours": {
"open_now": true
},
"photos": [
{
"height": 4140,
"html_attributions": [
"<a href="\"https://maps.google.com/maps/contrib/{投稿者ページID}\"">{投稿者名}</a>"
],
"photo_reference": {写真参照ID},
"width": 5520
}
],
"place_id": {PLACE_ID},
"plus_code": {
"compound_code": "{CODE} 新宿区、東京都",
"global_code": {GLOBAL_CODE}
},
"price_level": 2,
"rating": 3.8,
"reference": {REFERENCE},
"scope": "GOOGLE",
"types": [
"restaurant",
"food",
"point_of_interest",
"establishment"
],
"user_ratings_total": 348,
"vicinity": {住所}
},
],
[]... //配列で複数の場所が返ります
"status": "OK"
}

2. 写真を取得

写真のURLが直接入っていてくれたら楽だったのですが、もう一段階必要でした。

photos[0].photo_reference を写真参照IDとして、今度はPlace Photos APIで実際の写真を取得します。

これはパラメータが少ないので簡単です。
写真参照ID の部分に取得した文字列を設定すれば写真が取得できます。
maxwidthパラメータによってある程度取得する画像の解像度を制御できるので、必要なサイズに調整します。

https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference={写真参照ID}&key=YOUR_API_KEY

あとはGrid状に並べるだけです

写真ばかりだと何の記事かわからないので、申し訳程度のコード。

その前にCORS問題

今回はお手軽にHTML(JavaScript)からAPIへリクエストしようと思ったのですが、ブラウザから直接Google Maps APIへリクエストするとアクセスできません。

blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

知っている方は知っているいわゆるCORSってやつです。リクエスト受けるサーバ側で Allow 設定してもらわないとブラウザは通信してくれません。
そこで、代理でアクセスするbackendを立てています。そのためリクエスト先が

http://localhost:3333

になります。

この代理してくれるbackendのWebサービスを見かけましたが、今回は大切なAPI_KEYを含むリクエストです。第三者サーバを経由するとカード請求が増えて楽天ポイントがたくさん溜まってしまう恐れがあるため、ローカルでbackendを作りました。

コード概略

エラー処理とかあまり考えてないです。

import GridList from '@material-ui/core/GridList';
import GridListTile from '@material-ui/core/GridListTile';

//...中略

return (
<div>
{items.results
.filter((place) => place.photos != null)
.map((place) => (

<img src="{`http://localhost:3333/photo/${place.photos[0].photo_reference}`}" alt="{place.name}" />

))}</div>
);

GOTO

↑この騒動が忘れられる日を願ってリンクしておきます

カリフォルニア

浜松

佐賀

鳥取

資料

Google Cloud Console

公式ドキュメント

最後に

本当は混雑メーターのデータをAPI取得して、自分のよく行く飲食店・スーパーなど登録した場所のなかで「どこが一番空いているか」というのをやりたかったのですが、混雑データはAPIでは提供されてませんでした。

そこで外出自粛とGoogle Maps APIをネタに何かできないかなと、こういう形になりました。
APIのドキュメントやJSONのレスポンスを眺めて「こういう事ができそう」という、冷蔵庫の残り物で献立を考える方式ですが、意外と新しいアイデアが降ってくるかもしれません。

追伸

BPSに入社されますと、特典といたしまして当記事の美味しそうな料理の写真がぼかしなしでお読みいただけます。



CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。