Web Geo Data Vore

Du web, des cartes et des données, mangeons-les!

En
  • Services
    • Conseil et accompagnement
    • Développement
    • Formation
  • Projets
  • Blog technique
  • A propos

Ajout du support du géocodeur de l'IGN dans Geopy

mar. 06 janvier 2015 | tags: webgeocodagegeopyignopenlspython

Suite à des discussions sur le géocodage par le géocodeur de l'IGN, nous avons trouvé intéressant d'implémenter son support dans la bibliothèque Python Geopy. Le géocodage, pour rappel, c'est le fait d'associer des adresses à des coordonnées géographiques.

Nous avons pour le moment ignoré le support des codes EPSG. Il est en effet possible de retourner les coordonnées transformées en coordonnées locales (EPSG 2154, ...) mais comme les objets retournés par Geopy lors du géocodage contiennent une référence à latitude, longitude, cela ne nous paraissait pas très pertinent pour rester générique. Ce support pourra toujours être ajouté ultérieurement.

Nous avons rencontrés quelques cas qui ne semblent pas fonctionner ou bien nous avons loupé des informations dans la documentation officielle http://api.ign.fr/tech-docs-js/fr/developpeur/search.html

Enregistrez-vous auprès de l'IGN¶

Vous devez pour vos tests, vous enregistrer sur le site http://api.ign.fr pour créer une clé pour un usage "développeurs". Il vous faut créer une clé avec le support de OpenLS (c'est un standard OGC pour le géocodage). Cela pourra être une clé "Sig" ou "Web" qui permettent d'accéder aux trois fonctionnalités de géocodage qu'offrent l'API. Celle-ci permet une recherche adresse, une recherche par parcelles (sous réserve que ces parcelles soient des parcelles avec cadastre vecteur) ou par toponymes. Vous avez aussi la fonctionnalité de reverse geocoding qui consiste à faire l'opposer du géocodage c'est à dire d'associer une adresse à une position. Typiquement, cal répond à une question vous êtes livreur et souhaitez confirmer que vous êtes dans la bonne rue où livrer. Depuis votre mobile, vous envoyez vos coordonnées et vous connaissez votre rue.

Selon, votre usage, attention de souscrire à la "bonne" licence. Pour cela, allez voir les conditions d'utilisation sur http://professionnels.ign.fr/api-web#tab-3

Installer Geopy¶

Pour essayer le géocodeur de l'IGN, vous devez installer GeoPy (version 1.7) avec

pip install geopy


Configurer les variables d'environnement¶

Après installation, nous allons vous montrer quelques exemples d'opérations de géocodage

Pour éviter de coder "en dur", c'est à dire dans un fichier contenant du code, nous allons utiliser des variables d'environnement pour par exemple éviter de laisser trainer des informations confidentielles sur un gestionnaire de version type SVN, Git ou Mercurial

