18
04 juin 2015

Un contenu plus à jour est disponible pour déployer Addok (la brique logicielle pour géocoder avec BAN/BANO). En effet, il s'agissait du déploiement pour la version 0.5.x de Addok.

Celui-ci est passé en 1.0 récemment. J'ai traduit la documentation officielle dont la partie tutoriel qui peut être vue comme le remplacement de ce billet de blog http://addok.readthedocs.io/fr/master-0f766f7-fr/tutorial/

Le but est de rappeler ce qu'est le géocodage. A quoi généralement, cela sert.

Dans une deuxième temps, nous introduisons la Base Adresse Nationale (BAN) et la Base Adresse Nationale Ouverte (BANO, historique). En effet, dans ce contexte, des outils pour géocoder ont été mis en oeuvre. Nous expliquerons comment les utiliser, comment installer un serveur pour géocoder chez vous si par exemple, vous avez des besoins de géocodage massif ou de personnaliser la recherche d'adresse avec vos critères lors du géocodage.

Enfin, nous verrons comment consommer les informations venant du géocodeur en voyant les principaux outils pour cela. Nous avons fait le choix dans certains cas de référencer plutôt que de simplement copier/coller les ressources officielles. Ce tutoriel n'a pas vocation à remplacer les sources officielles mais à essayer de présenter les possibilités offertes par la BAN et les outils associés pour faciliter le géocodage.

Nous nous concentrons sur l'utilisation des données mais si votre rue ou votre numéro de rue n'est pas présent, vous pouvez contribuer aussi à faire cette mise à jour (même si vous êtes une collectivité) en allant sur la partie Contribuer

Ce contenu a été présenté lors du SOTM (State Of The Map) France 2015 à Brest (29) pendant la journée d'organisation libre, le Dimanche.

Le géocodage, pour qui, pour quoi?

Il s'agit d'être capable d'associer des adresses à des coordonnées.

Cela peut servir pour calculer des itinéraires. Un utilisateur final pour chercher le trajet le plus court saisit l'adresse de départ, le géocodeur renvoie les coordonnées de départ. Il saisit ensuite l'adresse d'arrivée et obtient encore les coordonnées. Ce sont ces coordonnées qui sont généralement utilisées pour appeler le calculateur d'itinéraires. En passant un point d'arrivée et de départ, il renvoie le trajet pour par exemple faire le trajet Paris - Brest.

Un autre usage est de déterminer les coordonnées géographiques de vos clients pour ensuite comprendre comment ils sont distribués: cela peut servir pour répartir les commerciaux d'une société.

Il est aussi intéressant de pouvoir effectuer l'opération inverse, c'est du géocodage inverse (ou "reverse-geocoding") qui consiste à déterminer l'adresse depuis les coordonnées. Cela peut servir par exemple à un livreur pour confirmer qu'il est bien dans la rue où il doit livrer.

BAN/BANO, quezako?

Rappel du projet

Pompage assumé de http://adresse.data.gouv.fr/about/ à propos de BAN (Base Adresse Nationale)

La Base Adresse Nationale est une base de données qui a pour but de référencer l'intégralité des adresses du territoire français.

Elle est constituée par la collaboration entre:

  • des acteurs nationaux tels que l'IGN et La Poste,
  • des acteurs locaux tels que les collectivités, les communes, les SDIS,
  • des citoyens par exemple à travers le projet OpenStreetMap et l'association OpenStreetMap France.

Le projet est co-gouverné par l'Administrateur Général des Données et le Conseil National de l'Information Géographique.

Le site adresse.data.gouv.fr est développé par la mission Etalab du Secrétariat Général à la Modernisation de l'Action Publique (SGMAP).

Pour BANO (Base Adresse Nationale Ouverte), il s'agit du projet initié par OpenStreetMap France qui a mené à la mise en place de la BAN qui regroupe principalement OpenStreetMap France, La Poste, l'IGN et d'autres acteurs publics (collectivités locales).

La licence

