# Google Maps API 教學 --- 撰文時間: 2022/7/18 [TOC] --- 參考文章:[運用Google Map API(Distance Matrix Service)取得旅程時間及距離](https://icelandcheng.medium.com/%E9%81%8B%E7%94%A8google-map-api-distance-matrix-service-%E5%8F%96%E5%BE%97%E6%97%85%E7%A8%8B%E6%99%82%E9%96%93%E5%8F%8A%E8%B7%9D%E9%9B%A2-4e7c9b929e9e) --- ## Install 使用任何可以發出http請求的套件即可,這邊以python的requests為例。其實Google Maps API有開發不同語言的SDK可以直接安裝使用,相對來講較為直觀,可以直接使用SDK裡面包好的function call,但這邊先以較為基礎原始的requests作為範例。 在使用前要先去Google Cloud Platform (GCP) 開通一個API Key 流程為: 1. 在GCP啟動一個專案,並為這個專案開通一個Google Maps API Key ![](https://i.imgur.com/wrusWjB.png=100x100) 2. 創建後,在左側的選單欄選擇Google地圖平台來使用Google Maps相關的服務,會跳出視窗告知你的API Key,按下前往後如果你有打勾啟動所有的話就會啟動所有的API,如果有需要後續可以自己在API列表停用不需要的API ![](https://i.imgur.com/8ZXn8ZW.png) 如上圖,可以看到所有啟用的API,點進去後就可以在右上角停用 3. 接著就可以開始看各個API需要的request跟response了! ## Usage 這邊以[Geocoding](https://developers.google.com/maps/documentation/geocoding)跟[Distance Matrix](https://developers.google.com/maps/documentation/distance-matrix)為例子,詳細內容可以在連結的官方文件中看到。 ### Geocoding 這個API主要的目標在於提供特定地點的座標位置,因此主要輸入包含地址、plus code (一種標記地點的編碼)等等。然而這個API也有提供反geocoding的服務,也就是提供座標位置(經緯度),可以反向查詢他的地址。 要向這個API發出請求,可以使用requests,範例程式碼如下: ```python import requests import json params = {'key':'YOUR_API_KEY_HERE', 'address':''} # 這裡response採用json格式,可以自由選擇為json?或是xml? url = 'https://maps.googleapis.com/maps/api/geocode/json?' params['address'] = '台北市中正區重慶南路一段122號' res = requests.get(url, params=params) mes = json.loads(res.text) print(mes) ``` 其中address直接填入想要查詢的地址就可以了,這邊以總統府的地址為例,得到的response如下: ```json { "results": [ { "address_components": [ { "long_name": "122號", "short_name": "122號", "types": [ "street_number" ] }, { "long_name": "Section 1, Chongqing South Road", "short_name": "Section 1, Chongqing S Rd", "types": [ "route" ] }, { "long_name": "Bo'ai Special Zone", "short_name": "Bo'ai Special Zone", "types": [ "neighborhood", "political" ] }, { "long_name": "建國里", "short_name": "建國里", "types": [ "administrative_area_level_4", "political" ] }, { "long_name": "Zhongzheng District", "short_name": "Zhongzheng District", "types": [ "administrative_area_level_3", "political" ] }, { "long_name": "Taipei City", "short_name": "Taipei City", "types": [ "administrative_area_level_1", "political" ] }, { "long_name": "Taiwan", "short_name": "TW", "types": [ "country", "political" ] }, { "long_name": "100", "short_name": "100", "types": [ "postal_code" ] } ], "formatted_address": "No. 122號, Section 1, Chongqing S Rd, Zhongzheng District, Taipei City, Taiwan 100", "geometry": { "bounds": { "northeast": { "lat": 25.0406219, "lng": 121.5125075 }, "southwest": { "lat": 25.0389397, "lng": 121.5115692 } }, "location": { "lat": 25.0403596, "lng": 121.5122878 }, "location_type": "ROOFTOP", "viewport": { "northeast": { "lat": 25.0411297802915, "lng": 121.5133893302915 }, "southwest": { "lat": 25.0384318197085, "lng": 121.5106913697085 } } }, "place_id": "ChIJ8VoOhwqpQjQRwdEJIkQaDhg", "types": [ "premise" ] } ], "status": "OK" } ``` 其中有幾個內容比較重要的: - address_components: 這個部分會把你傳入的地址parse成不同階級的內容,比方說新竹市屬於level 2的administrative area,那就會有相對應的一個dictionary來儲存這個內容 - formatted_address: 這個部分就是把你所傳入的地址格式化成英文,當然這個部分應該是跟你request的時候設定的return language有關,不過預設是英文所以沒有測試過中文的部分 - **geometry**: 最重要的部分就是這個geometry,也就是所查詢的地點的經度(longtitude)跟緯度(latitude),都會存放在這個dict裏面 其他的元件因為在我的實作中沒有特別使用到,因此就沒有特別研究,有需要一樣可以回到官方的文件中查詢用途跟用法。 最後稍微提一下就是這個status,他是判斷你這次查詢是否成功的一個狀態,有包含很多種錯誤狀態都會寫在這個地方,如果response有問題務必先確認status的內容! #### 收費與速度限制 目前的收費是**每1000個request5美元**,然後速度要求每秒鐘最多50個request,但沒有單日上限,所以在大量發出時務必注意自己的速度問題。其餘內容都一樣包含在[Usage and Billing](https://developers.google.com/maps/documentation/geocoding/usage-and-billing)裏面了 ### DistanceMatrix 這個API主要的服務為計算出發點與終點之間的距離以及所需時間,其中包含不同移動方式的選項。 要對這個API發出request,範例程式碼如下: ```python import requests import json params = {'key':'YOUR_API_KEY_HERE', 'origins':'', 'destinations':'', 'mode': 'walking'} url = 'https://maps.googleapis.com/maps/api/distancematrix/json?' res = requests.get(url, params=params) mes = json.loads(res.text) print(mes) ``` 下面附上從台北車站走到總統府的response為例: ```json { "destination_addresses": [ "No. 122號, Section 1, Chongqing S Rd, Zhongzheng District, Taipei City, Taiwan 100" ], "origin_addresses": [ "No. 3, Beiping W Rd, Zhongzheng District, Taipei City, Taiwan 100" ], "rows": [ { "elements": [ { "distance": { "text": "1.2 km", "value": 1157 }, "duration": { "text": "15 mins", "value": 928 }, "status": "OK" } ] } ], "status": "OK" } ``` 其中發出的request除了origins跟destinations是必填參數外,其他可選的參數要注意的有: - mode: 可以選擇要使用'walking', 'driving', 'bicycling'跟'transit',最後一個是大眾運輸的意思,預設是'driving'。而使用transit的話還可以選擇出發時間跟抵達時間 - unit: 選擇要以公制單位還是英制單位計算 另外注意的是是可以一次輸入多個起點跟終點的,要注意的是多個地點如果在params裏用list來儲存的話,requests在編碼成url的時候會用`&`這個delimiter,但是官方文件要求多個地點要使用`|`來分隔,因此建議直接用`|`把多個地址直接串成一個大字串就好。例如想要同時查詢從台北車站跟台北101走到總統府分別要多遠跟多久,可以把params裡面的'origins'設成 ```python 'origins':'台北市中正區黎明里北平西路3號|台北市信義區信義路五段7號' ``` 這樣子得到的response就會是: ```json { "destination_addresses": [ "No. 122號, Section 1, Chongqing S Rd, Zhongzheng District, Taipei City, Taiwan 100" ], "origin_addresses": [ "No. 3, Beiping W Rd, Zhongzheng District, Taipei City, Taiwan 100", "No. 7, Section 5, Xinyi Rd, Xinyi District, Taipei City, Taiwan 110" ], "rows": [ { "elements": [ { "distance": { "text": "1.2 km", "value": 1157 }, "duration": { "text": "15 mins", "value": 928 }, "status": "OK" } ] }, { "elements": [ { "distance": { "text": "5.9 km", "value": 5946 }, "duration": { "text": "1 hour 19 mins", "value": 4732 }, "status": "OK" } ] } ], "status": "OK" } ``` 可以看到rows中就有兩個結果分別描述需要的距離跟時間 得到的response中幾個重點: - distance: 這個dict的text描述了公里的估計,而value是精確的公尺 - duration: 同樣的text描述的分鐘的估計,而value是精確的秒數 最後同樣的會有status來描述這次查詢分別的狀態如何,因此response有問題時一樣記得先確認status的內容 #### 收費與速度限制 因為攜帶的參數不同所以收費方式也不太一樣,具體還是要看[Usage and Billing](https://developers.google.com/maps/documentation/distance-matrix/usage-and-billing),最基礎的版本一樣是**每1000個element5美元**,注意這邊計算的是element,根據官方文件的定義,一個element是一個origin乘上一個destination,所以一次查詢8個起點跟1個終點的距離,跟分八次查詢單一起點跟終點的距離,收費意義上是一樣的。如果有需要用到traffic information(當下的塞車情況)收費就會較高。速度限制上目前沒有單日上限,其他限制如下: - Maximum of 25 origins or 25 destinations per request. - Maximum 100 elements per server-side request. - Maximum 100 elements per [client-side](https://developers.google.com/maps/documentation/javascript/distancematrix) request. - 1000 elements per second (EPS), calculated as the sum of [client-side](https://developers.google.com/maps/documentation/javascript/distancematrix) and server-side queries. 以上為我個人測試與學習過程的一些紀錄,若有錯誤歡迎不吝指正並理性討論,謝謝!