Google 地圖平台靜態網頁 API 是一組 HTTP 介面,可產生直接嵌入網頁的圖片。
Google Maps Platform Web 服務是一組 HTTP 介面,可為地圖應用程式提供地理資料。
本指南說明一些常見做法,有助於設定圖片和網路服務要求,以及處理服務回應。如要進一步瞭解 Street View Static API,請參閱開發人員指南。
街景服務 Static API 的運作方式類似靜態 Web API,而中繼資料服務則類似 Web 服務。如要進一步瞭解中繼資料服務,請參閱「街景服務圖片中繼資料」。
什麼是靜態網頁 API?
Google Maps Platform 靜態網頁 API 可讓您在網頁中嵌入 Google 地圖圖片,不需使用 JavaScript 或載入任何動態網頁。靜態網頁 API 會根據使用標準 HTTPS 要求傳送的網址參數建立圖片。
一般的街景服務 Static API 要求格式如下:
https://www.googleapis.com/streetview/z/x/y?parameters
什麼是網路服務?
Google Maps Platform Web 服務是介面,可向外部服務要求 Maps API 資料,並在 Maps 應用程式中使用這些資料。根據《Google Maps Platform 服務條款》中的授權限制,這些服務應與地圖搭配使用。
Maps API Web 服務會使用 HTTP 或 HTTPS 要求,向特定網址傳送網址參數或 JSON 格式的 POST 資料,做為服務的引數。一般來說,這些服務會在回應主體中以 JSON 格式傳回資料,供應用程式剖析或處理。
街景服務 Static API 中繼資料要求的格式如下:
https://maps.googleapis.com/maps/api/streetview/parameters
SSL 和 TLS 存取權
凡是使用 API 金鑰或包含使用者資料的 Google 地圖平台要求,都必須透過 HTTPS 傳送。如果透過 HTTP 提出的要求含有機密資料,可能會遭到拒絕。
建立有效網址
您可能認為網址是否「有效」一眼就能判斷,但實際情況不然。例如,在瀏覽器的網址列內輸入的網址可能包含特殊字元 (例如 "上海+中國");瀏覽器必須在內部將這些字元轉譯為其他編碼方式才能傳送。同理可證,產生或接受 UTF-8 輸入值的任何程式碼都可能會將含有 UTF-8 字元的網址視為「有效網址」,但也需要先轉譯這些字元,才能向外傳送至網路伺服器。這個過程稱為網址編碼或百分比編碼。
特殊字元
所有網址都必須符合統一資源 ID (URI) 規格指定的語法,因此我們必須轉譯特殊字元。實務上,這表示網址只能包含一部分特殊 ASCII 字元:慣用的英數字元符號,以及用做網址內控制字元的部分預留字元。下表摘要列出這些字元:
| 字元集 | 字元 | 網址使用情況 |
|---|---|---|
| 英數字元 | a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 | 文字字串、結構用途 (http)、通訊埠 (8080) 等。 |
| 非預留 | - _ . ~ | 文字字串 |
| 預留 | ! * ' ( ) ; : @ & = + $ , / ? % # [ ] | 控制字元和 (或) 文字字串 |
建立有效網址時,請務必確認網址僅包含表格中列出的字元。如果網址使用上述字元集,通常會導致兩個問題:一個是遺漏問題,一個則是代換問題:
- 您需要處理的字元不屬於上述字元集。舉例來說,外國語言的字元 (例如「
上海+中國」) 就需要使用上述字元加以編碼。依照普遍慣例,空格 (網址內不允許使用) 通常也用加號'+'字元來表示。 - 字元屬於上方字元集中的預留字元,但需要直接使用。舉例來說,網址內會使用
?來表示查詢字串的開頭;如果您想使用「? and the Mysterions」這個字串,就必須對'?'字元進行編碼。
所有字元進行網址編碼時,都會使用 '%' 字元,外加對應至各自 UTF-8 字元的雙字元十六進位值。舉例來說,「上海+中國」以 UTF-8 編碼形式進行網址編碼的結果是 %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B,「? and the Mysterians」字串則是 %3F+and+the+Mysterians 或 %3F%20and%20the%20Mysterians。
需要編碼的常見字元
必須編碼的部分常見字元如下:
| 不安全的字元 | 經過編碼的值 |
|---|---|
| 空格 | %20 |
| " | %22 |
| < | %3C |
| > | %3E |
| # | %23 |
| % | %25 |
| | | %7C |
將使用者輸入內容轉換成網址的過程有時會遇到困難。舉例來說,使用者輸入的地址可能是「5th&Main St.」。一般來說,您應該根據各組成部分來建立網址,並將任何使用者輸入內容當成常值字元來處理。
此外,所有 Google 地圖平台網路服務和 Static Web API 的網址長度上限都是 16, 384 個字元。對於大部分的服務而言,很少出現接近此字元限制的情況。但請注意,某些服務的幾個參數可能會產生較長的網址。
Google API 的禮貌使用
設計不良的 API 用戶端可能會對網際網路和伺服器造成沉重負荷。本節說明 API 用戶端的最佳做法。遵循這些最佳做法,可避免應用程式因不慎濫用 API 而遭到封鎖。
指數輪詢
在極少數情況下,要求可能會發生錯誤;您可能會收到 4xx 或 5xx HTTP 回應代碼,或 TCP 連線可能會在用戶端和 Google 伺服器之間的某個位置失敗。通常,重試要求是值得的,因為後續要求可能會在原始要求失敗時成功。不過,請勿重複向 Google 伺服器提出要求。這種循環行為可能會導致用戶端與 Google 之間的網路超載,造成多方問題。
較好的做法是重試,並在每次重試之間增加延遲時間。每次嘗試時,延遲時間通常會以倍數增加,這種方法稱為指數輪詢。
舉例來說,假設某個應用程式向 Time Zone API 提出以下要求:
https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510×tamp=1331161200&key=YOUR_API_KEY以下 Python 範例說明如何使用指數輪詢提出要求:
import json import time import urllib.error import urllib.parse import urllib.request # The maps_key defined in the following code isn't a valid Google Maps API key. # You need to get your own API key. # See https://developers.google.com/maps/documentation/timezone/get-api-key API_KEY = "YOUR_KEY_HERE" TIMEZONE_BASE_URL = "https://maps.googleapis.com/maps/api/timezone/json" def timezone(lat, lng, timestamp): # Join the parts of the URL together into one string. params = urllib.parse.urlencode( {"location": f"{lat},{lng}", "timestamp": timestamp, "key": API_KEY,} ) url = f"{TIMEZONE_BASE_URL}?{params}" current_delay = 0.1 # Set the initial retry delay to 100ms. max_delay = 5 # Set the maximum retry delay to 5 seconds. while True: try: # Get the API response. response = urllib.request.urlopen(url) except urllib.error.URLError: pass # Fall through to the retry loop. else: # If the request didn't produce an IOError, parse the result. result = json.load(response) if result["status"] == "OK": return result["timeZoneId"] elif result["status"] != "UNKNOWN_ERROR": # Many API errors can't be fixed by a retry, such as # INVALID_REQUEST or ZERO_RESULTS. Don't retry these requests. raise Exception(result["error_message"]) if current_delay > max_delay: raise Exception("Too many retry attempts.") print("Waiting", current_delay, "seconds before retrying.") time.sleep(current_delay) current_delay *= 2 # Increase the delay on each retry. if __name__ == "__main__": tz = timezone(39.6034810, -119.6822510, 1331161200) print(f"Timezone: {tz}")
請確認應用程式呼叫鏈中沒有較高的重試程式碼,以免在短時間內連續傳送重複要求。
同步要求
如果大量同步要求傳送至 Google API,可能會被視為對 Google 基礎架構的分散式阻斷服務 (DDoS) 攻擊,並受到相應處理。為避免這個問題,請確保 API 要求不會在用戶端之間同步。
舉例來說,假設某個應用程式會顯示目前時區的時間。這個應用程式可能會在用戶端作業系統中設定鬧鐘,在每分鐘開始時喚醒系統,以便更新顯示的時間。請勿在應用程式中發出任何 API 呼叫,做為與該鬧鐘相關聯的處理作業。
為回應固定鬧鐘而發出 API 呼叫並非理想做法,因為這會導致 API 呼叫同步到分鐘的開頭 (即使在不同裝置之間),而不是平均分配。如果應用程式設計不佳,就會在每分鐘開始時產生比正常值高 60 倍的流量。
您可以改為設計應用程式,將第二個鬧鐘設定在隨機選擇的時間。當第二個鬧鐘響起時,應用程式會呼叫所需的任何 API 並儲存結果。應用程式在每分鐘開始時更新顯示內容,會使用先前儲存的結果,而不是再次呼叫 API。這樣一來,API 呼叫就會平均分散在一段時間內。此外,API 呼叫不會在螢幕更新時延遲算繪。
除了每分鐘的開始時間外,請勿指定其他常見的同步時間,例如每小時的開始時間和每天午夜。
處理回應
由於無法保證個別回應網路服務要求的確切格式 (某些元素可能遺失或位於多個位置),因此請勿假設任何指定回應傳回的格式與不同查詢相同。請改為處理回應,並使用運算式選取適當的值。
本節說明如何從網路服務回應中動態擷取這些值。
Google 地圖網路服務提供的回應雖然容易理解,但並不方便使用者閱讀。執行查詢時,您可能想擷取幾個特定值,而不是顯示一組資料。一般來說,請剖析網路服務的回應,並只擷取您感興趣的值。
剖析配置取決於是否以 JSON 格式傳回輸出內容。JSON 回應本身就是 JavaScript 物件,因此可在用戶端上直接透過 JavaScript 處理。