Autor: grudzień 2007 r.
Aktualizacja: grudzień 2013 r.
Cel
Ten samouczek jest przeznaczony dla programistów, którzy znają języki skryptowe i chcą się dowiedzieć, jak używać interfejsu Google Geocoding API do geokodowania adresów i włączania ich do pliku KML. Przykłady kodu są podane w języku Python, ale można je dość łatwo dostosować do większości innych języków programowania.
Geokodowanie to proces przekształcania adresu w zestaw współrzędnych geograficznych (szerokości i długości), co umożliwia wskazywanie adresów na mapie. Możesz chcieć geokodować adresy i umieszczać je bezpośrednio w pliku KML. Jest to powszechne na przykład wtedy, gdy dane są wprowadzane do formularza, a w odpowiedzi na żądania generujesz pliki KML. Te pliki KML mogą być przechowywane w bazie danych, systemie plików lub zwracane do elementu NetworkLink, który łączy się z Twoim plikiem. Pamiętaj, że korzystając z tej techniki, musisz przestrzegać Warunków korzystania z usługi Geocoding API, ponieważ istnieją pewne ograniczenia dotyczące czasu, przez jaki można przechowywać wyniki, a także liczby elementów, które można geokodować każdego dnia.
Z tego samouczka dowiesz się, jak za pomocą Pythona przekształcić ciąg znaków „1600 Amphitheatre Pkwy, Mountain View, CA 94043
” w ten sposób:
<?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>
Tworzenie dokumentu KML
KML to język znaczników XML, więc do utworzenia dokumentu KML możemy użyć wbudowanych funkcji Pythona xml.dom.minidom. Minidom w Pythonie to implementacja DOM, a DOM jest obsługiwany w większości języków programowania, więc ten proces powinien być łatwy do przeniesienia do innego języka programowania. Aby to zrobić:
- Utwórz dokument za pomocą funkcji
xml.dom.minidom.Document()
w Pythonie. - Utwórz element główny
<kml>
za pomocącreateElementNS.
- Dołącz go do dokumentu za pomocą tagu
appendChild
. - Utwórz element Document za pomocą
createElement
. - Dodaj go do elementu
<kml>
za pomocąappendChild
. - Dla każdego adresu utwórz element
<Placemark>
za pomocą elementucreateElement
i dołącz go do elementuDocument
. Następnie utwórz element<description>
, przypisz mu wartość adresu i dołącz go do elementu<Placemark>
. - Utwórz element
<Point>
, dodaj element podrzędny<coordinates>
i dołącz go do elementu<Placemark>
. - Wyślij adres do usługi Geocoder interfejsu Maps API, która zwraca odpowiedź w formacie JSON lub XML.
Użyj
urllib.urlopen()
, aby pobrać plik i odczytać go jako ciąg znaków. - Przeanalizuj odpowiedź i wyodrębnij elementy długości i szerokości geograficznej.
- Utwórz węzeł tekstowy w elemencie
<coordinates>
i przypisz mu ciąg znaków z długością i szerokością geograficzną. - Zapisz dokument KML w pliku tekstowym.
Przykładowy kod w Pythonie
Pamiętaj, że w przykładowym kodzie poniżej użyto zmiennej mapsKey, która jest tylko symbolem zastępczym. Musisz ją zastąpić własnym kluczem.
Poniżej znajdziesz przykładowy kod geokodowania w Pythonie 2.7 z danymi wyjściowymi w formacie 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')
Inne kwestie do rozważenia
Określanie czasu żądań geokodowania
Żądania geokodowania będą podlegać dziennym limitom maksymalnej liczby zapytań geokodera. Więcej informacji o tych limitach znajdziesz w dokumentacji interfejsu Google Geocoding API. Aby mieć pewność, że nie wysyłasz zapytań do geokodera zbyt szybko, możesz określić opóźnienie między poszczególnymi żądaniami geokodowania. Możesz zwiększać to opóźnienie za każdym razem, gdy otrzymasz stan OVER_QUERY_LIMIT
, i używać pętli while
, aby mieć pewność, że adres został prawidłowo geokodowany, zanim przejdziesz do następnego.
Zmiana kraju podstawowego
Geokoder jest zaprogramowany tak, aby faworyzować wyniki w zależności od domeny źródłowej.
Na przykład wpisanie „syracuse” w polu wyszukiwania na stronie maps.google.com spowoduje geokodowanie miasta „Syracuse, NY”, a wpisanie tego samego zapytania na stronie maps.google.it (domena włoska) spowoduje znalezienie miasta „Siracusa” na Sycylii. Otrzymasz te same wyniki, wysyłając to zapytanie za pomocą geokodowania HTTP do maps.google.it zamiast do maps.google.com. Możesz to zrobić, modyfikując zmienną mapsUrl
w przykładowym kodzie powyżej.
Więcej informacji o określaniu regionu znajdziesz w dokumentacji interfejsu Geocoding API.
Uwaga: nie możesz wysłać żądania do nieistniejącego serwera maps.google.*, więc przed przekierowaniem do niego zapytań o geokodowanie upewnij się, że domena kraju istnieje. Informacje o obsłudze geokodowania w poszczególnych krajach znajdziesz w tym poście.
Podsumowanie
Korzystając z powyższego kodu, możesz teraz geokodować adres za pomocą Pythona, tworzyć z niego plik KML<Placemark>
i zapisywać go na dysku. Jeśli okaże się, że musisz geokodować więcej adresów dziennie, niż pozwalają na to limity, lub że geokoder Google nie obejmuje interesujących Cię regionów, rozważ użycie dodatkowych internetowych usług geokodowania.
Teraz, gdy wiesz już, jak geokodować adresy, zapoznaj się z artykułami Korzystanie z KML w Edytorze Mashupów Google i Tworzenie KML za pomocą PHP i MySQL. Jeśli masz problemy z tym samouczkiem lub pytania dotyczące niego, opublikuj je na forum Stack Overflow.