Les données BAN sont sous licence double (dont ODBL) et celles de BANO en ODBL (http://bano.openstreetmap.fr/data/LICENCE.txt).

L'intérêt de BAN est qu'on dispose de plus de données car certaines viennent de l'IGN et de La Poste. Cela est à la fois une force et une faiblesse: plus d'adresses à disposition mais à l'inverse risque de bruit et moindre qualité (du moins dans un premier temps)

De l'intérêt d'installer son propre serveur Addok

Voici quelques raisons:

  • On ne peut avoir besoin de travailler que sur une zone. Dans ce cas, il n'est pas très productif d'interroger un serveur national.

  • On veut géocoder de manière massive: même si c'est possible, on risque de surcharger le serveur officiel et on aura toujours la latence liée au réseau qui sera handicapante. Pensez au concept du "fair-use" (voir la section OSM sur l'usage des tuiles par exemple). De plus, vous risquez le bannissement de votre IP pour avoir abusé des "bonnes choses".

  • On veut indexer en favorisant un champ parmi d'autres. Par exemple, on veut que la recherche favorise des résultats pour un code INSEE. En indexant spécifiquement et en donnant des règles spécifiques, on peut favoriser ce cas.

  • On peut ajouter un filtre pour par exemple spécifier le département lors de la recherche, en plus de l'adresse "classique" de type "numéro, type de voie, nom de voie, commune"

La technique: architecture générale

On a deux composantes:

  • un serveur qui mange des données adresse et s'occupe de les indexer, nommé Addok. Cela s'effectue avec Redis (une base de données clés/valeurs) permettant une indexation efficace combinée à des algorithmes de ressemblance de caractères (ngrams) côté Python.

  • un client qui appelle le serveur. Il le fait par l'intermédiaire d'un appel http. Cet appel peut être fait depuis:

    • un client lourd bureautique SIG type QGIS
    • une bibliothèque JavaScript pour la cartographie web (Leaflet ou OpenLayers)
    • une ligne de commande (géocodage CSV)
    • depuis un navigateur

Installation des briques (paquets, création dossier et environnement Python)

Installation des paquets

Au lieu de télécharger et d'enchainer des "clics-clics", les paquets sont la même chose mais installable en tapant des instructions dans la ligne de commande

sudo apt-get install redis-server python3.4 python3.4-dev python-pip python-virtualenv virtualenvwrapper

Création du répertoire

mkdir ban && cd ban

Création d'un environnement virtuel

virtualenv addok --python=/usr/bin/python3.4

PS: il est possible d'utiliser virtualenvwrapper lorsqu'on gère de nombreux environnements virtuels Python

Activation de l'environnement virtuel

source addok/bin/activate

Installation de Addok

pip install addok

Les données

Deux sources supportées officiellement

Nous avons retenu l'option 2 pour nous car plus facile à mettre en oeuvre.

Faites vos courses par département sur http://bano.openstreetmap.fr/data/ pour BANO

Sinon, faites-les sur BAN http://bano.openstreetmap.fr/BAN_odbl/. Pour ce dernier, les données de type JSON ne sont pas par département mais nationales. Il vous faudra télécharger la base complète et la filtrer ("recette" plus bas).

Pour info, les tailles des fichiers France ci-dessous

252 MB

wget http://bano.openstreetmap.fr/data/full.sjson.gz

1.8GB

gzip -d full.sjson.gz

Attention, ces chiffres sont trompeurs: l'indexation fait littéralement exploser le volume de données.

Pour notre démonstration, nous allons travailler à l'échelle du Finistère (29).

5.8 MB

wget http://bano.openstreetmap.fr/data/bano-29.json.gz

48MB

gzip -d bano-29.json.gz

Quelques exemples de filtrage pour information

Cela peut servir pour limiter encore plus les données.

Brest seule

grep '"city": "Brest"' bano-29.json > bano-29-brest.json

Brest et agglo

grep '"city": "Brest\|Bohars\|Gouesnou\|Guilers\|Guipavas\|Plougastel-Daoulas\|Plouzané\|Le Relecq-Kerhuon' bano-29.json > bano-29-brest-agglo.json

Après cet aparté, passons à Redis

Import et indexation des données dans Redis

