Geocodifica degli indirizzi da utilizzare in KML

Mano Marks, team Google Geo
Autore: dicembre 2007
Aggiornamento: dicembre 2013

Obiettivo

Questo tutorial è rivolto agli sviluppatori che hanno familiarità con i linguaggi di scripting e vogliono imparare a utilizzare l'API Google Geocoding per geocodificare gli indirizzi e incorporarli in un file KML. Sebbene gli esempi di codice siano presentati in Python, possono essere adattati abbastanza facilmente alla maggior parte degli altri linguaggi di programmazione.

La geocodifica è il processo di conversione di un indirizzo in un insieme di coordinate di latitudine/longitudine, che consente di indicare gli indirizzi su una mappa. Potresti voler geocodificare gli indirizzi e inserirli direttamente in un file KML. Questo è comune, ad esempio, quando i dati vengono inseriti in un modulo e vengono generati file KML in risposta alle richieste. Questi file KML potrebbero essere memorizzati in un database, in un file system o restituiti a un NetworkLink che si connette al file. Tieni presente che quando utilizzi questa tecnica, devi rispettare i Termini di servizio dell'API Geocoding, in quanto esistono alcune limitazioni relative al periodo di tempo per cui i risultati possono essere archiviati, nonché al numero di elementi che puoi geocodificare ogni giorno.

Questo tutorial mostra come utilizzare Python per trasformare la stringa "1600 Amphitheatre Pkwy, Mountain View, CA 94043" in questo modo:

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

Creare un documento KML

KML è un linguaggio di markup XML, quindi possiamo utilizzare le funzioni xml.dom.minidom integrate di Python per creare un documento KML. minidom di Python è un'implementazione DOM e DOM è supportato nella maggior parte dei linguaggi di programmazione, quindi questo processo dovrebbe essere facile da trasferire in un altro linguaggio di programmazione. Procedi nel seguente modo:

  1. Crea il documento utilizzando xml.dom.minidom.Document() di Python.
  2. Crea l'elemento radice <kml> utilizzando createElementNS.
  3. Aggiungilo al documento utilizzando appendChild.
  4. Crea un elemento Documento utilizzando createElement.
  5. Aggiungilo all'elemento <kml> utilizzando appendChild.
  6. Per ogni indirizzo, crea un elemento <Placemark> utilizzando createElement e aggiungilo all'elemento Document. Poi, crea un elemento <description>, assegnagli il valore dell'indirizzo e aggiungilo all'elemento <Placemark>.
  7. Crea un elemento <Point>, aggiungi un elemento secondario <coordinates> e aggiungilo all'elemento <Placemark>.
  8. Invia l'indirizzo al geocodificatore dell'API Maps, che invia una risposta in formato JSON o XML. Utilizza urllib.urlopen() per recuperare il file e leggerlo in una stringa.
  9. Analizza la risposta ed estrai gli elementi di longitudine e latitudine.
  10. Crea un nodo di testo nell'elemento <coordinates> e assegna la stringa di longitudine/latitudine come valore.
  11. Scrivi il documento KML in un file di testo.

Codice Python di esempio

Tieni presente che il codice di esempio riportato di seguito utilizza una variabile mapsKey fittizia. Dovrai sostituire questa chiave con la tua chiave.

Di seguito è mostrato un codice campione per il geocoding con Python 2.7 e output 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')

Altri aspetti da considerare

Tempistica delle richieste di geocodifica

Le richieste di geocodifica saranno soggette ai limiti giornalieri della frequenza massima di query del geocoder. Per ulteriori informazioni su questi limiti, consulta la documentazione dell'API Google Geocoding. Per assicurarti di non inviare query troppo rapidamente al geocodificatore, puoi specificare un ritardo tra ogni richiesta di geocodifica. Puoi aumentare questo ritardo ogni volta che ricevi uno stato OVER_QUERY_LIMIT e utilizzare un ciclo while per assicurarti di aver geocodificato correttamente un indirizzo prima di passare al successivo.

Modificare il paese di base

Il geocoder è programmato per distorcere i risultati a seconda del dominio di origine. Ad esempio, se inserisci "Siracusa" nella casella di ricerca su maps.google.com, verrà geocodificata la città di "Syracuse, NY", mentre se inserisci la stessa query su maps.google.it (il dominio italiano), verrà trovata la città di "Siracusa" in Sicilia. Otterresti gli stessi risultati inviando la query tramite geocodifica HTTP a maps.google.it anziché a maps.google.com, cosa che puoi fare modificando la variabile mapsUrl nel codice di esempio riportato sopra. Per ulteriori informazioni sul region biasing, consulta la documentazione dell'API Geocoding.

Nota:non puoi inviare una richiesta a un server maps.google.* inesistente, quindi assicurati che esista un dominio nazionale prima di reindirizzare le query di geocodifica. Per informazioni sul supporto del geocodice per paese, consulta questo post.

Conclusione

Utilizzando il codice riportato sopra, ora puoi geocodificare un indirizzo utilizzando Python, creare un file KML <Placemark> e salvarlo su disco. Se ti accorgi di dover geocodificare più indirizzi al giorno rispetto a quanto consentito dai limiti o che il geocoder di Google non copre le regioni che ti interessano, valuta la possibilità di utilizzare servizi web di geocodifica aggiuntivi.

Ora che sai come geocodificare gli indirizzi, consulta gli articoli su Utilizzo di KML in Google Mashup Editor e Utilizzo di PHP e MySQL per creare KML. Se hai problemi o domande su questo tutorial, pubblicale nel forum di Stack Overflow.