PythonでGoogle Places APIを使って取得したデータを表示させる方法

今回、PythonでGoogle Places APIを使って取得したデータを表示させる方法にをまとめていきます。八月中旬からアメリカでエンジニアインターンが開始して以降、ブログ更新と駒澤大学生向けサイト「KOMANEKO」のメンテナンスを怠っていました。

駒澤大学生向け学内団体情報とイベント共有サイト「KOMANEKO」

KOMANEKOでは新入生に向けたサークルなどの団体情報を簡単に管理できるだけでなく、部活、サークル、ゼミナールまたは個人が開催するイベントを簡単に共有し、Twitterなどでシェアすることができます。

最近アメリカでの生活にも余裕が出てきて「KOMANEKO」をメンテナンスする余裕が出てきました。何か新しい機能追加したいと思い、浮かんだのが今回リリースした「KOMAFOOD」です。Google MAPの情報を活用して駒澤大学から半径1km以内のレストラン情報を取得して表示させたら面白いのではないかと思い、早速翌日からインターン先で内職をしながら実装を開始。今回、PythonとFlaskで機能追加をしていきます。

完成コード

はじめに完成したコードを載せておきますね。今回、Googl APIでカフェの情報を取得し表示させるのがゴールです。

@core.route('/komafood')
def komafood():
    key = 'apikey' # 上記で作成したAPIキーを入れる
    client = googlemaps.Client(key) #インスタンス生成
    loc = {'lat': 35.6288505, 'lng': 139.65863579999996} # 軽度・緯度を取り出す
    place_results = client.places_nearby(location=loc, radius=1000, keyword='カフェ',language='ja') #半径1000m以内のカフェ情報を取得
    pprint.pprint(place_results)
    results = []
    photos = []
    for place_result in place_results['results']:
        results.append(place_result)
        # 配列にphotosが存在しないとき、NO IMAGE画像を表示。
        if not 'photos' in place_result.keys():
            photo = 'https://'+str(app.config['AWS_BUCKET'])+'.s3-ap-northeast-1.amazonaws.com/default_profile.png'
            photos.append(photo)
            else:
            p_value = place_result['photos'][0]['photo_reference']
            photo = 'https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference={}&key={}'.format(p_value,str(app.config['GOOGLE_MAP_API']))
            photos.append(photo)
    pprint.pprint(photos)
    print(random.choice(results))
    return render_template('comacafe.html',results=results,photos=photos)
<h1 class="event_top" style="color:#45494b;"><i class="fas fa-utensils"></i>
    <b>KOMAFOOD</b>
</h1>
<div class="site_box" style="background-image:linear-gradient(-210deg, #BC32A4 0%, #E03768 50%, #F67C33 100%); opacity:0.9;">
    <h2 class="intro_p" style="color:white;"><b>9/27(土)KOMAFOODをリリースしました。駒澤大学周辺にはおしゃれなカフェや駒澤大学生にはあまり知られていないお店がたくさんあります。
         KOMAFOODを通じて新しい食と空間の出会いを提供できるようなサイトを目指します。今後、カフェ以外のジャンルやレビュー順に表示できるなどの機能追加をしてまいります。</b>
    </h2>
</div>
<p style="color:#45494b; text-align: center;">*駒澤大学から半径1km以内のカフェ情報をGoogle M表示しています</p>
<div class="index_box">
    {% for result in results %}{% set A_list_loop = loop %}
        {% for photo in photos %}
            {% if loop.index==A_list_loop.index %}
                <a class='card_title' style="text-decoration: none; color : #000000;" href="{{result['result']['url']}}" target=”_blank”>
                <div class="post_box_index" style="color:#45494b;">
                    <div class="post_top">
                        <h1 class="index_title"><b>{{result['result']['name']}}</b></h1>
                    </div>
                    <img class="index_image_index" align='center' src="{{photo}}" alt="">
                    <p>住所:{{result['result']['vicinity']}}<br>
                    電話番号:{{result['result']['international_phone_number']}}<br>
                    評価:{{result['result']['rating']}}</p>
                </a>
                <p style='font-size:12px;'>WEBサイト<br><a href="{{result['result']['website']}}">{{result['result']['website']}}</a></p>
                </div>
            {% endif %}
        {% endfor %} 
    {% endfor %} 
</div>

Google APIキーを取得する

Google MAPの情報を取得するにはGoogle APIキーが必要になります。取得の方法についてはこちらの記事をご参照ください。

【要確認】Google Maps Platform APIキーの取得方法と注意点

