Autor: Diciembre de 2007
Actualización: Diciembre de 2013
Objetivo
Este instructivo está dirigido a desarrolladores que conocen los lenguajes de secuencias de comandos y desean aprender a usar la API de Geocoding de Google para geocodificar direcciones y, luego, incorporarlas en un archivo KML. Si bien las muestras de código se presentan en Python, se pueden adaptar con bastante facilidad a la mayoría de los otros lenguajes de programación.
La geocodificación es el proceso de convertir una dirección en un conjunto de coordenadas de latitud y longitud, lo que permite indicar direcciones en un mapa. Es posible que desees geocodificar direcciones y colocarlas directamente en un archivo KML. Esto es común, por ejemplo, cuando se ingresan datos en un formulario y se generan archivos KML en respuesta a las solicitudes. Estos archivos KML se pueden almacenar en una base de datos, en un sistema de archivos o se pueden devolver a un NetworkLink que se conecte a tu archivo. Ten en cuenta que, cuando uses esta técnica, debes cumplir con las Condiciones del Servicio de la API de Geocoding, ya que existen algunas limitaciones sobre el tiempo durante el que se pueden almacenar los resultados, así como la cantidad de elementos que puedes geocodificar cada día.
En este instructivo, se muestra cómo usar Python para convertir la cadena "1600 Amphitheatre Pkwy, Mountain View, CA 94043
" en lo siguiente:
<?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>
Crea un documento KML
KML es un lenguaje de marcado XML, por lo que podemos usar las funciones integradas xml.dom.minidom de Python para crear un documento KML. minidom de Python es una implementación de DOM, y DOM se admite en la mayoría de los lenguajes de programación, por lo que este proceso debería ser fácil de portar a otro lenguaje de programación. A continuación, se indican los pasos que debes seguir:
- Crea el documento con
xml.dom.minidom.Document()
de Python. - Crea el elemento raíz
<kml>
concreateElementNS.
. - Agrégalo al documento con
appendChild
. - Crea un elemento Document con
createElement
. - Anéxalo al elemento
<kml>
conappendChild
. - Para cada dirección, crea un elemento
<Placemark>
concreateElement
y agrégalo al elementoDocument
. Luego, crea un elemento<description>
, asígnale el valor de la dirección y agrégalo al elemento<Placemark>
. - Crea un elemento
<Point>
, agrega un elemento secundario<coordinates>
y agrégalo al elemento<Placemark>
. - Envía la dirección al codificador geográfico de la API de Maps, que envía una respuesta en formato JSON o XML.
Usa
urllib.urlopen()
para recuperar el archivo y leerlo en una cadena. - Analiza la respuesta y extrae los elementos de longitud y latitud.
- Crea un nodo de texto en el elemento
<coordinates>
y asígnale la cadena de longitud y latitud como su valor. - Escribe el documento KML en un archivo de texto.
Código de Python de muestra
Ten en cuenta que el siguiente código de ejemplo usa una variable mapsKey ficticia. Deberás reemplazar esta clave por tu propia clave.
A continuación, se muestra un ejemplo de código para la geocodificación con Python 2.7 y salida 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')
Otros aspectos que debes tener en cuenta
Cómo cronometrar las solicitudes de Geocoding
Las solicitudes de geocodificación estarán sujetas a los límites diarios máximos de la tasa de consultas del geocodificador. Consulta la documentación de la API de Google Geocoding para obtener más información sobre estos límites. Para asegurarte de no enviar consultas demasiado rápido al geocodificador, puedes especificar una demora entre cada solicitud de geocodificación. Puedes aumentar este retraso cada vez que recibas un estado OVER_QUERY_LIMIT
y usar un bucle while
para asegurarte de haber geocodificado correctamente una dirección antes de iterar a la siguiente.
Cómo cambiar el país base
El geocodificador está programado para sesgar sus resultados según el dominio de origen.
Por ejemplo, si ingresas "Syracuse" en el cuadro de búsqueda de maps.google.com, se geocodificará la ciudad de "Syracuse, NY", mientras que, si ingresas la misma búsqueda en maps.google.it (el dominio de Italia), se encontrará la ciudad de "Siracusa" en Sicilia. Obtendrías los mismos resultados si enviaras esa búsqueda a través de la geocodificación HTTP a maps.google.it en lugar de maps.google.com, lo que puedes hacer modificando la variable mapsUrl
en el código de ejemplo anterior.
Consulta la documentación de la API de Geocoding para obtener más información sobre el ajuste regional.
Nota: No puedes enviar una solicitud a un servidor maps.google.* que no existe, así que asegúrate de que exista un dominio de país antes de redireccionar tus consultas de geocodificación a él. Para obtener información sobre la compatibilidad con la geocodificación por país, consulta esta publicación.
Conclusión
Con el código anterior, ahora puedes geocodificar una dirección con Python, crear un objeto <Placemark>
de KML a partir de ella y guardarla en el disco. Si descubres que necesitas geocodificar más direcciones por día de lo que permiten los límites, o que el geocodificador de Google no cubre las regiones que te interesan, considera usar servicios web de geocodificación adicionales.
Ahora que sabes cómo geocodificar tus direcciones, consulta los artículos sobre Cómo usar KML en Google Mashup Editor y Cómo usar PHP y MySQL para crear KML. Si tienes algún problema o pregunta sobre este instructivo, publícalo en el foro de Stack Overflow.