Géocoder des adresses à utiliser dans KML

Mano Marks, équipe Google Geo
Auteur: décembre 2007
Mise à jour: décembre 2013

Objectif

Ce tutoriel est destiné aux développeurs qui maîtrisent les langages de script et qui souhaitent apprendre à utiliser l'API Google Geocoding pour géocoder des adresses et les intégrer dans un fichier KML. Bien que les exemples de code soient présentés en Python, ils peuvent être adaptés assez facilement à la plupart des autres langages de programmation.

Le geocoding consiste à convertir une adresse en un ensemble de coordonnées de latitude/longitude, ce qui permet d'indiquer des adresses sur une carte. Vous pouvez géocoder des adresses et les placer directement dans un fichier KML. C'est courant, par exemple lorsque des données sont saisies dans un formulaire et que vous générez des fichiers KML en réponse à des requêtes. Ces fichiers KML peuvent être stockés dans une base de données, dans un système de fichiers ou renvoyés à un lien réseau qui se connecte à votre fichier. Notez que lorsque vous utilisez cette technique, vous devez respecter les Conditions d'utilisation de l'API Geocoding, car le délai de stockage des résultats est limité, de même que le nombre d'éléments que vous pouvez géocoder chaque jour.

Ce tutoriel vous montre comment utiliser Python pour convertir la chaîne "1600 Amphitheatre Pkwy, Mountain View, CA 94043" en:

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

Créer un document KML

KML est un langage de balisage XML. Nous pouvons donc utiliser les fonctions xml.dom.minidom intégrées de Python pour créer un document KML. Le minidom de Python est une mise en œuvre de DOM, et DOM est compatible avec la plupart des langages de programmation. Ce processus doit donc être facile à transférer dans un autre langage de programmation. Procédez comme suit :

  1. Créez le document à l'aide de l'xml.dom.minidom.Document() de Python.
  2. Créez l'élément racine <kml> à l'aide de createElementNS..
  3. Ajoutez-le au document à l'aide de appendChild.
  4. Créez un élément Document à l'aide de createElement.
  5. Ajoutez-le à l'élément <kml> à l'aide de appendChild.
  6. Pour chaque adresse, créez un élément <Placemark> à l'aide de createElement et ajoutez-le à l'élément Document. Ensuite, créez un élément <description>, attribuez-lui la valeur de l'adresse et ajoutez-le à l'élément <Placemark>.
  7. Créez un élément <Point>, ajoutez un élément enfant <coordinates>, puis ajoutez-le à l'élément <Placemark>.
  8. Envoyez l'adresse au géocodeur de l'API Google Maps, qui envoie une réponse au format JSON ou XML. Utilisez urllib.urlopen() pour récupérer le fichier et le lire dans une chaîne.
  9. Analysez la réponse et extrayez les éléments de longitude et de latitude.
  10. Créez un nœud de texte dans l'élément <coordinates> et attribuez la valeur de longitude/latitude à sa valeur.
  11. Écrivez le document KML dans un fichier texte.

Exemple de code Python

Notez que l'exemple de code ci-dessous utilise une variable mapKey factice. Vous devez remplacer cette clé par votre propre clé.

Voici un exemple de code pour le géocodage avec une sortie Python 2.7 et 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')

Autres éléments à prendre en compte

Planifier les requêtes de géocodage

Les requêtes de geocoding sont soumises aux limites quotidiennes du taux de requête maximal du geocoder. Pour en savoir plus sur ces limites, consultez la documentation de l'API Google Geocoding. Pour vous assurer que vous n'envoyez pas de requêtes trop rapidement au geocoder, vous pouvez spécifier un délai entre chaque requête de geocode. Vous pouvez augmenter ce délai chaque fois que vous recevez un état OVER_QUERY_LIMIT et utiliser une boucle while pour vous assurer d'avoir géocodé une adresse avant de créer une itération pour la suivante.

Modifier le pays de base

Le geocoder est programmé pour pondérer ses résultats en fonction du domaine d'origine. Par exemple, si vous saisissez "syracuse" dans le champ de recherche sur maps.google.com, vous marquez la ville de "Syracuse, NY" alors que vous saisissez la même requête sur maps.google.it (domaine de l'Italie) pour trouver la ville de "Syracuse" en Sicile. Vous obtenez les mêmes résultats en envoyant cette requête via le geocoding HTTP à maps.google.it au lieu de maps.google.com. Vous pouvez le faire en modifiant la variable mapsUrl dans l'exemple de code ci-dessus. Reportez-vous à la documentation de l'API Geocoding pour en savoir plus sur la pondération de la région.

Remarque : Vous ne pouvez pas envoyer de requête à un serveur maps.google.* inexistant. Assurez-vous donc qu'un domaine de pays existe avant de rediriger vos requêtes de geocoding vers celui-ci. Pour connaître les codes géographiques par pays, consultez cet article.

Conclusion

À l'aide du code ci-dessus, vous pouvez maintenant géocoder une adresse à l'aide de Python, créer un fichier KML <Placemark> à partir de celui-ci, puis l'enregistrer sur le disque. Si vous avez besoin de géocoder plus d'adresses par jour que ne le permettent les limites ou que le geocoder de Google ne couvre pas les régions qui vous intéressent, envisagez d'utiliser d'autres services Web de geocoding.

Maintenant que vous savez comment géocoder vos adresses, consultez les articles Utiliser KML dans Google Mashup Editor et Utiliser PHP et MySQL pour créer un fichier KML. Si vous rencontrez des problèmes ou si vous avez des questions concernant ce tutoriel, veuillez les poser sur le forum Stack Overflow.