TCDのカスタマーサポートに寄せられる質問でも多い部類に入ります。今回はGoogle Mapの表示に関わるGoogle Maps Platformについて実際の取得作業を行いながら、記事を作成しました。GoogleMapで不具合のある方の参考になれば嬉しく思います。 …

pythonライブラリのgooglemapsをインストール

続いてPythonライブラリをインストールします。コマンドで以下を実行します。

pip install googlemaps

googlemapsとpprintをimport

ライブラリのインストールは完了したらgooglemapsとpprintをimportします。pprintはlist型やdictionary型を見やすくするためのprintライブラリです。

import googlemaps
import pprint # list型やdict型を見やすくprintするライブラリ

Google Mapの情報を取得する

Google Mapの情報を取得していきます。こちらは@core.route(‘/komafood’)pythonフレームワークflaskのお作法でこの1行でサイトのパスを設定しています。その下にkomafoodファンクションを作成し、取得したAPIキーをセットしてgooglemaps.Client(key)でインスタンスを生成します。今回、駒澤大学半径1km以内の情報を取得したいので、以下のように記述します。

@core.route('/komafood')
def komafood():
key = str(app.config['GOOGLE_MAP_API']) # 上記で作成したAPIキーを入れる
    client = googlemaps.Client(key) #インスタンス生成
    loc = {'lat': 35.6288505, 'lng': 139.65863579999996} # 大学の緯度、経度を設定。
    place_results = client.places_nearby(location=loc, radius=1000, keyword='カフェ',language='ja') #半径1000m以内のカフェ情報を取得
    pprint.pprint(place_results)

pprintで結果を見ると以下のようにデータを取得できているのが確認できます。