addok batch /home/adminuser/ban/bano-29.json

addok ngrams

On utilise en fait une configuration par défaut et c'est un peu magique.

Inspectons la configuration

gedit addok/lib/python3.4/site-packages/addok/config/default.py

En effet, il est possible par exemple de changer l'indexation: nous pourrions très bien vouloir utiliser d'autres champs.

Vous pouvez aussi voir la documentation officielle

Test du serveur

Lancer le serveur

gunicorn addok.server:app

Tester que ça marche dans le navigateur avec:

http://127.0.0.1:8000/search/?q=Loguillo

Il est possible de déployer gunicorn seul ou en combinaison avec un serveur web plus classique type Apache ou Nginx mais nous ne rentrons pas dans ce détail. Une petite recherche web peut répondre facilement à cette question.

Pour visualiser dans le navigateur, il est recommandé d'avoir JSONView https://addons.mozilla.org/fr/firefox/addon/jsonview/ sous Firefox et https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc sous Chrome/Chromium

En ligne de commande,

sudo pip install httpie

http http://127.0.0.1:8000/search/?q=Loguillo

ou

sudo apt-get install curl

curl http://127.0.0.1:8000/search/?q=Loguillo | python -mjson.tool

Comprendre les appels

Vous pouvez tout simplement utiliser la documentation officielle

Elle est simplement tellement bien faite et didactique, que ce serait bête de ne pas l'utiliser. Elle est en français donc aucune excuse n'est possible ;)

Consommer l'API

Via des bibliothèques JavaScript dans le navigateur

Leaflet

Le plugin est récupérable sur https://github.com/komoot/leaflet.photon

Une illustration de son usage est le site officiel de la BAN https://adresse.data.gouv.fr/map/

OpenLayers 3

Le plugin est sur https://github.com/webgeodatavore/ol3-photon. Il est accompagné de la démo

OpenLayers 2

Il n'existe pas de code pour OpenLayers 2 mais le code pour OpenLayers 3 est quasi prêt pour cela: seule la partie zoom et construction du point pour zoomer est à changer.

Via un client comme QGIS

Sinon en ligne de commande, en ouvrant la console Python

canvas = qgis.utils.iface.mapCanvas()
centre = qgis.core.QgsPoint(-1.7923, 47.1993)
canvas.setCenter(centre)
qgis.utils.iface.mapCanvas().refresh()

import urllib2
import json

def centerToAdress(placeName):
    req = urllib2.Request('http://api-adresse.data.gouv.fr/search/?q=%s' % placeName)
    response = urllib2.urlopen(req).read()
    jsonResp = json.loads(response)
    coords = jsonResp['features'][0]['geometry']['coordinates']
    ptCentre = qgis.core.QgsPoint(*coords)
    print ptCentre
    canvas.setCenter(ptCentre)
    qgis.utils.iface.mapCanvas().refresh()

centerToAdress('Paris')

Il est possible de "pluginiser" les appels à BAN/BANO soit en hackant MMGIS, soit sur GeoCoding QGIS soit avec un développement "from scratch" (à partir de rien).

En géocodant un CSV

Si vous n'avez pas besoin de cartes dans l'immédiat mais juste des données.

Par le site web, c'est possible avec http://adresse.data.gouv.fr/csv/

Sinon, passez par les exemples officiels (dupliqués ci-dessous)

http --timeout 600 -f POST http://api-adresse.data.gouv.fr/search/csv/ data@path/to/file.csv

http -f POST http://api-adresse.data.gouv.fr/search/csv/ columns='voie' columns='ville' data@path/to/file.csv

Un jeu de données pour tester peut être l'annuaire des débits de tabac en France métropolitaine.

Pensez à n'utiliser que les premières lignes plutôt que tout le jeu de données.
Même si le géocodage marche sur le jeu de données complet, il est inutile de patienter, ni de faire des appels lourds vers le serveur officiel (ou le votre) juste pour un test.

Par des appels individuels

En fait, on les a déjà vus dans la section "Comprendre les appels".

