Try   HackMD

Google Maps API 教學


撰文時間: 2022/7/18


參考文章:運用Google Map API(Distance Matrix Service)取得旅程時間及距離


Install

使用任何可以發出http請求的套件即可,這邊以python的requests為例。其實Google Maps API有開發不同語言的SDK可以直接安裝使用,相對來講較為直觀,可以直接使用SDK裡面包好的function call,但這邊先以較為基礎原始的requests作為範例。

在使用前要先去Google Cloud Platform (GCP) 開通一個API Key
流程為:

  1. 在GCP啟動一個專案,並為這個專案開通一個Google Maps API Key
  2. 創建後,在左側的選單欄選擇Google地圖平台來使用Google Maps相關的服務,會跳出視窗告知你的API Key,按下前往後如果你有打勾啟動所有的話就會啟動所有的API,如果有需要後續可以自己在API列表停用不需要的API

    如上圖,可以看到所有啟用的API,點進去後就可以在右上角停用
  3. 接著就可以開始看各個API需要的request跟response了!

Usage

這邊以GeocodingDistance Matrix為例子,詳細內容可以在連結的官方文件中看到。

Geocoding

這個API主要的目標在於提供特定地點的座標位置,因此主要輸入包含地址、plus code (一種標記地點的編碼)等等。然而這個API也有提供反geocoding的服務,也就是提供座標位置(經緯度),可以反向查詢他的地址。

要向這個API發出請求,可以使用requests,範例程式碼如下:

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如下:

{
  "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裏面了

DistanceMatrix

這個API主要的服務為計算出發點與終點之間的距離以及所需時間,其中包含不同移動方式的選項。
要對這個API發出request,範例程式碼如下:

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為例:

{
  "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'設成

'origins':'台北市中正區黎明里北平西路3號|台北市信義區信義路五段7號'

這樣子得到的response就會是:

{
  "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,最基礎的版本一樣是每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 request.
  • 1000 elements per second (EPS), calculated as the sum of client-side and server-side queries.

以上為我個人測試與學習過程的一些紀錄,若有錯誤歡迎不吝指正並理性討論,謝謝!