はじめに
Python初学者のわたしが覚えるために、学んだことを整理し、理解を深めるために記事を書いています。
前回の続きで、Google Maps APIになります!
※本記事は第3回目になります!
まだ第1回・第2回を読んでいない方は、先にそちらから読んでもらえると、
流れがより分かりやすいと思います😊
この記事でやること(本日のゴール⚽️)
第2回では、日本語でフローを整理しながら全体像を掴み、
Google Maps API(Text Search)を使ってお店の検索を行いました🐥
今回の記事では、その検索結果で取得した place_id を使って、
お店の基本情報と口コミを取得するところまで進めていきたいと思います!
ドーナツ屋さんの情報を取得するまでの流れを3つのフローに分けて行いたいと思います💪
- 検索結果から place_id を取得する
- place_idを使って基本情報を取得する
- place_idを使って口コミを取得する
検索結果から place_id を取得する
place_idとは?と思いましたよね!私もです😂
place_idは、Google Maps APIが場所やお店ごとに
1つずつに割り当てられているIDを指します!
ポイント!
Text Search ではお店を「検索」するところまでしかできない!!
なので、検索結果から取得した place_id を使って、
別のAPIで詳しい情報を取得していきます!
place_idを使うと以下のような詳しい情報などを取得することができる!
- 住所
- 電話番号
- お店のURL
- 評価
- 口コミ
ここではText Searchのレスポンスから次の処理で必要になるplace_idだけを取り出す関数を作っていきます🐥
APIのレスポンスにはplace_id以外にもたくさんの情報が入っているんです!
実際にprintで出力してみると英語がいっぱいで読解不可でした😂
そのままで扱うのは難しいのでplace_idだけを取り出す役割をこの関数に持たせています✏️
#③ 検索結果からplace_idを取得する
def get_place_id(self,response_json: dict) -> Optional[str]:
#もし2つ目のフローでレスポンスがなかった場合はNoneで返す
if not response_json:
return None
#Text Searchの検索一覧
response_results = response_json.get("results",[])
"""
.get("results", []) は 辞書の標準メソッド
①辞書に"results"というキーがあればその値を返す
②キーが存在しないときは第2引数の値の空っぽリストを返す
"""
#もし"results"というキーがなければNoneで返す
if not response_results:
return None
#最初の店舗のお店のplace_idを取得して
place_id = response_results[0].get("place_id")
#もしそれがなければNone
if not place_id:
return None
return place_id
place_idを使って基本情報を取得する
Text Searchの検索結果からplace_idを取得ができたので🙌
次はこのplace_idを使って、お店の基本情報を取得していきます! 🍩🍩🍩
#④ place_idを使って基本情報を取得する
def get_place_id_detail(self, place_id: str) ->Optional[Dict]:
#------------------
# place_id を使って、以下の基本情報を取得する
# ・住所
# ・電話番号
# ・ホームページURL
# ・評価
# ・レビュー総数
#------------------
if not place_id:
return None
#APIリクエストをする
#place_id を使って「詳細情報」を取得するためのエンドポイント
url = "https://maps.googleapis.com/maps/api/place/details/json"
#検索ワード、言語、APIキーを指定する
params = {
"place_id": place_id,
"language": "ja",
"fields": "formatted_address,formatted_phone_number,website,rating,user_ratings_total",
"key": self.api_key_demo
}
#requests.getはrequestのメソッドで必要な情報を取得してとお願い
shop_detail_response = requests.get(url, params=params)
#HTTPのエラーコード200が成功なので、それ以外の場合はNoneで返す
if shop_detail_response.status_code != 200:
return None
#受け取ったレスポンスをJSON型にする
shop_detail_response_json = shop_detail_response.json()
#キーが存在しないときは第2引数の値の空っぽ辞書で返す
shop_detail_result = shop_detail_response_json.get("result",{})
#結果がなければNoneで返す
if not shop_detail_result:
return None
#必要な項目をゲットして抜き出す(辞書にまとめる)
place_detail = {
"address":shop_detail_result.get("formatted_address"),
"phone": shop_detail_result.get("formatted_phone_number"),
"website": shop_detail_result.get("website"),
"rating": shop_detail_result.get("rating"),
"review_count": shop_detail_result.get("user_ratings_total")
}
return place_detail
今回HTTPのエラーコードは200の成功以外はNoneとしましたが、
それ以外のエラーコードを調べてみたら、こんなに色々ありました!
エラーコードで何が原因なのかが分かるようになっています☺️
【HTTPのエラーコード一覧】
| ステータスコード | 意味 | 内容 |
|---|---|---|
| 200 | 成功 | 正常にレスポンスを取得できたので処理を続ける |
| 400 | 不正なリクエスト | パラメータの指定ミスなど。 |
| 401 | 認証エラー | APIキーが無効・未設定など |
| 403 | アクセス拒否 | APIキーの制限・権限不足 |
| 404 | 見つからない | place_id が存在しない可能性 |
| 429 | リクエスト過多 | APIの利用制限(呼びすぎ) |
| 500 | サーバーエラー | Google側の一時的な不具合 |
【辞書として取得】
"address": shop_detail_result.get("formatted_address") の部分では、
APIで取得したほしい情報を、辞書にします!
-
"address"は、この辞書で使う キー -
shop_detail_result.get("formatted_address")は、.get()を使って
Google Places API のレスポンスの中から
formatted_addressという項目を取り出してvalueにしています!!
formatted_address が存在しない場合はNoneを返します🐥
place_idを使って口コミを取得する
次はplace_idを使って、レビューを取得していきます✏️
#⑤ place_idを使って口コミを取得する
def get_shop_reviews(self, place_id: str) ->Optional[list]:
if not place_id:
return None
#place_id を使って「詳細情報」を取得するためのエンドポイント
url = "https://maps.googleapis.com/maps/api/place/details/json"
#検索ワード、言語、APIキーを指定する
params = {
"place_id": place_id,
"fields": "reviews",
"language": "ja",
"key": self.api_key_demo
}
#APIへ.getでリクエストを出す
reviews_response = requests.get(url, params=params)
#HTTPのエラーコード200が成功なので、それ以外の場合はNoneで返す
if reviews_response.status_code != 200:
return None
#レビューがある場合はJSON形式で受け取る
reviews_response_json = reviews_response.json()
#resultを取得し、なければNoneで返す
review_result = reviews_response_json.get("result",{})
if not review_result:
return None
#レビューがあれば取得し、なければ空リストを返す
reviews = review_result.get("reviews",[])
if not reviews:
return []
return reviews
結果がなければ空の辞書なのに、Noneで返すなぞ!🧐
ここの部分が矛盾している気がして、私は理解がなかなか難しかったです💦
結果がなければ空の辞書にしてねといっているのに、最後はreturn Noneで返すことがモヤモヤしました!
review_result = reviews_response_json.get("result",{})
if not review_result:
return None
ここで {} を指定しているのは、
APIのレスポンスにresultが存在しなかった場合になります!
これを入れなければ空っぽだとエラーを出してしまいます!
なので、{} に一時的に空だけど入れて、エラーを出さないようにして、
最後はこれをNoneで返しています🐥
まとめ
今回は、Text Searchの次の段階としてplace_idを使って
基本情報とレビューの取得を行いました!
色々とこの部分でも私は迷ったので、お役に立てる嬉しいです☺️
次回はこの取得したデータが基本情報とレビューがバラバラになっているので、
1店舗分を1つにまとめていきます😊