Geocodierung von Adressen für die Verwendung in KML

Mano Marks, Google Geo-Team
Erstellt: Dezember 2007
Aktualisiert: Dezember 2013

Ziel

Diese Anleitung richtet sich an Entwickler, die mit Skriptsprachen vertraut sind und wissen möchten, wie sie mit der Google Geocoding API Adressen geocodieren und in eine KML-Datei einbinden können. Die Codebeispiele werden in Python dargestellt, lassen sich jedoch problemlos an die meisten anderen Programmiersprachen anpassen.

Geocoding bezeichnet die Umwandlung einer Adresse in eine Gruppe von Breiten- und Längengradkoordinaten, damit Adressen auf einer Karte dargestellt werden können. Sie können Adressen geocodieren und direkt in eine KML-Datei einfügen. Das ist z. B. üblich, wenn Daten in ein Formular eingegeben werden und Sie KML-Dateien als Antwort auf Anfragen generieren. Diese KML-Dateien können in einer Datenbank oder in einem Dateisystem gespeichert oder an einen NetworkLink zurückgegeben werden, der eine Verbindung zu Ihrer Datei herstellt. Beachten Sie, dass Sie bei der Verwendung dieser Technik die Nutzungsbedingungen für die Geocoding API einhalten müssen, da es einige Zeitbeschränkungen gibt, für die die Ergebnisse gespeichert werden können, und wie viele Elemente Sie pro Tag geocodieren können.

In dieser Anleitung erfahren Sie, wie Sie mit Python den String „1600 Amphitheatre Pkwy, Mountain View, CA 94043“ in Folgendes umwandeln:

<?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-Dokument erstellen

KML ist eine XML-Markup-Sprache. Daher können wir mit den integrierten Python-Funktionen von xml.dom.minidom ein KML-Dokument erstellen. Die Miniaturversion von Python ist eine DOM-Implementierung. DOM wird in den meisten Programmiersprachen unterstützt. Daher sollte dieser Vorgang einfach in eine andere Programmiersprache portiert werden können. Und so gehts:

  1. Erstellen Sie das Dokument mit xml.dom.minidom.Document() von Python.
  2. Erstellen Sie das Stammelement <kml> mit createElementNS.
  3. Hängen Sie es mithilfe von appendChild an das Dokument an.
  4. Erstellen Sie ein Dokumentelement mit createElement.
  5. Hängen Sie es mithilfe von appendChild an das Element <kml> an.
  6. Erstellen Sie für jede Adresse ein <Placemark>-Element mit createElement und hängen Sie es an das Document-Element an. Erstellen Sie dann ein <description>-Element, weisen Sie ihm den Wert der Adresse zu und hängen Sie es an das <Placemark>-Element an.
  7. Erstellen Sie ein <Point>-Element, fügen Sie ein untergeordnetes <coordinates>-Element hinzu und hängen Sie es an das <Placemark>-Element an.
  8. Senden Sie die Adresse an den Geocoder der Maps API, der eine Antwort im JSON- oder XML-Format sendet. Verwenden Sie urllib.urlopen(), um die Datei abzurufen und in einen String zu lesen.
  9. Parst die Antwort und extrahiert die Längen- und Breitengradelemente.
  10. Erstellen Sie einen Textknoten im Element <coordinates> und weisen Sie den String für Längen- und Breitengrad als Wert zu.
  11. Schreiben Sie das KML-Dokument in eine Textdatei.

Python-Beispielcode

Im folgenden Beispielcode wird eine Dummy-MapsKey-Variable verwendet. Sie müssen diesen Schlüssel durch Ihren eigenen Schlüssel ersetzen.

Im Folgenden sehen Sie Beispielcode für das Geocoding mit Python 2.7 und der JSON-Ausgabe:

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')

Weitere wichtige Punkte

Zeitliche Abfolge der Geocodierungsanforderungen

Für Geocoding-Anfragen gelten die maximalen Tageslimits für die Abfragerate. Weitere Informationen zu diesen Limits finden Sie in der Dokumentation zur Google Geocoding API. Damit Abfragen nicht zu schnell an den Geocoder gesendet werden, können Sie zwischen den einzelnen Geocode-Anfragen eine Verzögerung angeben. Sie können diese Verzögerung jedes Mal erhöhen, wenn Sie einen OVER_QUERY_LIMIT-Status erhalten, und mit einer while-Schleife prüfen, ob Sie eine Adresse erfolgreich geocodiert haben, bevor Sie zur nächsten gelangen.

Änderung des zugrunde liegenden Landes

Der Geocoder ist so programmiert, dass die Ergebnisse je nach Ursprungsdomain gewichtet werden. Wenn Sie beispielsweise „syracuse“ in das Suchfeld auf maps.google.com eingeben, wird die Stadt „Syracuse, NY“ geocodiert, während dieselbe Abfrage auf maps.google.it (Domain von Italien) zurückgegeben wird, wird die Stadt „Siracusa“ auf Sizilien gefunden. Sie erhalten dieselben Ergebnisse, wenn Sie die Abfrage über die HTTP-Geocodierung an maps.google.it statt an maps.google.com senden. Dazu ändern Sie einfach die Variable mapsUrl im Beispielcode oben. Weitere Informationen finden Sie in der Geocoding API-Dokumentation.

Hinweis:Sie können keine Anfrage an einen nicht vorhandenen „maps.google.*“-Server senden. Achten Sie also darauf, dass eine länderspezifische Domain vorhanden ist, bevor Sie Ihre Geocoding-Abfragen an sie weiterleiten. Informationen zur Geocodierung nach Land findest du in diesem Beitrag.

Fazit

Mit dem obigen Code kannst du jetzt mit Python eine Adresse geocodieren, daraus eine KML-<Placemark> erstellen und sie auf dem Laufwerk speichern. Wenn Sie feststellen, dass Sie mehr Adressen pro Tag geocodieren müssen, als die Limits zulassen, oder der Google-Geocoder die gewünschten Regionen nicht umfasst, können Sie zusätzliche Geocoding-Webdienste verwenden.

Nachdem Sie nun wissen, wie Sie Ihre Adressen geocodieren, lesen Sie die Artikel KML im Google Mashup Editor verwenden und PHP und MySQL zum Erstellen von KML verwenden. Wenn Sie Probleme mit oder Fragen zu dieser Anleitung haben, posten Sie sie im Stack Overflow-Forum.