Pour du géocodage en masse, évitez de "bourriner" sur l'API et utilisez le géocodage CSV (qui permet d'éviter de saturer le réseau à cause du nombre d'appels et aussi de diminuer la consommation mémoire) ou bien installez votre propre serveur, d'où ce workshop.

Nous espérons que vous avez apprécié ce contenu. N'hésitez pas à commenter qu'il s'agisse d'incompréhensions, d'erreurs de notre part (typo comme contenu) ou pour simplement nous remercier !

img_slideshow: 
A propos de l'auteur: 
Thomas Gratier

Intéressé par le domaine de l'Open Source, il reste curieux sur tous les sujets liés à la géomatique/cartographie. Côté code, il privilégie les languages de programmation dynamique (JavaScript, PHP, Python, ...). Il apprécie l'automatisation du traitement de données (batch, PostGIS, OGR/GDAL, ETL,...), l'opendata (OSM inclus), le webmapping (il est l'auteur d'un livre sur OpenLayers 3). Sa veille technologique au sein de l'équipe concerne surtout la dataviz, l'opensource et l'opendata.

Sa présence dans l'équipe s'explique par une phrase : "Autant mutualiser notre curiosité!"

Lecteur assidu, il est surtout un fan de pêche à la ligne quand il dispose de suffisamment de temps ;)

Commentaires

L'intérêt de BAN est qu'on dispose de plus de données car certaines viennent de l'IGN et de La Poste. Cela est à la fois une force et une faiblesse: plus d'adresses à disposition mais à l'inverse risque de bruit et moindre qualité (du moins dans un premier temps)

Pas trop de bruit en fait car L'IGN travaillait depuis des années avec la Poste et la DGFIP à l'unification des sources. On parle de sources multiples qui intègrent la BAN, mais en pratique ce sont des données unifiées via IGN qui entrent.

Excellent toto. Je suis entrain de l’exploiter en local et ça marche bien. Cependant je voudrai le déployer sur un serveur avec un host different de "127.0.0.1 exemple 192.168.0.113 et ça ne marche pas
voici l'erreur
(addok)root@ubuntu-srv1:/home/abdou.diouck/ban# gunicorn addok.server:app
[2016-01-04 16:40:45 +0100] [2229] [INFO] Starting gunicorn 19.3.0
[2016-01-04 16:40:45 +0100] [2229] [ERROR] Connection in use: ('127.0.0.1', 8000)

Comment l'expliquer?

Et puis une derrière question. Serait il possible de stocker le json depuis une table postgresql pour faciliter la recherche
Merci

Pour le point 1 http://docs.gunicorn.org/en/stable/settings.html#bind

Pour le point 2, stocker dans une base PostgreSQL serait contreproductif pour des raisons de perfomance dans ce cas précis.

Si vous voulez vraiment stocker dans une base PostgreSQL, inutile d'utiliser Addok. Addok utilise Redis beaucoup plus performant pour ce besoin précis que PostgreSQL (ce n'est pas un troll, j'adore PostGIS mais pour d'autres besoins)

Bonjour,

Au delà de la perte de performance, est-il possible d'exploiter la BAN sous sa forme actuelle pour du géocodage sous PostGIS? Il me semble que la seule extension disponible pour le moment le soit pour les USA...

Merci bien

Il n'est pas prévu (ou je ne suis pas au courant) à ce jour dans PostGIS de géocoder. L'extension TIGER (pour les US) stocke les données et les géocode comme si Addok était inclus dans PostGIS.

Pour géocoder depuis PostGIS, soit:

Merci beaucoup, je vais me plonger là dedans!

Bonjour
je viens d'installer le server BAN . Est ce que vous pouvez m'expliquer comment changer l'url http http://127.0.0.1:8000 par http://212.47.238.201:8000 ?
MErci de votre compréhension.

as tu essayé
$addok -h
pour voir les paramètres possibles ? Sinon essaye
$addok serve --port=:8000
ou
$gunicorn addok.server:app -b :8000

Bonjour,
J'ai suivi votre tutoriel mais j'ai l'erreur suivante lorsque j'exécute la ligne
pip addok batch /home/ban/bano-29.json

