Post en forme de pense-bête qui j’imagine pourra servir à d’autres, tant il a été long pour moi de trouver une solution simple et rapide à mettre en place. On va donc parler de géocodage et même de reverse geocoding tant qu’on y est.
Il arrive souvent qu’après avoir scrapé un site, ou je ne sais quoi encore, on se retrouve avec des adresses postales du type 6 rue de Lyon, St-Servan, Gironde que l’on aimerait bien visualiser sur une carte. Mais pour ça, la plupart des outils de cartographie demande des coordonnées GPS et pas simplement une adresse. Alors quand il y en a une ça va mais quand on arrive à plusieurs centaines voir plusieurs milliers, ça pose problème.
On va voir ici deux façons de faire. Une, très simple à mettre en place mais qui s’appuie sur l’API un tantinet restrictive de Google Maps et une seconde où l’on va construire un script Python pour arriver à nos fins (et en s’appuyant sur le bon travail de Adrien Van Hamme). L’avantage de ces deux méthodes c’est qu’on ne va pas rentrer une à une chaque adresse mais que l’on va servir d’une base de données contenue dans un fichier CSV.
Quelques petites remarques pour commencer :
- Pour bien tout suivre il va falloir télécharger Python évidemment.
- Vous allez aussi avoir besoin de Node.js qui va nous permettre de bosser avec du javascript sur notre machine.
- Préparez votre fichier CSV d’adresses en n’hésitant pas à les détailler en y ajoutant en plus le noms des départements, régions et France (ou le pays concerné). Cela aidera grandement les API à ne pas faire trop d’erreurs. L’adresse entière doit être contenue, si possible, dans une seule et même colonne pour que tout soit pris en compte et c’est plus pratique. Enfin, optez pour le point-virgule comme délimiteur, ce sera utile pour la seconde méthode !
- Il vaut mieux être familier des panneaux de commandes car tout va se passer dedans ou presque.
Méthode 1 : géocoder avec l’API de Google Maps
On va débuter par la méthode qui demande le moins de compétence mais qui est par conséquent celle qui nous laisse le moins de marge de manœuvre. Pour cela on va se servir d’un petit module développé par Noah Veltman, que vous pouvez retrouver sur la page Github du projet. Je vais simplement reprendre le points essentiels.
Première chose à faire, allez récupérer votre clé pour utiliser l’API de Google Maps. Tout est très bien expliqué par ici.
Puis on ouvre un panneau de commande et on vient installer le module :
npm install -g csvgeocode
Et voila ! Enfin presque maintenant il faut l’utiliser, on rentre donc cette nouvelle commande :
csvgeocode chemin/d'entrée/fichier.csv chemin/desortie/fichier.csv --url "https://maps.googleapis.com/maps/api/geocode/json?address={{LE_NOM_DE_VOTRE_COLONNE_ADRESSE}}&key=VOTRE_CLE_API" --verbose
Petite astuce si vous galérez à trouver le chemin de votre fichier csv, faites le simplement glisser dans un autre panneau de commande, cela vous donnera son chemin, ne reste plus qu’à le recopier.
N’oubliez pas de renseigner le nom de votre colonne d’adresse et enfin votre clé Google. Personnellement je rajoute une option –verbose qui permet de voir en temps réel le géocodage des adresses. Ça permet de voir si il y a des erreurs dans notre fichier et couper le programme si besoin. Et puis comme ça on voit que le programme tourne, c’est moins frustrant que d’attendre simplement le retour à la fin du processus !
Une méthode rapide, (plus ou moins) efficace mais limitée au bon vouloir de l’API qui autorise seulement 2500 requêtes par jour pour les comptes gratuits. Cela suffira donc pour un petit travail sur quelques centaines d’adresses mais pas plus.
Méthode 2 : géocoder avec du Python et Nominatim
Cette seconde méthode est bien plus souple que la première et va nous permettre, en plus, de mettre les mains dans le Python. Je vais ici reprendre les points essentiels du très bon tuto de Adrien Van Hamme qui a également mis à disposition son script, merci à lui.
Après avoir installer Python sur votre machine, on va poursuivre en installant geopy qui va nous permettre d’utiliser différents services de géoloc’, dont Nominatim pour notre cas.
Puis vient l’étape de l’écriture du script dont la majeure partie provient, une nouvelle fois du travail d’Adrien Van Hamme :
#!/usr/bin/env python # coding: utf8 import csv from time import sleep from geopy.geocoders import Nominatim geocoder = Nominatim() inputFile = open('/chemin/dossier/entrée/fichier.csv', 'rb') #chemin de votre fichier à géocoder outputFile = open('/chemin/dossier/sortie/fichierOK.csv', 'w') #chemin de votre fichier de résultats try: outputData = csv.writer(outputFile, delimiter=';', lineterminator='\n') #spécifier le délimiteur de votre fichier de sortie outputData.writerow(('adresse', 'lat', 'lng')) #spécifier le nom de vos colonnes pour le fichier de résultats inputData = csv.reader(inputFile, delimiter=';') #spécifier le délimiteur de votre fichier à géocoder for ligne in inputData: adresse = ligne[0] #ligne correspond aux colonnes de votre tableau try: location = geocoder.geocode(adresse, True, 30) outputData.writerow((adresse, location.latitude, location.longitude)) except Exception as inst: print(inst) sleep(0.5) finally: inputFile.close() outputFile.close()
Finissons par quelques précisions sur ce script. Prenez bien soin de modifier vos chemins d’entrée et de sortie, assurez vous que le script et vos fichiers sont dans le même répertoire. Modifiez si besoin la ligne 15 pour qu’elle colle avec la syntaxe de votre csv (voir plus bas dans la section reverse geocoding). Il ne semble pas vraiment aimer les codes postaux donc laissez les tomber et préférez ville + région.
Vous n’avez plus qu’à exécuter ce script dans votre panneau de commande en tapant son chemin d’accès !
Le reverse geocoding
Comme promis, on va aussi en profiter pour parler reverse geocoding. L’avantage de ce script est qu’il permet en un rien de temps de passer du geocoding classique à du reverse. Pour cela on modifie la fonction location à la ligne 18.
location = geocoder.geocode(adresse, True, 30)
devient
location = geocoder.reverse(adresse, True, 30)
Bien souvent nos latitudes et longitudes sont séparées par une virgule, ce qui va nous forcer à modifier également la ligne de déclaration de la colonne d’adresse à la ligne 16.
adresse = ligne[0]
devient
adresse = ligne[0] + "," + ligne[1]
Vous pouvez aussi appliquer ce cas pendant un géocodage classique si votre adresse complète se trouve dans deux colonnes différentes.
Et enfin à la ligne 18, on lui demande d’écrire nos nouvelles informations dans notre fichier de sortie.
outputData.writerow((adresse, location.latitude, location.longitude))
devient
outputData.writerow((coord, location.address.encode('utf-8')))
Quelques conseils pour régler les problèmes fréquents :
- L’aide de Python pour son installation/sa mise en route/son utilisation (en anglais).
- Les commentaires du post d’Adrien Van Hamme pour les questions liées au script et aux problèmes fréquents rencontrés.
- Faites travailler vos méninges, c’est en forgeant qu’on devient forgeron.
Dommage de s’appuyer sur l’API de Google… il faudrait lire les condition d’utilisation de celle-ci quant à ce qu’on peut réellement faire avec le résultat du géocodage !
En alternative il y a l’API de la Base Adresse Nationale… écrite en python (le code est libre et sur github).
Cette API permet du géocodage à l’unité, du géocodage inverse, de l’autocomplétion d’adresse et du géocodage en masse de fichiers CSV (pas besoin de faire des milliers de requêtes, mais une seul pour des paquets pouvant aller jusque 10 à 15000 lignes).
Ça se passe ici: http://adresse.data.gouv.fr/tools/