Adresy geograficzne w pliku KML

Mano Marks, Google Geo Team
Autor: grudzień 2007 r.
Aktualizacja: grudzień 2013 r.

Cel

Ten samouczek jest przeznaczony dla programistów, którzy znają języki programowania i chcą dowiedzieć się, jak korzystać z interfejsu API Google Geocoding do geokodowania adresów i umieszczania ich w pliku KML. Chociaż przykłady kodu są dostępne w języku Python, można je łatwo dostosować do większości języków programowania.

Geokodowanie to proces konwertowania adresu na zestaw długości i szerokości geograficznej, co umożliwia wskazanie adresów na mapie. Warto geokodować adresy i umieszczać je bezpośrednio w pliku KML. Takie sytuacje są częste, na przykład gdy dane są wprowadzane w formularzu i generujesz pliki KML w odpowiedzi na żądania. Pliki KML mogą być przechowywane w bazie danych, systemie plików lub zwrócone do NetworkLink, który łączy się z Twoim plikiem. Podczas korzystania z tej metody musisz przestrzegać Warunków korzystania z usługi interfejsu Geocode API, ponieważ obowiązują pewne ograniczenia dotyczące czasu przechowywania wyników oraz liczby elementów, które możesz przetworzyć na dane geograficzne każdego dnia.

W tym samouczku pokazujemy, jak użyć Pythona, aby pobrać ciąg „1600 Amphitheatre Pkwy, Mountain View, CA 94043” i przekształcić go w ten:

<?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, dzięki czemu do utworzenia dokumentu KML możemy używać języka Python z wbudowanymi funkcjami xml.dom.minidom. Minimalem Pythona jest implementacja DOM. Jest on obsługiwany w większości języków programowania, więc przeniesienie go do innego języka programowania powinno być łatwe. Aby to zrobić:

  1. Utwórz dokument za pomocą xml.dom.minidom.Document() w Pythonie.
  2. Utwórz element główny <kml> za pomocą createElementNS.
  3. Dołącz go do dokumentu za pomocą polecenia appendChild.
  4. Utwórz element w dokumencie za pomocą createElement.
  5. Dołącz go do elementu <kml> za pomocą appendChild.
  6. Dla każdego adresu utwórz element <Placemark> za pomocą atrybutu createElement i dołącz go do elementu Document. Następnie utwórz element <description>, przypisz mu wartość adresu i dołącz go do elementu <Placemark>.
  7. Utwórz element <Point>, dodaj podrzędny element <coordinates> i dołącz go do elementu <Placemark>.
  8. Wyślij adres do Geokodera interfejsu API Map Google, który wyśle odpowiedź w formacie JSON lub XML. Użyj urllib.urlopen(), aby pobrać plik i odczytać go w ciągu znaków.
  9. Przeanalizuj odpowiedź i wyodrębnij elementy długości i szerokości geograficznej.
  10. Utwórz węzeł tekstowy w elemencie <coordinates> i przypisz jego długość i szerokość geograficzną jako jego wartość.
  11. Zapisz dokument KML w pliku tekstowym.

Przykładowy kod w Pythonie

Przykładowy kod poniżej zawiera fikcyjną zmienną mapsKey – musisz zastąpić ten klucz własnym kluczem.

Poniżej znajduje się przykładowy kod do geokodowania w języku Python 2.7 i pliku 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 a  element.
  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

Czas wykonywania żądań danych geograficznych

Żądania geokodowania będą podlegać maksymalnym dziennym limitom liczby zapytań geokodera. Więcej informacji na temat tych ograniczeń znajdziesz w dokumentacji interfejsu Google Geocoding API. Aby mieć pewność, że zapytania nie będą wysyłane zbyt szybko do geokodera, możesz określić opóźnienie między poszczególnymi żądaniami geokodowania. Możesz zwiększyć to opóźnienie za każdym razem, gdy otrzymasz stan OVER_QUERY_LIMIT, i użyć pętli while, aby mieć pewność, że kod został przetworzony prawidłowo, zanim przejdziesz do następnego.

Zmiana kraju podstawowego

Geokoder zaprogramuje wyniki odpowiednio do domeny źródłowej. Na przykład wpisanie „syracuse” w polu wyszukiwania na maps.google.com spowoduje wysłanie danych geograficznych do „Syracuse w Nowym Jorku”, a to samo zapytanie na maps.google.it (domenie włoskiej) znajdzie na Sycylii miasto „Siracusa”. Aby uzyskać te same wyniki, wysyłaj zapytanie przez geokodowanie HTTP do maps.google.it zamiast maps.google.com. Możesz to zrobić, zmieniając zmienną mapsUrl w przykładowym kodzie powyżej. Aby dowiedzieć się więcej o Promowanie ze względu na region, zapoznaj się z dokumentacją interfejsu Geocoding API.

Uwaga: nie możesz wysłać żądania do nieistniejącego serwera map.google.*, dlatego zanim przekierujesz na to zapytanie geokodowania, sprawdź, czy istnieje domena krajowa. Pomoc dotyczącą geokodowania według krajów znajdziesz w tym poście.

Podsumowanie

Powyższy kod pozwala teraz przetworzyć dane geograficzne za pomocą Pythona, utworzyć z niego plik KML (<Placemark>) i zapisać go na dysku. Jeśli okaże się, że musisz przetworzyć geograficznie więcej adresów dziennie, niż pozwala na to limit lub geokoder Google nie uwzględnia interesujących Cię regionów, rozważ skorzystanie z dodatkowych usług geokodowania.

Teraz już wiesz, jak geokodować adresy, więc zapoznaj się z artykułami o używaniu plików KML w Edytorze Google Mashup oraz o tworzeniu plików KML przy użyciu języka PHP i MySQL. Jeśli masz pytania lub problemy dotyczące tego samouczka, zadaj je na forum Stack Overflow.