作者:2007 年 12 月
更新日期:2013 年 12 月
目標
本教學課程適用於熟悉指令碼語言的開發人員,且想要瞭解如何使用 Google Geocoding API 為地址進行地理編碼,並將這些地址整合至 KML 檔案。雖然程式碼範例是在 Python 中呈現,但也能輕鬆適應大多數其他程式設計語言。
「地理編碼」是將地址轉換為一組經緯度座標的程序,能讓您在地圖上顯示地址。您可以針對地址進行地理編碼,並直接將這些地址放入 KML 檔案這很常見,例如在表單中輸入資料時,而且您為了回應要求而產生 KML 檔案。這些 KML 檔案可以儲存在資料庫或檔案系統中,也可以傳回與檔案連結的 NetworkLink。請注意,使用這項技術時,您必須遵守 Geocoding API 的《服務條款》,因為儲存結果的時間有一些限制,以及您每天可以進行剖析的元素數量。
本教學課程說明如何使用 Python 擷取「1600 Amphitheatre Pkwy, Mountain View, CA 94043
」字串,並將其轉換為字串:
<?xml version='1.0' encoding='UTF-8'?>
<kml xmlns='http://earth.google.com/kml/2.2'>
<Document>
<Placemark>
<description>1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA</description>
<Point>
<coordinates>-122.081783,37.423111,0</coordinates>
</Point>
</Placemark>
</Document>
</kml>
建立 KML 文件
KML 是 XML 標記語言,因此我們可以使用 Python 內建的 xml.dom.minidom 函式建立 KML 文件。Python 的最簡單之處為 DOM 實作,且大多數程式設計語言都支援 DOM,因此這項程序應可輕鬆轉移至其他程式設計語言。步驟如下:
- 使用 Python 的
xml.dom.minidom.Document()
建立文件。 - 使用
createElementNS.
建立根<kml>
元素 - 使用
appendChild
將文件附加到文件。 - 使用
createElement
建立 Document 元素。 - 使用
appendChild
將其附加到<kml>
元素。 - 針對每個位址,使用
createElement
建立<Placemark>
元素,並將其附加至Document
元素。接著建立<description>
元素,並為其指派位址的值,然後將該元素附加到<Placemark>
元素中。 - 建立
<Point>
元素,新增子項<coordinates>
元素並附加至<Placemark>
元素。 - 將地址傳送到 Maps API 地理編碼器;這個地理編碼器會以 JSON 或 XML 傳送回應。使用
urllib.urlopen()
擷取檔案並讀取為字串。 - 剖析回應並擷取經度和緯度元素。
- 在
<coordinates>
元素中建立文字節點,並將經度/緯度字串指定為其值。 - 將 KML 文件寫入文字檔案。
Python 程式碼範例
請注意,以下程式碼範例使用的是虛擬 mapsKey 變數,您需要將這個金鑰替換成自己的金鑰。
以下示範使用 Python 2.7 和 JSON 輸出進行地理編碼的程式碼範例:
import urllib import xml.dom.minidom import json def geocode(address, sensor=False): # This function queries the Google Maps API geocoder with an # address. It gets back a csv file, which it then parses and # returns a string with the longitude and latitude of the address. # This isn't an actual maps key, you'll have to get one yourself. # Sign up for one here: https://code.google.com/apis/console/ mapsKey = 'abcdefgh' mapsUrl = 'https://maps.googleapis.com/maps/api/geocode/json?address=' # This joins the parts of the URL together into one string. url = ''.join([mapsUrl,urllib.quote(address),'&sensor=',str(sensor).lower()]) #'&key=',mapsKey]) jsonOutput = str(urllib.urlopen(url).read ()) # get the response # fix the output so that the json.loads function will handle it correctly jsonOutput=jsonOutput.replace ("\\n", "") result = json.loads(jsonOutput) # converts jsonOutput into a dictionary # check status is ok i.e. we have results (don't want to get exceptions) if result['status'] != "OK": return "" coordinates=result['results'][0]['geometry']['location'] # extract the geometry return str(coordinates['lat'])+','+str(coordinates['lng']) def createKML(address, fileName): # This function creates an XML document and adds the necessary # KML elements. kmlDoc = xml.dom.minidom.Document() kmlElement = kmlDoc.createElementNS('http://earth.google.com/kml/2.2','kml') kmlElement = kmlDoc.appendChild(kmlElement) documentElement = kmlDoc.createElement('Document') documentElement = kmlElement.appendChild(documentElement) placemarkElement = kmlDoc.createElement('Placemark') descriptionElement = kmlDoc.createElement('description') descriptionText = kmlDoc.createTextNode(address) descriptionElement.appendChild(descriptionText) placemarkElement.appendChild(descriptionElement) pointElement = kmlDoc.createElement('Point') placemarkElement.appendChild(pointElement) coorElement = kmlDoc.createElement('coordinates') # This geocodes the address and adds it to aelement. coordinates = geocode(address) coorElement.appendChild(kmlDoc.createTextNode(coordinates)) pointElement.appendChild(coorElement) documentElement.appendChild(placemarkElement) # This writes the KML Document to a file. kmlFile = open(fileName, 'w') kmlFile.write(kmlDoc.toprettyxml(' ')) kmlFile.close() if __name__ == '__main__': createKML('1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA', 'google.kml')
其他注意事項
計時地理編碼要求
地理編碼要求將取決於地理編碼器的每日查詢上限。如要進一步瞭解這些限制,請參閱 Google Geocoding API 說明文件。為避免傳送查詢的速度過快至地理編碼器,您可以指定每個地理編碼要求之間的延遲時間。每次收到 OVER_QUERY_LIMIT
狀態時,您都可以增加此延遲時間,並使用 while
迴圈,以確保在疊代到下一個地址之前,已成功完成地址的地理編碼。
變更基準國家
地理編碼器經過編碼後,會根據原始網域調整結果。
舉例來說,在 maps.google.com 的搜尋框中輸入「syracuse」,即可在「Syracuse, NY」中為城市進行地理編碼,而在 maps.google.it (義大利網域) 輸入相同的查詢,就可以找到西西里市的「Siracusa」城市。透過 HTTP 地理編碼將查詢傳送至 maps.google.it,而非 maps.google.com,這樣就能取得相同的結果,只要修改上述程式碼範例中的 mapsUrl
變數即可。如要進一步瞭解區域自訂調整,請參閱 Geocoding API 說明文件。
注意:您無法將要求傳送至不存在的 maps.google.* 伺服器,因此請務必先將國家/地區網域存在,再為您的地理編碼查詢進行重新導向。如需各國家/地區的地理編碼支援,請查看這篇文章。
結語
使用上述程式碼,您現在可以使用 Python 為地址進行地理編碼,再使用其中建立 KML <Placemark>
並將其儲存到磁碟。如果您發現每天需要對更多地址進行地理編碼,因而超出上限,或是 Google 地理編碼器未涵蓋所需地區,請考慮使用其他額外的網路服務。
現在,您已經知道如何將地址進行地理編碼,請參閱在 Google Mashup Editor 中使用 KML及使用 PHP 和 MySQL 建立 KML 一文。如果您在教學課程中有任何疑問或有任何疑問,請前往 Stack Overflow 論壇張貼問題。