'results': [{'geometry': {'location': {'lat': 35.633795, 'lng': 139.6608681},
                           'viewport': {'northeast': {'lat': 35.63512747989272,
                                                      'lng': 139.6621710298927},
                                        'southwest': {'lat': 35.63242782010728,
                                                      'lng': 139.6594713701073}}},
              'icon': 'https://maps.gstatic.com/mapfiles/place_api/icons/cafe-71.png',
              'id': '458005d7b299cb781bb3ea89f697a8e440a9638d',
              'name': 'rice cafe',
              'photos': [{'height': 4618,
                          'html_attributions': ['<a '
                                                'href="https://maps.google.com/maps/contrib/109845876179671154841/photos">石川智子</a>'],
                          'photo_reference': 'CmRaAAAAhfmVkWgNOtv6jcKhFDi97cGGMSmpnc_ojnHFkQBjwwZTwk7hur-ylWbGTRCY6CS3CWDQbYvldUySha-ZqMU-T9_Hd5ZGR7Anoq1_R4D2oX0IaJNOTYznWwbpqGDMkjfBEhCybXtyozfgV_q_FKfz__tiGhSXQ_TYyKkWfQfoKz_tVsJCT1iHfQ',
                          'width': 3464}],
              'place_id': 'ChIJF3G_G5D0GGARwHen_P84lKw',
              'plus_code': {'compound_code': 'JMM6+G8 Tokyo, 東京都 Japan',
                            'global_code': '8Q7XJMM6+G8'},
              'rating': 4.2,
              'reference': 'ChIJF3G_G5D0GGARwHen_P84lKw',
              'scope': 'GOOGLE',
              'types': ['cafe', 'food', 'point_of_interest', 'establishment'],
              'user_ratings_total': 54,
              'vicinity': '4 Chome-5-5 Kamiuma, Setagaya City'},
             {'geometry': {'location': {'lat': 35.6332433, 'lng': 139.6617063},
                           'viewport': {'northeast': {'lat': 35.63459312989272,
                                                      'lng': 139.6630561298927},
                                        'southwest': {'lat': 35.63189347010728,
                                                      'lng': 139.6603564701072}}},
              'icon': 'https://maps.gstatic.com/mapfiles/place_api/icons/cafe-71.png',
              'id': 'b99fb5f85ed8c6893b51829ecefb2dfe55de93cd',
              'name': 'TOKYO People’s Cafe Komazawa',
              'opening_hours': {'open_now': False},
              'photos': [{'height': 3024,

空のリストを用意する

データを取得することを確認できたら、その結果をfor文でループさせ必要な情報のみを取得していきます。取得したデータをリストに格納していきたいのでカフェ情報とカフェ写真用の空のリストを用意します。

results = []
photos = []

for文でデータを取得していく

先ほど取得した結果をfor文でループさせてデータを配列に格納します。取得したデータは先ほど作成した空のリストにappendを使って追加していきます。results.append(place_result)今回、とりあえず以下のデータを取得していきます。

 for place_result in place_results['results']:
        results.append(place_result)

画像データの存在チェック

続いてお店の画像データを取得していきます。画像データがない場合もあるので、if文で条件分岐をさせて画像がない場合はNo image画像を画像が存在する場合は、画像一枚のみを取得して先ほどと同様にリストに格納していきます。

photo_referenceに画像のデータがあるので取得し、以下のような画像urlを作成します。https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference=画像データ&key=APIキー

# 配列にphotosが存在しないとき、NO IMAGE画像を表示。
        if not 'photos' in result.keys():
            photo = 'https://'+str(app.config['AWS_BUCKET'])+'.s3-ap-northeast-1.amazonaws.com/default_profile.png'
          #配列に追加
      photos.append(photo)
        # 配列にphotosが存在するとき、画像情報を取得。
        else:
            p_value = result['photos'][0]
            photos_photo_reference = p_value['photo_reference']
            pprint.pprint(photos_photo_reference)
            photo = 'https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference={}&key={}'.format(photos_photo_reference,'csmdcmsdicmsdfivmdfinvdsjkcmmcdios')
            #配列に追加 
            photos.append(photo)
    # pprint.pprint(results)

HTMLファイルを作成し、作成したリストの値を渡す

komanekocafe.htmlを作成し、二つのリストをrender_templateを使って渡してあげます。

return render_template('komacafe.html',results=results,photos=photos)

HTMLファイルでループを使ってお店情報を表示させていく。

komacafe.htmlにコードを追加していきます。お店情報とお店の画像が格納された二つのリストをfor文で処理していきます。複数のリストの処理の仕方については以下の記事を参考にしました。

[Jinja2] 複数のリストをまとめてfor文で処理する – Qiita

はじめに 結構はまったのでメモです # やりたかったこと jinja2上で以下のような複数のリストをfor文のinのあとに当てはめて、 A_list = [a_1, a_2, a_3] B_list = [b_1, b_2…

<div class="index_box">
    {% for result in results %}{% set A_list_loop = loop %}
        {% for photo in photos %}
            {% if loop.index==A_list_loop.index %}
                <a class='card_title' style="text-decoration: none; color : #000000;" href="{{result['result']['url']}}" target=”_blank”>
                <div class="post_box_index" style="color:#45494b;">
                    <div class="post_top">
                        <h1 class="index_title"><b>{{result['result']['name']}}</b></h1>
                    </div>
                    <img class="index_image_index" align='center' src="{{photo}}" alt="">
                    <p>住所:{{result['result']['vicinity']}}<br>
                    電話番号:{{result['result']['international_phone_number']}}<br>
                    評価:{{result['result']['rating']}}</p>
                </a>
                <p style='font-size:12px;'>WEBサイト<br><a href="{{result['result']['website']}}">{{result['result']['website']}}</a></p>
                </div>
            {% endif %}
        {% endfor %} 
    {% endfor %} 
</div>

For文でリストを回して表示させることで以下のようにGoogle Mapから取得した情報を以下のように表示させることができました。

駒澤大学生向け学内団体情報とイベント共有サイト「KOMANEKO」

9/27(土)KOMAFOODをリリースしました。駒澤大学周辺にはおしゃれなカフェや駒澤大学生にはあまり知られていないお店がたくさんあります。 KOMAFOODを通じて新しい食と空間の出会いを提供できるようなサイトを目指します。今後、カフェ以外のジャンルやレビュー順に表示できるなどの機能追加をしてまいります。 *駒澤大学から半径1km以内のカフェ情報をGoogle M表示しています …

まとめ

当初、ぐるなびAPIを使用して大学周辺の画像を表示させる計画だったのですが、取得できる情報の精度が低かった(カフェしているのに長崎ちゃんぽんとかロイヤルホストが出てくる)ので今回Google map APIを使用しました。今後、カフェ以外のジャンルやレビュー順に表示できるなどの機能追加をしていきたいと思います。KOMAFOODを通じて新しい食と空間の出会いを提供できるようなサイトを目指します。

最新情報をチェックしよう!
>文系エンジニア大学生の技術ブログ

文系エンジニア大学生の技術ブログ

社会が多様化していく中、大学生の学生生活も多様であるべきと考えています。主にエンジニア向けにITやプログラミングなどの技術系と大学生向けに休学、留学、海外生活、トビタテ留学、長期インターンに関する記事を書いています。