> Là, je suis un peu speed, mais je peux essayer de faire une réponse un peu
> détaillée tant que c'est chaud ce week-end (si je vais pas faire du
> voilier...)
La bonne nouvelle, c'est qu'Eridan, à Brest, ne peut (veut?) plus louer de
voilier pour le solo, et, tous mes acolytes marins étant indisponibles, me
voici coincé à Paris pour le week-end, et donc je peux tâcher de donner
quelques détails sur le "making-of" de la carte sur les emprunts toxiques. En
particulier sur la géolocalisation, qui, comme l'a souligné Pieren, nous a
causé quelques problèmes.
Je précise d'emblée combien je considère OSM comme un projet intéressant, à
soutenir, à utiliser. Preuve en est que je bataille à Libé pour utiliser OSM
chaque fois que possible. (Et c'est pas gagné d'avance...)
Et donc, s'il y a quelques critiques dans la suite de ce mail, c'est uniquement
dans un but constructif. :)
Voici donc avec quelque détail comment nous avons procédé pour la
géolocalisation automatiques des clients Dexia.
== Structure du fichier ==
Le fichier qu'on nous a donné à traiter en entrée était remarquablement bien
structuré (merci Dexia, ).
Une colonne pour typer les clients (région, département, commune, communauté
urbaine, etc.). Cette donnée se retrouve dans les "catégories de clients" de la
carte, avec quelques regroupements (notamment dans "autres", mais pas
seulement).
Ensuite, pour chaque ligne, concernant les données pouvant servir à la
géolocalisation, les colonnes disponibles étaient :
- pays (systématiquement "FRANCE")
- région, en toutes lettres (ex.: "Picardie")
- code département (01, 02...)
- code postal
- ville (avec des valeurs brutes parfois un peu polluées, par exemple : "ST
MEDARD EN JALLES CEDEX", "RENNES Cedex 9", "CHARLEVILLE MEZIERES CDX")
- adresse, avec à boire et à manger dans le champ, voici quelques exemples :
- 15, RUE FRANCIADE C.S.3414
- HOTEL DE VILLE PLACE CARNOT BP
20
- MAIRIE
- ODARC 19 AVENUE NOEL FRANCHINI
- LIEU DIT CASETTA
- SERVICES FINANCIERS 27, AVENUE IMPERATRICE-EUGENIE
- DIR DES AFF. ECO ET FINANCIERES BD DU GOUVERNEUR FELIX EBOUE BP
109
- 8 Rue du Rh“ne
- ECOPOLE ZI ET PORTUAIRE DE BOUROGNE
- PPINIÔRES D'ENTREPRISES LA MARE · JOUY
- Mr XXX YYY /B 454 SPF/DEF Bureau financement et tresorerie 3,Avenue
Victoria
- SOUS DIRECTION DE LA DETTE ET DU CONTROLE EXTERNE
HOTEL DU DEPARTEMENT
- 159 RUE PDF FRANCOIS MITTERAND BP 125
- HOTEL DU DEPARTEMENT 2 16 BOULEVARD SOUFFLOT MMe
XXX YYY-DGA Finances
- 93 AVENUE F ET I JOLIOT CURIE
- 22 AVE DU 3EME MILENAIRE BP26
- 22 -24 VIADUC KENNEDY CASE OFFICIELLE No36
- Maison de la Communaut‚ sise 2 avenue du G‚n‚ral De
Gaulle
- MAISON DE REPOS ET DE CONVALESCENCE
- 27Bis AllŠes Jean-JaurŠs
- etc.
== Obstacles rencontrés ==
Notre précédente (et unique) expérience de géolocalisation automatique
remontait à la carte sur la loi SRU. Les données pour cette carte consistaient
"simplement" en une liste de communes, et plutôt des communes importantes
puisque concernées par la loi SRU.
Nous avions utilisé Nominatim pour la géolocalisation automatique, et les
résultats étaient parfaits. Mais, j'insiste, les données étaient
particulièrement homogènes et bien cartographiées dans OSM.
Ayant cette bonne expérience de Nominatim, nous sommes partis sur la même
piste. Mais cette fois, la bataille fut autrement plus ardue.
Notre code comporte deux parties: une partie javascript front-end exploitant
des geojson, et une partie backend en amont générant ces geojson une bonne fois
pour toutes.
Pour la géolocalisation, comme principe général, nous avons généré une chaîne à
chercher par ligne du fichier, en fonction de son type. Par exemple, pour une
région, nous n'envoyions que le nom de la région. Pour une commune, seulement
le contenu de la colonne "Ville". Pour les organismes tels que les communautés
de communes, les syndicats mixtes, les offices HLM, nous envoyions une chaîne
composée avec l'adresse (nettoyée de ce qui pouvait l'être automatiquement) et
la ville.
Voici les paramètres envoyés à Nominatim:
params = {
'q' : querystring,
'format' : 'json',
'polygon': 1,
'addressdetails': 1,
'countrycodes': 'fr',
'osm_type': osm_type,
}
Quelques premières remarques:
- querystring correspond bien évidemment à la chaîne générée en python
- 'osm_type' était défini dynamiquement selon les types de clients (comme vous
pouvez le voir sur la carte, il y a des points pour les communes, les
communautés urbaines, etc. et des polygons pour les régions et les
départements).
- le paramètre "polygon", permettant d'avoir les polygonpoints d'un point,
était envoyé en permanence, une optimisation aurait été de ne l'envoyer que
pour les régions et les départements
- countrycodes n'a pas toujours été utilisé
- on ne le voit pas ici, mais il est arrivé dans le cas de traitements manuels
qu'un exclude_place_ids soit précisé
A la première itération globale du script, fantastique! nous avions des points
par centaines et des polygones sur notre carte.
En y regardant d'un peu plus près, on a vu qu'il manquait des données et que
certaines étaient erronées.
Je vais diviser les problèmes en trois catégories: ceux concernant les
polygones (régions et départements), ceux concernant les communes, et ceux
concernant les clients ayant une adresse précise.
Quelle que soit la catégorie, on verra que les problèmes ont trois sources
générales: notre inexpérience de Nominatim et OSM d'une part, des infos
erronées dans le fichier en entrée d'autre part, des "incohérences" dans les
données d'OSM enfin.
* Régions et départements
Comme dit plus haut, à la première itération du script, plein de départements
et régions sont apparus sur notre carte, ce qui était plutôt bon signe.
Mais très vite, on a remarqué qu'il en manquait.
Il y avait apparemment trois types de manques:
- soit Nominatim renvoyait un polygonpoints vide (exemple: Finistère)
- soit les données renvoyées étaient verrolées (tous les départements autour
des Charentes étaient concernés, mais aussi le Calvados ; apparemment le node
Bénauges mettait le bazar - à l'heure où j'écris, c'est toujours le cas sur la
vue détail de MapQuest, par exemple:
http://open.mapquestapi.com/nominatim/v1/details.php?place_id=79143957)
- soit Nominatim ne connaissait tout simplement pas (ex.: Côtes-d'Armor)
Nous avons donc dû chercher des sources alternatives, parmi lesquelles:
- un export d'OSM en shp fait par Freed (merci !), mais malheureusement
incomplet (l'Aquitaine ou la Corse par exemple n'avaient pas le bon polygon)
- un script permettant de parser sauvagement les pages détails de MapQuest, par
exemple: http://open.mapquestapi.com/nominatim/v1/details.php?place_id=79266078
- pour la Corse, l'Aquitaine et Poitou-Charentes, des shp glanés sur Internet
* Communes
Là encore, l'expérience de la carte SRU nous a joué un tour: dans un premier
temps, nous n'avions envoyé QUE le nom de la ville à Nominatim.
Le premier piège dans lequel nous sommes tombés est que le paramètre
countrycodes: "fr" empêchait la géolocalisation de tous les points situés en
dehors de la France métropolitaine.
Nous l'avons donc provisoirement retiré, mais alors bonjour les faux-amis. Par
exemple, recherchez "Nice 02" (02 étant un reliquat d'un nettoyage partiel de
"CEDEX 02") dans Nominatim, et vous verrez du pays ;) Le bled en question, aux
Etats-Unis, est un vrai attrape-mouches avec ses rues portant le nom de villes
françaises.
Ensuite, les nombreuses homonymies nous ont piégés, et quelques maires de
communes pointées à tort n'étaient pas contents, et à juste titre!
A force de jouer avec Nominatim, nous avions remarqué que le display_name avait
presque systématiquement la structure suivante (plus ou moins détaillée selon
l'item): numéro de rue, rue, ville, département, région, pays
Ainsi, pour essayer de cibler avec plus de précision, nous avons généré une
chaîne équivalente pour les communes (mais sans l'adresse): ville, département,
région, France. Résultat: 100% de réussite... sauf en Bretagne! "Paimpol,
Côtes-d'Armor, Bretagne, France" ne donne aucun résultat, alors que "Paimpol,
Bretagne, France" donne le bon. Idem pour "Douarnenez, Finistère, Bretagne,
France", mais là "Douarnenez, Bretagne, France" ne donne rien non plus, il faut
mettre seulement "Douarnenez, Finistère, France" pour avoir une réponse.
C'était le cas aussi pour quelques communes isolées hors de Bretagne,
"Saint-Lary-Soulan", par exemple, qui ne veut pas qu'on lui accole
"Hautes-Pyrénées".
Autre problème: certaines avaient des noms d'usage non reconnus, par exemple:
"LE TEIL D'ARDECHE", "LA MURE D'ISERE", "OUISTREHAM RIVA-BELLA".
Parfois, l'absence d'une apostrophe donnait des mauvais résultats, par exemple
"COURNON D AUVERGNE".
Enfin, quelques communes étaient tout simplement inconnues de notre cher
Nominatim, par exemple: "CONNANTRE", "LINGUIZZETTA", "REAUP-LISSE", "SAINT
LANGIS LES MORTAGNE", "SAINT-PAUL-DE-JARRAT"...
Il est à noter que les codes postaux que nous avions dans le fichier ont généré
plus de bruit en général qu'ils nous ont été utiles, et donc rapidement nous
les avons ignorés pour la géolocalisation. En revanche, nous les avons affichés
sur les popups des points, sur la carte, car cela nous aidait (et les
internautes) à repérer les erreurs en la consultant.
* Points ayant une adresse précise
Il s'agit des syndicats mixtes, communautés de communes, communautés urbaines,
organismes de logement, etc. C'est la catégorie qui nous a donné le plus de mal.
Comme on a pu le voir plus haut, la colonne "adresse" avait des valeurs très
polluées.
La première étape fut donc de trouver le plus de règles possibles pour les
nettoyer automatiquement.
Néanmoins, 460 lignes ont dû être traitées à la main. "Traitées à la main",
cela consistait à nettoyer la chaîne envoyée à Nominatim avant un nouvel envoi.
Parfois cela revenait à corriger une faute (ajouter un "R" à "MITTERAND" par
exemple), parfois c'était beaucoup plus laborieux, et il fallait en passer par
une recherche internet, des essais sur Nominatim, etc. Souvent, nous avons dû
mettre des données approchantes: par exemple, la rue d'à côté quand une rue
n'existait pas, ou parfois même le nom du village seulement quand aucune rue
n'était disponible. Le plus gros écueil de ce contournement est que parfois
deux points on pu être géolocalisés au même endroit, et sont donc affichés l'un
sur l'autre, sans pour l'instant de possibilité de les différencier, dès lors
qu'ils sont dans la même catégorie de clients (sinon, bien sûr, il suffit de
décocher une catégorie pour avoir accès à l'autre).
Une fois toutes ces lignes traitées à la main, nous sommes tombés dans un autre
piège. Pour une raison que je n'explique pas, même quand on précise lors de
l'appel à Nominatim un osm_type, la réponse contient des items de tous les
types.
Or, selon les catégories des clients, notre script cherchait un osm_type
précis: une "relation" pour les régions et les départements, un "node" pour les
autres.
Sauf que, et nous ne nous en sommes rendu compte que bien tard, quand on donne
à Nominatim un nom de rue sans lui donner de numéro, la réponse est de type
"way", et ce même si on précise "osm_type": "node" dans l'appel (j'ai aussi
essayé avec la valeur "N", vu que je n'ai pas bien compris le point de la doc à
ce sujet: http://open.mapquestapi.com/nominatim/ ; remarque: la page wiki,
elle, laisse à penser que le paramètre ne serait utile que pour le reverse:
http://wiki.openstreetmap.org/wiki/Nominatim).
Par conséquent, de nombreux points étaient ignorés par le script, qui attendait
des "node", mais ne trouvait que des "way". N'ayant pas anticipé ce point, ces
erreurs n'étaient pas mises au jour par le script. Et nous avons mis un peu de
temps à nous en rendre compte.
La géolocalisation des adresses est, comme je disais, ce qui a coûté le plus de
temps de contournement. Voici quelques exemples où l'on aurait pu attendre une
réponse de Nominatim:
- "BOULEVARD DE LATTRE DE TASSIGNY TARBES", il faut ajouter "DU GENERAL" pour
avoir une réponse => "BOULEVARD DU GENERAL DE LATTRE DE TASSIGNY TARBES"
- "42, CHEMIN POURPIER, SAINT-PAUL" => "42, CHEMIN DU GRAND POURPIER,
SAINT-PAUL"
- "16 AVENUE GEORGE LEVY, VENISSIEUX" => "16, AVENUE DU DOCTEUR GEORGES LEVY,
VENISSIEUX"
- "28/32 RUE DU XXE CORPS AMERICAIN METZ" => "28/32 AVENUE DU XXE CORPS
AMERICAIN METZ"
- "rue du 12eme arrondissement MORTAIN" => "rue du XIIeme arrondissement
MORTAIN"
Il y a aussi des erreurs parfois, par exemple "BOULEVARD SALVATOR ALLENDE", à
SAINT-HERBAIN, au lieu de SalvaDor.
Ajoutons à ça, donc, un grand nombre de rue tout simplement pas encore
cartographiées.
Malheureusement, on n'a pas noté systématiquement, lors de nos traitements
manuels, pourquoi telle ou telle adresse avait posé problème. Et donc je ne
cite ici que quelques exemples de mémoire. Je ne sais pas si ça peut aider,
mais je dois pouvoir mettre à disposition les adresses en question, dans un
fichier brut.
== Bilan ==
Rapidement:
- 5500 lignes à traiter, ça donne forcément un nombre de cas particuliers
élevé...
- si c'était à refaire, je pense que je partirais plutôt sur la piste
d'installer un PostgreSQL avec les données OSM de la France en local (avec ma
propre indexation) plutôt que d'interroger Nominatim ; mais peut-être que
j'aurais dit l'inverse si j'avais suivi cette option ;) Par ailleurs,
maintenant que j'ai en local toutes les coordonnées des départements, des
régions, et de milliers de ville, je ne partirai pas de zéro la prochaine
fois...
- tout le monde a été très content du résultat à Libé, mais je dois dire que
quand je vais voir le journaliste en lui disant: "ahem, il me reste 460 points
à traiter à la main, on fait moit'-moit' ?" et qu'il me répond "Euh, mais
Google, il les trouve, lui?", je sais que je perds quelques points ;)
- rien à voir avec la géolocalisation, mais clairement on a perdu pas mal de
temps et de cheveux dans les méandres d'OpenLayers, dont la documentation et
l'API sont certainement sponsorisés par les laboratoires Servier, ou au moins
par un marchant d'aspirine. J'attendais que Leaflet gère le geojson pour
envisager de l'utiliser, c'est maintenant chose faite, et je crois que je suis
mûr pour faire l'expérience lors de notre prochaine carte ; voire pour Chimère,
sur lequel nous avons commencé à travailler
(https://gitorious.org/~yohanboniface/chimere/djangoize/commits/refactoring),
pour l'instant surtout moi pour un projet perso
(http://epicures.enix.org:8000/), mais comme souvent c'est en éclaireur d'une
utilisation au boulot plus tard.
D'avance merci pour vos remarques !
Yohan, marin à terre
_______________________________________________
Talk-fr mailing list
[email protected]
http://lists.openstreetmap.org/listinfo/talk-fr