Endereços de geocodificação para uso no KML

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

Objetivo

Este tutorial é destinado a desenvolvedores familiarizados com linguagens de script e que querem aprender a usar a API Google Geocoding para geocodificar endereços e incorporá-los em um arquivo KML. As amostras de código são apresentadas em Python, mas podem ser facilmente adaptadas à maioria das outras linguagens de programação.

Geocoding é o processo de conversão de um endereço em um conjunto de coordenadas de latitude/longitude, o que possibilita indicar endereços em um mapa. É possível 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 para um NetworkLink que se conecta ao arquivo. Observe que, ao usar essa técnica, você precisa observar os Termos de Serviço da API Geocoding porque há algumas limitações para o tempo em que os resultados podem ser armazenados, bem como o número de elementos que você pode geocodificar diariamente.

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. O DOM é compatível com a maioria das linguagens de programação, portanto, esse processo deve ser fácil de transferir para outra linguagem de programação. 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 Document usando createElement.
  5. Anexe-o ao elemento <kml> usando appendChild.
  6. Para cada endereço, crie um elemento <Placemark> usando createElement e anexe-o ao elemento Document. Em seguida, crie um elemento <description>, atribua o valor do endereço e anexe-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 geocodificador da API Maps, que envia uma resposta em JSON ou XML. Use urllib.urlopen() para extrair e ler o arquivo 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 o valor dele.
  11. Grave o documento KML em um arquivo de texto.

Exemplo de código Python

Observe que o exemplo de código abaixo usa uma variável mapsKey fictícia. Será necessário substituir essa chave pela sua própria chave.

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

Outros aspectos a serem considerados

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

As solicitações de geocodificação estarão sujeitas aos limites diários da 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, especifique um atraso entre cada solicitação. É possível aumentar esse atraso sempre que você receber um status OVER_QUERY_LIMIT e usar uma repetição while para garantir a geocodificação de um endereço antes de iterar para o próximo.

Como alterar o país base

O geocodificador é programado para influenciar os resultados de acordo com o domínio de origem. Por exemplo, se você digitar "syracuse" na caixa de pesquisa de maps.google.com, a cidade de "Syracuse, NY" vai ser geocodificada, e a mesma consulta em maps.google.it (domínio da Itália) vai encontrar a cidade de "Siracusa" na Sicília. Para ter os mesmos resultados, envie essa consulta por meio da 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 saber mais sobre viés de região.

Observação: não é possível enviar uma solicitação a um servidor Maps.google.* inexistente. Portanto, verifique se há um domínio de país antes de redirecionar suas consultas de geocodificação para ele. Para ver o suporte de geocódigo por país, confira esta postagem (em inglês).

Conclusão

Com o código acima, é possível geocodificar um endereço usando Python, criar um <Placemark> KML fora dele e salvá-lo no disco. Se você precisar geocodificar mais endereços por dia do que os limites permitidos ou se o geocodificador do Google não cobrir as regiões nas quais você tem interesse, considere o uso de outros serviços da Web de geocodificação.

Agora que você sabe como geocodificar seus endereços, confira os artigos sobre Como usar KML no Editor de mashup do Google e Como usar PHP e MySQL para criar KML. Se você tiver algum problema ou dúvidas sobre este tutorial, poste no fórum do Stack Overflow (em inglês).