File "/addok/lib/python3.4/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 1: ordinal not in range(128)

Merci de relire plus attentivement le tutoriel: je n'ai jamais indiqué de lancer une commande "pip addok batch /home/ban/bano-29.json"

Serait-il possible d'avoir un exemple détaillé, par exemple en python, d'appel de l'API en mode batch avec envoi d'un fichier csv par une requête POST ?

mes essais n'aboutissent pas.

Après analyse des appels faits par httpie (basé en Python) qui est l'utilitaire pour les démos sur https://adresse.data.gouv.fr/api/#csv, j'ai fait un exemple illustrant votre besoin sur https://gist.github.com/ThomasG77/e488251696a00de73631

Il faut juste changer le nom du fichier CSV en entrée ainsi que celui en sortie. J'ai utilisé le module requests qui n'est pas dans la bibliothèque standard Python donc à vous de l'installer.

Merci, çà me parit clair.

Par contre, J'échoue dans l'installation du module requests, avec les 2 commandes proposées sur http://requests-fr.readthedocs.org/en/ :
pip install requests
pip install -i http://pip.kennethreitz.com/simple requests

Question connexe, (mais peut-être triviale car je suis encore un peu novice en python), :même si j'arrive à installer le module requests, comment distribuer mon application à des utilisateurs qui ne disposent pas du module ?

Bonjour,
Étant sur ubuntu server 16.04 LTS, j'ai du changer quelques commandes. Et ça ne fonctionne pas encore... Où/qui peut me venir en aide ?
Voici mes commandes :
- Changement : sudo apt-get install redis-server python3 python3-dev python-pip python-virtualenv virtualenvwrapper
- sudo mkdir /ban && cd /ban
- sudo virtualenv addok –python=/usr/bin/python3.5
- source addok/bin/activate (Quand je fais un python -V, je suis bien en version 3.5)
- sudo -H pip install addok (le 6h est là pour éviter les messages)
Test des données en Bretagne :
- wget http://bano.openstreetmap.fr/data/bano-29.json.gz
- gzip -d bano-29.json.gz
- addok batch /home/bano-29.json
Et là : paf !

Traceback (most recent call last):
File "/usr/local/bin/addok", line 9, in
load_entry_point('addok==0.5.0', 'console_scripts', 'addok')()
File "/usr/local/lib/python2.7/dist-packages/addok/bin/__init__.py", line 43, in main
from addok import config
File "/usr/local/lib/python2.7/dist-packages/addok/config/__init__.py", line 5, in
from .default import * # noqa
File "/usr/local/lib/python2.7/dist-packages/addok/config/default.py", line 2, in
from pathlib import Path
ImportError: No module named pathlib

Des idées pour trouver une solution ?
Merci

Bonjour,

Un réponse tardive mais cela peut servir à d'autres.

Vous utilisez

sudo -H pip install addok

Le sudo vous fait accéder au Python 2.7 de la machine et pas de l'environnement virtuel.

Par conséquent, vous devez l'enlever.

Cette déduction vient du "traceback" qui référence Python 2.7 alors que vous devriez être en 3.5.

File "/usr/local/lib/python2.7/dist-packages/addok/bin/__init__.py", line 43, in main

 

Bonjour,

Merci pour ce tuto très bien fait. Cela fonctionne "out of the box".
Cependant, ne connaissant pas Python, je n'ai pas compris la création de l'environnement virtuel et surtout comment revenir à cet environnement après un arrêt de l’environnement.
Merci.

Cordialement.

Allez dans le répertoire 'ban' puis faire

source addok/bin/activate

Ensuite, repartir de http://geotribu.net/node/811#user-content-test-du-serveur

Pour en savoir plus sur les environnements virtuels http://python-guide-fr.readthedocs.io/fr/latest/dev/virtualenvs.html (PS: je suis le traducteur fr)

Merci, c'est beaucoup plus clair.

questions subsidiaires :
- je souhaiterais rendre ce service en production, est-ce possible ? Avez-vous des recommandation particulières ?
- comment automatiser les mises à jour ?

Cordialement.