Géocoder des adresses à utiliser dans KML

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

Objectif

Ce tutoriel s'adresse aux développeurs qui connaissent 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 et de longitude, ce qui permet d'indiquer des adresses sur une carte. Vous pouvez géocoder des adresses et les insérer directement dans un fichier KML. Cela se produit souvent, 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 ou un système de fichiers, ou renvoyés à un NetworkLink qui se connecte à votre fichier. Notez que lorsque vous utilisez cette technique, vous devez respecter les Conditions d'utilisation de l'API Geocoding, car il existe des limites concernant la durée de stockage des résultats, ainsi que le nombre d'éléments que vous pouvez géocoder chaque jour.

Ce tutoriel vous explique comment utiliser Python pour transformer 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 module minidom de Python est une implémentation du DOM. Le DOM étant compatible avec la plupart des langages de programmation, ce processus devrait être facile à transposer dans un autre langage de programmation. Procédez comme suit :

  1. Créez le document à l'aide de xml.dom.minidom.Document() de Python.
  2. Créez l'élément <kml> racine à 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. Créez ensuite 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> et ajoutez-le à l'élément <Placemark>.
  8. Envoyez l'adresse au géocodeur de l'API Maps, qui renvoie 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-lui la chaîne de longitude/latitude comme 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 mapsKey fictive. Vous devrez remplacer cette clé par votre propre clé.

Vous trouverez ci-dessous un exemple de code pour le géocodage avec Python 2.7 et la sortie 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 points à prendre en compte

Synchroniser les requêtes de géocodage

Les requêtes de géocodage seront soumises aux limites quotidiennes maximales du taux de requêtes du géocodeur. Pour en savoir plus sur ces limites, veuillez consulter la documentation de l'API Google Geocoding. Pour vous assurer de ne pas envoyer de requêtes trop rapidement au géocodeur, vous pouvez spécifier un délai entre chaque requête de géocodage. 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 correctement géocodé une adresse avant de passer à la suivante.

Modifier le pays de base

Le géocodeur est programmé pour orienter ses résultats en fonction du domaine d'origine. Par exemple, si vous saisissez "syracuse" dans le champ de recherche de maps.google.com, la ville de "Syracuse, NY" sera géocodée. En revanche, si vous saisissez la même requête sur maps.google.it (le domaine italien), la ville de "Siracusa" en Sicile sera trouvée. Vous obtiendrez les mêmes résultats en envoyant cette requête via le geocoding HTTP à maps.google.it au lieu de maps.google.com. Pour ce faire, vous pouvez modifier la variable mapsUrl dans l'exemple de code ci-dessus. Pour en savoir plus sur le biais régional, consultez la documentation de l'API Geocoding.

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 géocodage vers celui-ci. Pour connaître les pays dans lesquels le géocodage est disponible, consultez cet article.

Conclusion

À l'aide du code ci-dessus, vous pouvez désormais géocoder une adresse à l'aide de Python, créer un fichier KML <Placemark> à partir de celle-ci et l'enregistrer sur le disque. Si vous constatez que vous devez géocoder plus d'adresses par jour que les limites autorisées ou que le géocodeur Google ne couvre pas les régions qui vous intéressent, envisagez d'utiliser des services Web de géocodage supplémentaires.

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 KML. Si vous rencontrez des problèmes avec ce tutoriel ou si vous avez des questions à son sujet, veuillez les poser sur le forum Stack Overflow.