[筆記] 使用 Python 抓取 Google Maps API 地標資料(上)

起因是工作上的需求需要抓取 Google Maps 上的地標,就順便記錄一下過程。但我其實沒有真正寫過 Python,所以如果有任何意見或建議都歡迎 鞭我 跟我分享。

特別提一下 Google Maps 不像其他 Google 服務有把 API 一起包在 Google API Client Library 裡面,而是自己獨立的 Google Maps API,我覺得是蠻奇怪的(如果有人知道為什麼請跟我說)。好在 Google Maps 也是有提供 Apache 2.0 授權的 Client,包含多種語言,都放在 GitHub 上:

這次為了 時程 快速上手,我就選 Python client 來試試看。其實我真的很想藉這個機會碰碰 Go 的說⋯⋯
以上的 client 都包含了下列服務的 API,看起來應該是蠻方便的:

  • Google Maps Directions API
  • Google Maps Distance Matrix API
  • Google Maps Elevation API
  • Google Maps Geocoding API
  • Google Places API
  • Google Maps Roads API
  • Google Maps Time Zone API

更多 client 的簡介和特性,可以到這裡晃晃:Google 地圖 Web 服務的用戶端程式庫

這次我們就鎖定 Google Places API 來 示範 紀錄啦。其實官方文件寫的還算清楚,只是分佈在很多地方。
好 der,那就來抓抓看吧~

環境說明

  • Python Client for Google Maps Services 要求 Python 2.7 或以上的執行環境。
  • 我們這次採用 Python 3.6.2,並且以 pyenv 做版本管理。
  • 使用 Pipenv 管理專案套件,同時也會自動建立 virtualenv 虛擬環境。
  • 使用 dotenv 儲存敏感資訊,後面會再說明使用的情境。

申請 Google Maps API key

所有的 Google Maps Web Service 都需要 API key 或 client ID。這裡我們需要申請一個 Server key 形態的 API key,步驟如下:

  1. 登入 Google Developer Console
  2. 選擇你要使用的專案,或是建立新專案。
  3. 進入專案的資訊主頁,選擇 啟用 API 和服務
    enter image description here
  4. 接著就會進入API 程式庫,啟用想要使用的 API。
    這裡我們要用 Places API,搜尋就可以找到 Google Places API Web Service
    enter image description here
  5. 進去之後按下 [啟用]
    enter image description here
  6. 接著我們要來建立新的 Server Key。前一步驟啟用完成後會自動套轉到該 API 頁面,Google 馬上提醒你要建立憑證才能使用。點選 [建立憑證]。
    enter image description here
  7. Google 會幫你判斷要取得哪種憑證,選擇 Google Places API Web Service 後點選 [我需要哪些憑證?],就會自動生成一個 API Key
    enter image description here

到這裡,我就已經完成取得 API key 的前置作業。你也可以幫這組 Key 增加限制,指定只有哪些網站、IP 位址或應用程式才有權用這組金鑰呼叫 API。

安裝相關套件與環境

Pipenv

這裡我們使用 Pipenv 來管理專案套件。

$ pip install pipenv  # 安裝 Pipenv
$ pipenv install      # 在專案目錄中啟用並安裝套件,若有 dev 套件則加上 --dev
$ pipenv shell        # 啟動專案的 virtualenv 虛擬環境

Google Maps client library

接下來我們就要安裝 Python client 來存取 API。

$ pipenv install googlemaps

dotenv

另外,為了不要把 API key 傳到 git 上,我們選擇了 dotenv 套件來儲存敏感資訊。

$ pipenv install python-dotenv

來抓抓看

這裡簡單以雷達搜尋功能來示範怎麼抓資料回來。
By the way,雷達搜尋雖然很好用,但是英文版的文件說他要被棄用了(噢不!),官方部落格也有相關的說明

# .env
GOOGLE_PLACES_API_KEY= # 把你的 API KEY 放這裡
# radarsearch.py
import googlemaps
import os

from os.path import join, dirname
from dotenv import load_dotenv, find_dotenv

dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path, override=True)  # 設定 override 才會更新變數哦!

GOOGLE_PLACES_API_KEY = os.environ.get("GOOGLE_PLACES_API_KEY")

# Client
gmaps = googlemaps.Client(key=GOOGLE_PLACES_API_KEY)

# Radar search
location = (25.017156, 121.506359)
radius = 25000
place_type = 'restaurant'
places_radar_result = gmaps.places_radar(location, radius, type=place_type)

print(places_radar_result)

如果沒特別指定,API 回傳的格式預設是一個 JSON(client 提供的型態為 dict),我們最主要的資料結果是放置於 'result' 陣列(client 提供的型態為 list)。官方文件對於回傳的「搜尋回應」有更詳細的介紹。

此時,我們可以近一步再用迴圈抓出 Place ID,將其餵給地點詳細資料查詢,以取得更詳盡的資訊,例如其完整地址、電話號碼、使用者評分和評論。

def get_place_details(place_id):
    return gmaps.place(place_id)

for value in places_radar_result['results']:
    place_id = value['place_id']
    print(get_place_details(place_id))

更多 client 的使用範例,可以參考官方放在 GitHub 上的 test 目錄

下集預告

接下來會試著把抓到資料存到資料庫,以及嘗試把一個區域的地圖資料完整走訪。
由於我是 Python 超新手菜鳥,內容可能有不精確的地方。
如果對這系列內容有任何意見或建議,麻煩在下方提出你的看法,萬分感謝!

參考資料