Pour vous authentifier, vous avez deux choix (qui s'excluent):

  • en passant par ce qu'on appel le referer avec la clé d'API
  • avec un couple nom utilisateur / mot de passe avec la clé d'API.

Selon votre clé et votre système d'exploitation, l'exportation des variables d'environnement varie aussi. Voir le récapitulatif ci-dessous.

Linux / Mac

# Clé Sig
export IGNFRANCE_KEY='votre_cle'
export IGNFRANCE_USERNAME='votre_nom_utilisateur'
export IGNFRANCE_PASSWORD='votre_mot_de_passe'
unset IGNFRANCE_REFERER

ou

# Clé Web
export IGNFRANCE_KEY='votre_cle'
export IGNFRANCE_REFERER='localhost' # En dev, c'st localhost mais cela peut changer quand vous avez une clé "pro"
unset IGNFRANCE_USERNAME
unset IGNFRANCE_PASSWORD

Windows

# Clé Sig
set IGNFRANCE_KEY='votre_cle'
set IGNFRANCE_USERNAME='votre_nom_utilisateur'
set IGNFRANCE_PASSWORD='votre_mot_de_passe'
setx IGNFRANCE_REFERER ""

ou

# Clé Web
set IGNFRANCE_KEY='votre_cle'
set IGNFRANCE_REFERER='localhost' # En dev, c'st localhost mais cela peut changer quand vous avez une clé "pro"
setx IGNFRANCE_USERNAME ""
setx IGNFRANCE_PASSWORD ""
In [1]:
# Pour la compatibilité Python 2/3
from __future__ import absolute_import, division, print_function
from builtins import (bytes, str, open, super, range,
                      zip, round, input, int, pow, object)

from geopy.geocoders.ignfrance import IGNFrance
import os
# Si on veut le mode debug qui permet d'afficher les urls appelées ainsi que le contenu XML qui est envoyé et reçu,
# on décommente les 4 lignes ci-dessous
#import logging
#logger = logging.getLogger('geopy')
#logger.addHandler(logging.StreamHandler())
#logger.setLevel('DEBUG')

# Partie authentification qui nécessite d'avoir enregistré les variables d'environnement avant d'avoir lancé le "notebook"
ign = IGNFrance(
    api_key=os.environ.get('IGNFRANCE_KEY'),
    username=os.environ.get('IGNFRANCE_USERNAME'),
    password=os.environ.get('IGNFRANCE_PASSWORD'),
    referer=os.environ.get('IGNFRANCE_REFERER'),
    timeout=20 # Set to 20 seconds
)
In [2]:
# Appel au cadastre pour avoir les coordonnées d'une parcelle

cadastre_call = ign.geocode('44109000EX0114', 'CadastralParcel', maximum_responses=10, exactly_one=True)

print (cadastre_call.raw)
{'departement': '44', 'qualite': None, 'match_type': None, 'municipality': 'Nantes', 'street': '44109000EX0114', 'postal_code': None, 'freeformaddress': None, 'lng': '-1.556303', 'commune_absorbee': '000', 'id': None, 'section': 'EX', 'accuracy': '1.0', 'commune': '109', 'nature': None, 'feuille': '1', 'numero': '0114', 'extended_geocode_match_code': None, 'bbox': None, 'lat': '47.222482', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '44109', 'territoire': None}
In [3]:
# Adresse avec retour de type freeform
adress_call_with_freeform = ign.geocode(
    query="8 rue Général Buat, Nantes",
    query_type="StreetAddress",
    is_freeform=True,
    exactly_one=False,
    maximum_responses=5
)

print (adress_call_with_freeform)

for adr in adress_call_with_freeform:
    print (adr.raw)
[Location((47.233314, -1.536575, 0.0)), Location((47.212006, -1.582534, 0.0)), Location((47.260711, -1.566178, 0.0)), Location((47.218152, -1.568012, 0.0)), Location((47.206557, -1.592118, 0.0))]
{'departement': None, 'qualite': None, 'match_type': 'Street number', 'municipality': None, 'street': None, 'postal_code': None, 'freeformaddress': '8 r general buat , 44000 Nantes', 'lng': '-1.536575', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.7665790499899182', 'commune': None, 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': None, 'lat': '47.233314', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': None, 'territoire': None}
{'departement': None, 'qualite': None, 'match_type': 'Street number', 'municipality': None, 'street': None, 'postal_code': None, 'freeformaddress': '8 r general de torquat , 44000 Nantes', 'lng': '-1.582534', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.582541483223572', 'commune': None, 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': None, 'lat': '47.212006', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': None, 'territoire': None}
{'departement': None, 'qualite': None, 'match_type': 'Street number', 'municipality': None, 'street': None, 'postal_code': None, 'freeformaddress': '8 r du guatemala , 44000 Nantes', 'lng': '-1.566178', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.2943440453147809', 'commune': None, 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': None, 'lat': '47.260711', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': None, 'territoire': None}
{'departement': None, 'qualite': None, 'match_type': 'Street', 'municipality': None, 'street': None, 'postal_code': None, 'freeformaddress': 'r du 14 juillet , 44000 Nantes', 'lng': '-1.568012', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.2734706663557187', 'commune': None, 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': None, 'lat': '47.218152', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': None, 'territoire': None}
{'departement': None, 'qualite': None, 'match_type': 'Street number', 'municipality': None, 'street': None, 'postal_code': None, 'freeformaddress': '8 r du 4 aout 1789 , 44000 Nantes', 'lng': '-1.592118', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.2697096751028238', 'commune': None, 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': None, 'lat': '47.206557', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': None, 'territoire': None}
In [4]:
# Adresse avec retour "classique"
adress_call = ign.geocode('8 rue Général Buat, Nantes', 'StreetAddress',
    maximum_responses=10, exactly_one=False)

for poi in adress_call:
    print (poi.raw)
{'departement': '44', 'qualite': 'Plaque adresse', 'match_type': 'Street number', 'municipality': 'Nantes', 'street': 'r general buat', 'postal_code': '44000', 'freeformaddress': None, 'lng': '-1.536575', 'commune_absorbee': None, 'id': 'ADRNIVX_0000000280107559', 'section': None, 'accuracy': '0.7665790499899182', 'commune': 'Nantes', 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '-1.536575;47.233314;-1.536575;47.233314', 'lat': '47.233314', 'search_centre_distance': None, 'building': '8', 'id_tr': 'TRONROUT0000000029411220', 'insee': '44109', 'territoire': 'FXX'}
{'departement': '44', 'qualite': 'Plaque adresse', 'match_type': 'Street number', 'municipality': 'Nantes', 'street': 'r general de torquat', 'postal_code': '44100', 'freeformaddress': None, 'lng': '-1.582534', 'commune_absorbee': None, 'id': 'ADRNIVX_0000000280149590', 'section': None, 'accuracy': '0.582541483223572', 'commune': 'Nantes', 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '-1.582534;47.212006;-1.582534;47.212006', 'lat': '47.212006', 'search_centre_distance': None, 'building': '8', 'id_tr': 'TRONROUT0000000029478000', 'insee': '44109', 'territoire': 'FXX'}
{'departement': '44', 'qualite': 'Plaque adresse', 'match_type': 'Street number', 'municipality': 'Nantes', 'street': 'r du guatemala', 'postal_code': '44300', 'freeformaddress': None, 'lng': '-1.566178', 'commune_absorbee': None, 'id': 'ADRNIVX_0000000280064268', 'section': None, 'accuracy': '0.2943440453147809', 'commune': 'Nantes', 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '-1.566178;47.260711;-1.566178;47.260711', 'lat': '47.260711', 'search_centre_distance': None, 'building': '8', 'id_tr': 'TRONROUT0000000029413775', 'insee': '44109', 'territoire': 'FXX'}
{'departement': '44', 'qualite': '2.5', 'match_type': 'Street', 'municipality': 'Nantes', 'street': 'r du 14 juillet', 'postal_code': '44000', 'freeformaddress': None, 'lng': '-1.568012', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.2734706663557187', 'commune': 'Nantes', 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '-1.568532;47.217678;-1.567555;47.218642', 'lat': '47.218152', 'search_centre_distance': None, 'building': None, 'id_tr': 'TRONROUT0000000029478040', 'insee': '44109', 'territoire': 'FXX'}
{'departement': '44', 'qualite': 'Plaque adresse', 'match_type': 'Street number', 'municipality': 'Nantes', 'street': 'r du 4 aout 1789', 'postal_code': '44100', 'freeformaddress': None, 'lng': '-1.592118', 'commune_absorbee': None, 'id': 'ADRNIVX_0000000280159532', 'section': None, 'accuracy': '0.2697096751028238', 'commune': 'Nantes', 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '-1.592118;47.206557;-1.592118;47.206557', 'lat': '47.206557', 'search_centre_distance': None, 'building': '8', 'id_tr': 'TRONROUT0000000029481302', 'insee': '44109', 'territoire': 'FXX'}
{'departement': '44', 'qualite': '1.5', 'match_type': 'Street', 'municipality': 'Nantes', 'street': "r de l'equateur", 'postal_code': '44300', 'freeformaddress': None, 'lng': '-1.562882', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.26967433318786127', 'commune': 'Nantes', 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '-1.564157;47.260263;-1.561622;47.260670', 'lat': '47.260594', 'search_centre_distance': None, 'building': None, 'id_tr': 'TRONROUT0000000029413004', 'insee': '44109', 'territoire': 'FXX'}
{'departement': '44', 'qualite': 'Plaque adresse', 'match_type': 'Street number', 'municipality': 'Nantes', 'street': 'r du 4 septembre 1870', 'postal_code': '44100', 'freeformaddress': None, 'lng': '-1.590612', 'commune_absorbee': None, 'id': 'ADRNIVX_0000000280159557', 'section': None, 'accuracy': '0.25598544716882954', 'commune': 'Nantes', 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '-1.590612;47.206384;-1.590612;47.206384', 'lat': '47.206384', 'search_centre_distance': None, 'building': '8', 'id_tr': 'TRONROUT0000000029480947', 'insee': '44109', 'territoire': 'FXX'}
{'departement': '44', 'qualite': '2.5', 'match_type': 'Street', 'municipality': 'Nantes', 'street': 'all des 4 jeudis', 'postal_code': '44300', 'freeformaddress': None, 'lng': '-1.520599', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.2318486016515655', 'commune': 'Nantes', 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '-1.521037;47.265866;-1.520564;47.265982', 'lat': '47.265874', 'search_centre_distance': None, 'building': None, 'id_tr': 'TRONROUT0000000029407954', 'insee': '44109', 'territoire': 'FXX'}
{'departement': '44', 'qualite': 'Plaque adresse', 'match_type': 'Street number', 'municipality': 'Nantes', 'street': "r d'houat", 'postal_code': '44000', 'freeformaddress': None, 'lng': '-1.532728', 'commune_absorbee': None, 'id': 'ADRNIVX_0000000280115932', 'section': None, 'accuracy': '0.17517346923349658', 'commune': 'Nantes', 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '-1.532728;47.229494;-1.532728;47.229494', 'lat': '47.229494', 'search_centre_distance': None, 'building': '8', 'id_tr': 'TRONROUT0000000029411945', 'insee': '44109', 'territoire': 'FXX'}
{'departement': '44', 'qualite': 'Plaque adresse', 'match_type': 'Street number', 'municipality': 'Nantes', 'street': 'r du senat', 'postal_code': '44300', 'freeformaddress': None, 'lng': '-1.541816', 'commune_absorbee': None, 'id': 'ADRNIVX_0000000280098724', 'section': None, 'accuracy': '0.011213555538219304', 'commune': 'Nantes', 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '-1.541816;47.238518;-1.541816;47.238518', 'lat': '47.238518', 'search_centre_distance': None, 'building': '8', 'id_tr': 'TRONROUT0000000029414412', 'insee': '44109', 'territoire': 'FXX'}
In [5]:
# Cas PositionOfInterest en réalité les toponymes
position_of_interest_call_attrib_filtering = ign.geocode(
    'Les Molettes',
    'PositionOfInterest',
    maximum_responses=10,
    filtering='<Place type="Departement">38</Place>',
    exactly_one=False
)

for poi in position_of_interest_call_attrib_filtering:
    print (poi.raw)
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': 'les molettes', 'street': None, 'postal_code': '38080', 'freeformaddress': None, 'lng': '5.187107', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '1.0', 'commune': 'Four', 'nature': u'Lieu-dit habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.187107;45.571717;5.187107;45.571717', 'lat': '45.571717', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38172', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': 'les mollettes', 'street': None, 'postal_code': '38420', 'freeformaddress': None, 'lng': '5.892806', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.9960000000000001', 'commune': 'Revel', 'nature': u'Lieu-dit habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.892806;45.183353;5.892806;45.183353', 'lat': '45.183353', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38334', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': 'la molette', 'street': None, 'postal_code': '38110', 'freeformaddress': None, 'lng': '5.351472', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.9274619965671969', 'commune': 'Saint-Victor-de-Cessieu', 'nature': u'Lieu-dit non habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.351472;45.535483;5.351472;45.535483', 'lat': '45.535483', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38464', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': u'c\xf4te molette', 'street': None, 'postal_code': '38630', 'freeformaddress': None, 'lng': '5.536513', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.8897061588184721', 'commune': 'Veyrins-Thuellin', 'nature': u'Lieu-dit habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.536513;45.621909;5.536513;45.621909', 'lat': '45.621909', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38541', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': u'for\xeat mollette', 'street': None, 'postal_code': '38110', 'freeformaddress': None, 'lng': '5.461903', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.8833077194568336', 'commune': 'La Chapelle-de-la-Tour', 'nature': u'Lieu-dit non habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.461903;45.600697;5.461903;45.600697', 'lat': '45.600697', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38076', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': 'mollette', 'street': None, 'postal_code': '38110', 'freeformaddress': None, 'lng': '5.552278', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.8691261201457529', 'commune': u'La B\xe2tie-Montgascon', 'nature': u'Lieu-dit habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.552278;45.570568;5.552278;45.570568', 'lat': '45.570568', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38029', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': u'bois des molletti\xe8res', 'street': None, 'postal_code': '38570', 'freeformaddress': None, 'lng': '5.995897', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.8629062171042865', 'commune': 'Goncelin', 'nature': 'Bois', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.995897;45.344977;5.995897;45.344977', 'lat': '45.344977', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38181', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': u'ch\xe2teau de molette', 'street': None, 'postal_code': '38110', 'freeformaddress': None, 'lng': '5.358407', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.862710197935416', 'commune': 'Saint-Victor-de-Cessieu', 'nature': u'Ch\xe2teau', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.358407;45.532776;5.358407;45.532776', 'lat': '45.532776', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38464', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': u'l\xe9ch\xe8re de molletunay', 'street': None, 'postal_code': '38230', 'freeformaddress': None, 'lng': '5.190194', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.7986032102892423', 'commune': 'Tignieu-Jameyzieu', 'nature': 'Marais', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.190194;45.743722;5.190194;45.743722', 'lat': '45.743722', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38507', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': 'molletonnet', 'street': None, 'postal_code': '38510', 'freeformaddress': None, 'lng': '5.415808', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.7777325396789276', 'commune': 'Courtenay', 'nature': u'Lieu-dit non habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.415808;45.742529;5.415808;45.742529', 'lat': '45.742529', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38135', 'territoire': 'FXX'}
In [7]:
# Filtrage des résultats en fonction d'une enveloppe 
lat_min, lng_min, lat_max, lng_max = 45.00, 5, 46, 6.40

spatial_filtering_envelope = """
<gml:envelope>
    <gml:pos>{lat_min} {lng_min}</gml:pos>
    <gml:pos>{lat_max} {lng_max}</gml:pos>
</gml:envelope>
""".format(
    lat_min=lat_min,
    lng_min=lng_min,
    lat_max=lat_max,
    lng_max=lng_max
)

position_of_interest_call_spatial_filtering_envelope = ign.geocode(
    'Les Molettes',
    'PositionOfInterest',
    maximum_responses=10,
    filtering=spatial_filtering_envelope,
    exactly_one=False
)

for poi in position_of_interest_call_spatial_filtering_envelope:
    print (poi.raw)
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': 'les molettes', 'street': None, 'postal_code': '38080', 'freeformaddress': None, 'lng': '5.187107', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '1.0', 'commune': 'Four', 'nature': u'Lieu-dit habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.187107;45.571717;5.187107;45.571717', 'lat': '45.571717', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38172', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': 'les mollettes', 'street': None, 'postal_code': '38420', 'freeformaddress': None, 'lng': '5.892806', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.9960000000000001', 'commune': 'Revel', 'nature': u'Lieu-dit habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.892806;45.183353;5.892806;45.183353', 'lat': '45.183353', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38334', 'territoire': 'FXX'}
{'departement': '73', 'qualite': None, 'match_type': 'City', 'municipality': 'les mollettes', 'street': None, 'postal_code': '73160', 'freeformaddress': None, 'lng': '5.873005', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.9960000000000001', 'commune': 'Vimines', 'nature': u'Lieu-dit habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.873005;45.546334;5.873005;45.546334', 'lat': '45.546334', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '73326', 'territoire': 'FXX'}
{'departement': '73', 'qualite': None, 'match_type': 'City', 'municipality': 'les mollettes', 'street': None, 'postal_code': '73800', 'freeformaddress': None, 'lng': '6.058192', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.9960000000000001', 'commune': 'Les Mollettes', 'nature': u'Lieu-dit habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '6.058192;45.463153;6.058192;45.463153', 'lat': '45.463153', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '73159', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': 'la molette', 'street': None, 'postal_code': '38110', 'freeformaddress': None, 'lng': '5.351472', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.9274619965671969', 'commune': 'Saint-Victor-de-Cessieu', 'nature': u'Lieu-dit non habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.351472;45.535483;5.351472;45.535483', 'lat': '45.535483', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38464', 'territoire': 'FXX'}
{'departement': '73', 'qualite': None, 'match_type': 'City', 'municipality': 'les mollets', 'street': None, 'postal_code': '73460', 'freeformaddress': None, 'lng': '6.287666', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.9126922040903768', 'commune': u'Cl\xe9ry', 'nature': u'Lieu-dit habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '6.287666;45.646727;6.287666;45.646727', 'lat': '45.646727', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '73086', 'territoire': 'FXX'}
{'departement': '73', 'qualite': None, 'match_type': 'City', 'municipality': 'pont des mollettes', 'street': None, 'postal_code': '73800', 'freeformaddress': None, 'lng': '6.046512', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.8955700370726849', 'commune': 'Les Mollettes', 'nature': 'Pont', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '6.046512;45.462661;6.046512;45.462661', 'lat': '45.462661', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '73159', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': u'c\xf4te molette', 'street': None, 'postal_code': '38630', 'freeformaddress': None, 'lng': '5.536513', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.8897061588184721', 'commune': 'Veyrins-Thuellin', 'nature': u'Lieu-dit habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.536513;45.621909;5.536513;45.621909', 'lat': '45.621909', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38541', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': u'for\xeat mollette', 'street': None, 'postal_code': '38110', 'freeformaddress': None, 'lng': '5.461903', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.8833077194568336', 'commune': 'La Chapelle-de-la-Tour', 'nature': u'Lieu-dit non habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.461903;45.600697;5.461903;45.600697', 'lat': '45.600697', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38076', 'territoire': 'FXX'}
{'departement': '38', 'qualite': None, 'match_type': 'City', 'municipality': 'mollette', 'street': None, 'postal_code': '38110', 'freeformaddress': None, 'lng': '5.552278', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': '0.8691261201457529', 'commune': u'La B\xe2tie-Montgascon', 'nature': u'Lieu-dit habit\xe9', 'feuille': None, 'numero': None, 'extended_geocode_match_code': None, 'bbox': '5.552278;45.570568;5.552278;45.570568', 'lat': '45.570568', 'search_centre_distance': None, 'building': None, 'id_tr': None, 'insee': '38029', 'territoire': 'FXX'}
In [8]:
# Reverse géocodage "Normal" c'est à dire sans filtre
point_call = ign.reverse(
    query='47.229554,-1.541519',
    exactly_one=True
)

print (point_call.raw)
{'departement': '44', 'qualite': 'Projection', 'match_type': None, 'municipality': 'Nantes', 'street': 'av camille guerin', 'postal_code': '44000', 'freeformaddress': None, 'lng': '-1.541519', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': None, 'commune': 'Nantes', 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': 'Street number', 'bbox': '-1.541519;47.229554;-1.541519;47.229554', 'lat': '47.229554', 'search_centre_distance': '0.00', 'building': '3', 'id_tr': None, 'insee': '44109', 'territoire': 'FXX'}
In [11]:
# Il existe la possibilité de retourner à la fois des adresses et des toponymes via des "preferences
point_call_preference = ign.reverse('47.229554,-1.541519',
    reverse_geocode_preference=['StreetAddress', 'PositionOfInterest'])

print (point_call_preference[0].raw)

# Reverse geocodage en spécifiant le centre et le rayon de recherche en mètres
spatial_filtering_radius = """
<gml:CircleByCenterPoint>
    <gml:pos>{coord}</gml:pos>
    <gml:radius>{radius}</gml:radius>
</gml:CircleByCenterPoint>
""".format(coord='48.8033333 2.3241667', radius='50')

point_call_radius = ign.reverse('48.8033333,2.3241667',
    maximum_responses=10,
    filtering=spatial_filtering_radius)

print (len(point_call_radius))

# Test avec les mêmes coordonnées, sans filtre spatial
point_call_no_radius = ign.reverse('48.8033333,2.3241667',
  maximum_responses=10)

print (len(point_call_no_radius))
{'departement': '44', 'qualite': 'Projection', 'match_type': None, 'municipality': 'Nantes', 'street': 'av camille guerin', 'postal_code': '44000', 'freeformaddress': None, 'lng': '-1.541519', 'commune_absorbee': None, 'id': None, 'section': None, 'accuracy': None, 'commune': 'Nantes', 'nature': None, 'feuille': None, 'numero': None, 'extended_geocode_match_code': 'Street number', 'bbox': '-1.541519;47.229554;-1.541519;47.229554', 'lat': '47.229554', 'search_centre_distance': '0.00', 'building': '3', 'id_tr': None, 'insee': '44109', 'territoire': 'FXX'}
6
10
In [10]:
# Filtrage avec un polygone
# Ne marche pas ou bien on a loupé quelque chose dans la documentation
# http://api.ign.fr/tech-docs-js/fr/developpeur/search.html#Recherche_avec_une_contrainte_polygonale
spatial_filtering_polygon = """
<gml:Polygon>
    <gml:exterior>
        <gml:LinearRing>
            <gml:pos>48.8033 2.3241</gml:pos>
            <gml:pos>48.8033 2.3242</gml:pos>
            <gml:pos>48.8032 2.3242</gml:pos>
            <gml:pos>48.8032 2.3241</gml:pos>
        </gml:LinearRing>
    </gml:exterior>
</gml:Polygon>
"""

point_call_polygon = ign.reverse('48.8033333,2.3241667',
  maximum_responses=10, filtering=spatial_filtering_polygon)

print (point_call_polygon)
[]

Exemple avec des données tabulaires¶

On termine avec un exemple plus complet qui utilise des bibliothèques de haut niveau comme Pandas pour manipuler un CSV Il permet d'utiliser aussi en entrée des données Excel et d'écrire en Excel

Selon votre besoin et vos contraintes, le module CSV de Python peut faire l'affaire.

Si vous devez utiliser Excel, il est possible de travailler avec Tablib ou bien le couple xlrd/xlwt

Pour LibreOffice, il est possible d'utiliser une bibliothèque comme Unotools qui s'interface avec LibreOffice/OpenOffice via Python

Vous devez installer Pandas et Numpy avec

pip install numpy pandas
In [14]:
import pandas as pd
import numpy as np
import urllib

# Les données viennent de http://www.ign.fr/institut/adresses-lign
df = pd.read_csv(
    'ign_adresse_a_geocoder.tsv',
    sep='\t',
    encoding='utf-8'
)

columns_names = list(df.columns.values)
print (columns_names)
# [u'NOM', u'ADRESSE', u'CP_VILLE', u'TEL']

# Ajout de nouvelles "colonnes"
df.insert(len(columns_names), "R_ADRESS", np.nan)
df.insert(len(columns_names) + 1, "LONGITUDE", np.nan)
df.insert(len(columns_names) + 2, "LATITUDE", np.nan)
df.insert(len(columns_names) + 3, "ACCURACY", np.nan)
df.insert(len(columns_names) + 4, "QUALITE", np.nan)
df.insert(len(columns_names) + 5, "MATCH_TYPE", np.nan)

# Appel au service de géocodage et mise à jour des colonnes avec les résultats
for index, row in df.iterrows():
    url_encoded_address = (row['ADRESSE'] + ', ' + row['CP_VILLE']).encode('ascii', errors='xmlcharrefreplace') # Pour éviter des erreurs sur les accents
    #print url_encoded_address
    results = ign.geocode(
        url_encoded_address,
        query_type="StreetAddress",
        exactly_one=True
    )
    df.loc[index, 'R_ADRESS'] = results.address
    df.loc[index, 'LONGITUDE'] = results.longitude
    df.loc[index, 'LATITUDE'] = results.latitude
    df.loc[index, 'ACCURACY'] = results.raw['accuracy']
    df.loc[index, 'QUALITE'] = results.raw['qualite']
    df.loc[index, 'MATCH_TYPE'] = results.raw['match_type']

# Write results
df.to_csv('adresses_avec_geocodage.txt', sep='\t', encoding='utf-8', index=False)
df
[u'NOM', u'ADRESSE', u'CP_VILLE', u'TEL']
Out[14]:
NOM ADRESSE CP_VILLE TEL R_ADRESS LONGITUDE LATITUDE ACCURACY QUALITE MATCH_TYPE
0 Institut national de l'information géographiqu... 73, avenue de Paris 94165 SAINT-MANDÉ CEDEX Tél. : 01 43 98 80 00 73 av de paris, 94160 Saint-Mandé 2.424258 48.845824 0.9495000000000001 2.5 Street number
1 Le monde des cartes 50, rue de la Verrerie 75004 PARIS Tél. : 01 43 98 85 10 50 r de la verrerie, 75004 Paris 2.352677 48.858157 1.0 2.5 Street number
2 IGN France International 90, avenue de Flandre 75019 PARIS Tél. : 01 42 34 56 56 90 av de flandre, 75019 Paris 2.376554 48.890093 1.0 Plaque adresse Street number
3 ENSG (École nationale des sciences géographiqu... 6/8, avenue Blaise Pascal 77455 MARNE-LA-VALLÉE CEDEX 2 Tél. : 01 64 15 30 01 72110 Torcé-en-Vallée 0.396991 48.133234 0.5783559826357312 30.0 City
4 Centre de production Île-de-France 73, avenue de Paris 94165 SAINT-MANDÉ CEDEX NaN 73 av de paris, 94160 Saint-Mandé 2.424258 48.845824 0.9495000000000001 2.5 Street number
5 Service de l'inventaire forestier Château des Barres 45290 NOGENT-SUR-VERNISSON NaN 45290 Nogent-sur-Vernisson 2.741791 47.846382 0.9287148985644398 30.0 City
6 Direction interrégionale centre-est 239 rue Garibaldi 69422 LYON CEDEX 03 NaN 239 r garibaldi, 69003 Lyon 4.853296 45.754735 0.9495000000000001 2.5 Street number
7 Direction interrégionale nord-ouest - Nantes 2, boulevard de la Loire - BP 30412 44204 NANTES CEDEX 02 NaN 2 bd de la loire, 44200 Nantes -1.526320 47.211030 0.9495000000000001 Plaque adresse Street number
8 Direction interrégionale nord-ouest - Caen 73, rue Marie Curie 14200 HEROUVILLE-SAINT-CLAIR NaN 73 r marie curie, 14200 Hérouville-Saint-Clair -0.343789 49.212766 1.0 1.5 Street number
9 Direction interrégionale sud-est - Europarc de... 1330, avenue JRGG de la Lauzière, CS 80518 13593 AIX-EN-PROVENCE CEDEX 3 NaN 1330 av j-r guilibert gautier de la lauziere, ... 5.370244 43.478432 0.6328914150100643 Plaque adresse Street number
10 Direction interrégionale nord-est 11, rue de l'Île de Corse 54000 NANCY NaN 11 r de l'ile de corse, 54000 Nancy 6.189437 48.693567 1.0 Projection Street number
11 Direction interrégionale sud-ouest Rue Pierre Ramond-Caupian, BP 60104 33166 SAINT-MÉDARD-EN-JALLES CEDEX NaN r pierre ramond, 33160 Saint-Médard-en-Jalles -0.740556 44.884896 0.8136069696508097 1.5 Street
12 Base aérienne de Creil Route de la Forêt de Verneuil-en-Halatte, BP 125 60107 CREIL CEDEX NaN av de la foret d'halatte, 60100 Creil 2.498073 49.256173 0.7131275949857955 2.5 Street
13 IGN Espace - Parc technologique du canal 6, avenue de l'Europe - BP 42116 31521 RAMONVILLE CEDEX NaN 54470 Hamonville 5.812487 48.827340 0.6252486056441077 30.0 City
14 IGN Sologne Camp des Landes 41200 VILLEFRANCHE-SUR-CHER NaN le camp des landes, 41200 Villefranche-sur-Cher 1.718985 47.293048 1.0 Projection Street enhanced

Les résultats dans adresses_avec_geocodage.txt sont très bons mais aussi quelquefois très mauvais. On les identifie assez vite car le résultat est alors avec une précision "à la ville" City

Voici quelques cas où le résultat est à la ville et ce n'est pas toujours la bonne ville d'ailleurs.

In [12]:
# Ville où code postal et adresses ne correspondent pas en fait à une commune (ville nouvelle)
# Voir https://fr.wikipedia.org/wiki/Marne-la-Vall%C3%A9e
adress_call = ign.geocode('6/8, avenue Blaise Pascal, 77455 MARNE-LA-VALLÉE CEDEX 2', 'StreetAddress',
    maximum_responses=10, exactly_one=True)
print (adress_call.address)
adress_call = ign.geocode('6/8, avenue Blaise Pascal, Champs sur Marne', 'StreetAddress',
    maximum_responses=10, exactly_one=True)
print (adress_call.address)
39270 Marnézia
6/8 av blaise pascal, 77420 Champs-sur-Marne
In [13]:
# Juste un édifice mais sans rue donc un peu normal mais gagnerait à utiliser des noms de bâtiments
# Pour éviter des erreurs sur les accents
address = 'Château des Barres, 45290 NOGENT-SUR-VERNISSON'.encode('ascii', errors='xmlcharrefreplace')
adress_call = ign.geocode(address, maximum_responses=10, exactly_one=True)
print (adress_call.address)
45290 Nogent-sur-Vernisson
In [16]:
# Correspondance la meilleure (similarité de chaîne du genre calcul de la distance de Levenshtein)
# Malheureusement, le nom de la commune est incomplet donc c'est faux.
# Le calculateur semble ignorer l'indication que fournit le code postal dans la chaîne envoyée
address = "6, avenue de l'Europe - BP 42116, 31521 RAMONVILLE CEDEX".encode('ascii', errors='xmlcharrefreplace')
adress_call = ign.geocode(address, maximum_responses=10, exactly_one=True)
print (adress_call.address)
address = "6, avenue de l'Europe - BP 42116, 31521 RAMONVILLE-SAINT-AGNE CEDEX".encode('ascii', errors='xmlcharrefreplace')
adress_call = ign.geocode(address, maximum_responses=10, exactly_one=True)
print (adress_call.address)
54470 Hamonville
6 av de l'europe, 31520 Ramonville-Saint-Agne

Récupération du code¶

Pour cela, suivez l'URL suivante https://gist.github.com/ThomasG77/6b0525707674b1bbb343

Support du géocodeur en dehors de Python¶

Le support du géocodage est plus limité mais existe aussi côté PHP.

Vous pouvez aussi utiliser CURL, un utilitaire en ligne de commande même s'il vous restera toujours à gérer le XML retourné.

Par ailleurs, des exemples sont aussi disponibles sur le site officiel de l'IGN lorsque vous voulez géocoder directement côté client (en JavaScript ou Flash) mais sans avoir besoin de garder le résultat du géocodage en mémoire http://api.ign.fr/tech-docs-js/examples/

Aide possible

Si vous avez des besoins liés au géocodage ou que certaines fonctions sont manquantes, nous pouvons les implémenter. N'hésitez pas à nous contacter.

Page 1 / 1

Social

  • atom feed
  • Twitter
  • LinkedIn
  • Viadeo




Contact

Web Geo Data Vore
+(33) 6 66 16 81 63 contact@webgeodatavore.com
44000 Nantes - France

Crédits

Articles récents

  • mar. 06 janvier 2015 - Ajout du support du géocodeur de l'IGN dans Geopy

Partenaires

  • 2I2LNotre partenaire spécialisé dans la formation et l’accompagnement à la migration vers les logiciels libres.
  • INKI dataNotre partenaire études, statistiques et observatoires
  • L'Ouvre-Boite 44Notre coopérative d'activité, elle nous accompagne dans la création et la gestion de notre activité profesionnelle
Open Data Inside

Motorisé par Pelican. Thème blueidea, inspiré du thème par défaut.