Geocodificação de endereços para uso em KML

Mano Marks, equipe do Google Geo
Criado em: dezembro de 2007
Atualizado em: dezembro de 2013

Objetivo

Este tutorial é destinado a desenvolvedores que conhecem linguagens de script e querem aprender a usar a API Google Geocoding para geocodificar endereços e incorporá-los a um arquivo KML. Embora os exemplos de código sejam apresentados em Python, eles podem ser adaptados com facilidade para a maioria das outras linguagens de programação.

A geocodificação é o processo de conversão de um endereço em um conjunto de coordenadas de latitude/longitude, permitindo indicar endereços em um mapa. Talvez você queira geocodificar endereços e colocá-los diretamente em um arquivo KML. Isso é comum, por exemplo, quando os dados estão sendo inseridos em um formulário e você está gerando arquivos KML em resposta a solicitações. Esses arquivos KML podem ser armazenados em um banco de dados, em um sistema de arquivos ou retornados a um NetworkLink que se conecta ao seu arquivo. Ao usar essa técnica, observe os Termos de Serviço da API Geocoding, já que há algumas limitações no tempo em que os resultados podem ser armazenados, bem como no número de elementos que podem ser geocodificados a cada dia.

Neste tutorial, mostramos como usar o Python para transformar a string "1600 Amphitheatre Pkwy, Mountain View, CA 94043" em:

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

Criar um documento KML

O KML é uma linguagem de marcação XML. Portanto, podemos usar as funções xml.dom.minidom integradas do Python para criar um documento KML. O minidom do Python é uma implementação do DOM, que é compatível com a maioria das linguagens de programação. Portanto, esse processo é fácil de portar para outra linguagem. Siga estas etapas:

  1. Crie o documento usando xml.dom.minidom.Document() do Python.
  2. Crie o elemento raiz <kml> usando createElementNS.
  3. Anexe-o ao documento usando appendChild.
  4. Crie um elemento de documento usando createElement.
  5. Anexe-o ao elemento <kml> usando appendChild.
  6. Para cada endereço, crie um elemento <Placemark> usando createElement e adicione-o ao elemento Document. Em seguida, crie um elemento <description>, atribua a ele o valor do endereço e adicione-o ao elemento <Placemark>.
  7. Crie um elemento <Point>, adicione um elemento filho <coordinates> e anexe-o ao elemento <Placemark>.
  8. Envie o endereço para o Geocoder da API Maps, que envia uma resposta em JSON ou XML. Use urllib.urlopen() para recuperar o arquivo e lê-lo em uma string.
  9. Analise a resposta e extraia os elementos de longitude e latitude.
  10. Crie um nó de texto no elemento <coordinates> e atribua a string de longitude/latitude como valor.
  11. Grave o documento KML em um arquivo de texto.

Exemplo de código Python

O exemplo de código abaixo usa uma variável mapsKey fictícia. Substitua essa chave pela sua.

Confira abaixo um exemplo de código para geocodificação com Python 2.7 e saída 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')

Outras considerações

Como controlar a frequência das solicitações de geocódigos

As solicitações de geocodificação estão sujeitas aos limites diários máximos de taxa de consulta do geocodificador. Consulte a documentação da API Google Geocoding para mais informações sobre esses limites. Para não enviar consultas muito rapidamente ao geocodificador, você pode especificar um atraso entre cada solicitação de geocodificação. É possível aumentar esse atraso a cada vez que você recebe um status OVER_QUERY_LIMIT e usar um loop while para garantir que um endereço foi geocodificado antes de passar para o próximo.

Como alterar o país base

O geocodificador é programado para influenciar os resultados dependendo do domínio de origem. Por exemplo, ao inserir "syracuse" na caixa de pesquisa em maps.google.com, a cidade de "Syracuse, NY" será geocodificada. Já ao inserir a mesma consulta em maps.google.it (domínio da Itália), a cidade de "Siracusa" na Sicília será encontrada. Você teria os mesmos resultados enviando essa consulta por geocodificação HTTP para maps.google.it em vez de maps.google.com. Para isso, modifique a variável mapsUrl no exemplo de código acima. Consulte a documentação da API Geocoding para mais informações sobre o ajuste de região.

Observação:não é possível enviar uma solicitação a um servidor maps.google.* inexistente. Portanto, verifique se um domínio de país existe antes de redirecionar suas consultas de geocodificação para ele. Para saber quais países têm suporte para geocodificação, confira esta postagem.

Conclusão

Usando o código acima, agora é possível geocodificar um endereço com Python, criar um <Placemark> KML e salvar no disco. Se você precisar geocodificar mais endereços por dia do que os limites permitem ou se o geocodificador do Google não abranger as regiões de seu interesse, use outros serviços da Web de geocodificação.

Agora que você já sabe como geocodificar seus endereços, confira os artigos sobre Como usar KML no Google Mashup Editor e Como usar PHP e MySQL para criar KML. Se você tiver problemas ou dúvidas sobre este tutorial, poste no fórum do Stack Overflow.