Première rédaction de cet article le 28 septembre 2007
Dernière mise à jour le 21 juin 2010
Le service Vélib' de location de vélos à Paris est un grand succès sur l'Internet. D'innombrables sites le discutent et proposent des mashups à partir des données Vélib'. En effet, le service Vélib' a une API REST qui permet facilement de trouver des informations.
Les grand succès du Web sont souvent les services qui exposent une
API, permettant ainsi au reste du monde de
bâtir des services à valeur ajoutée. Vélib' a une API qui permet de
connaitre l'état des stations (combien de vélos libres ? combien
d'emplacements libres ?). On peut alors assez facilement construire
des services indiquant cet état, ou faisant des statistiques sur le
long terme, par exemple avec des outils comme
RRDtool. Voir par exemple http://www.roulib.fr/
ou http://v.mat.cc/
. On peut aussi trouve un amusant
gadget Netvibes (qui marche aussi avec le
service personnalisé de Google) en http://www.ghusse.com/informatique/widget-velib-11-fonctionne-sous-netvibes_309/
.
Ainsi, pour récupérer l'état d'une station, il faut interroger
http://www.velib.paris.fr/service/stationdetails/paris/NNN
où NNN est le numéro de la station. Essayons avec un client REST
classique, curl :
% curl http://www.velib.paris.fr/service/stationdetails/paris/14024 <?xml version="1.0" encoding="UTF-8"?> <station> <available>16</available> <free>8</free> <total>24</total> <ticket>1</ticket>
16 vélos sont donc disponibles.
Quant à
http://www.velib.paris.fr/service/carto
, il
permet de récupérer la liste des stations.
Où est documentée cette API ? Eh bien justement, il semble qu'elle
ne l'est nulle part. Il faut apparemment l'extraire par
rétro-ingéniérie du code source
Javascript des pages de http://www.velib.paris.fr/
. Par exemple, la page http://www.velib.paris.fr/Trouver-une-station
appele le script Javascript
gmaps_search_station.js
qui contient :
request.open("GET", stationDetailsUrl + "/"+ this.number, true);
et, un peu plus loin, l'explication des éléments XML retournés :
instance.availableBikes = xmlDoc.getElementsByTagName('available')[0].firstChild.nodeValue; instance.freeCapacity = xmlDoc.getElementsByTagName('free')[0].firstChild.nodeValue; instance.totalCapacity = xmlDoc.getElementsByTagName('total')[0].firstChild.nodeValue;
Merci à Mathieu Arnold pour ses explications sur ce point.
Voyons maintenant un client pour accéder à ce service. Je l'écris
en C pour montrer que C ne
signifie pas forcément manipulations de bas niveau des
prises et travail XML
difficile. Pour le réseau , j'utilise l'excellente
libcurl (qui gère tous les détails,
y compris IPv6, SSL,
etc) et pour le XML la non moins excellente
libxml2. Le résultat est disponible en get-station.c
. Il se compile ainsi :
% gcc -Wall `curl-config --cflags` `xml2-config --cflags` -c get-station.c % gcc -o get-station get-station.o `curl-config --libs` `xml2-config --libs`
et s'utilise ainsi (la station 15068 est située boulevard Victor près de la gare du RER) :
% ./get-station 15068 Available bikes - Free slots - Total slots at station 15068 14 4 20
(Le total ne correspond pas car un emplacement peut être en maintenance.)
Un autre programme équivalent a été développé en Haskell, en utilisant la bibliothèque standard Network.HTTP et le paquetage HaXML pour traiter l'XML. Ce programme prend les mêmes arguments et affiche les mêmes résultats que le programme en C.
Si on préfère Java, j'ai noté que ce message en parlait.
Mais, au fait, pourquoi est-il nécessaire de faire de la rétro-ingéniérie, plutôt que de simplement lire la documentation, comme c'est le cas avec le Vélo Star de Rennes cité plus loin ? Parce que la Ville de Paris ne pense pas que le citoyen puisse avoir envie de créer lui-même. Elle le voit comme un simple consommateur. Résultat, il existe une application Vélib « officielle » sur iPhone mais les développeurs qui voudraient essayer de faire pareil pour d'autres plate-formes comme Android ne peuvent pas lutter à armes égales, puisqu'ils n'ont pas accès à la documentation. Bref, la Mairie de Paris privilégie hélas le système fermé d'Apple. Pire, il semble que le sous-traitant de la Mairie, JCDecaux, harcèle activement ceux qui essaient de développer des applications non-officielles (voir aussi ce qui est arrivé à Vélibérator).
Oublions cette triste attitude d'une mairie et de son sous-traitant (en février 2013, la Mairie de Paris a d'ailleurs annoncé un changement radical de politique dont il reste à voir s'il se concrétisera) et
voyons si on peut appliquer la même méthodologie au service Vélov de Lyon. Si on
regarde le source HTML des pages Web de http://velov.grandlyon.com/
, on trouve la mention du script Javascript
http://velov.grandlyon.com/velov/zhp/js/velov.js
qui, une fois téléchargé et étudié, nous indique que l'API est très
proche de celle de Paris (ce qui n'est pas étonnant, c'est la même
société). Développons donc un client REST, cette fois en Python. Ce programme s'utilise de la même façon :
% python get-station.py 1023 Available bikes - Free slots - Total slots at station 1023 - CROIX ROUSSE / PERFETTI 7 11 20
Le service déployé à Marseille, Le vélo, est techniquement
identique à celui de Paris. On peut utiliser les mêmes programmes,
avec l'URL http://www.levelo-mpm.fr/service/stationdetails/marseille/NNNN
.
Testons un dernier langage sur ce service, celui du shell Unix. Comme le shell n'a pas de mécanisme incorporé pour analyser le XML, nous utiliserons un script XSLT :
<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="text"/> <xsl:param name="num"/> <xsl:template match="/"> <xsl:text>Statistiques pour la station </xsl:text> <xsl:value-of select="$num"/> <xsl:apply-templates/> </xsl:template> <xsl:template match="available"> <xsl:text>Vélos libres : </xsl:text> <xsl:apply-templates/> </xsl:template> <xsl:template match="free"> <xsl:text>Bornes libres : </xsl:text> <xsl:apply-templates/> </xsl:template> <xsl:template match="total"> <xsl:text>Nombre total de bornes : </xsl:text> <xsl:apply-templates/> </xsl:template> <xsl:template match="ticket"> <xsl:text>Bornes en panne : </xsl:text> <xsl:apply-templates/> </xsl:template> </xsl:stylesheet>
et le script contient :
#!/bin/sh # Recuperer des informations sur une station du service de vélos en # libre-service Le Velo a Marseille URL="http://www.levelo-mpm.fr/service/stationdetails/marseille" STYLESHEET="format.xsl" set -e if [ "$1" = "" ]; then echo "Usage: $0 station-number" > /dev/stderr exit 1 fi num=$1 output=`mktemp /tmp/levelo-$num.XXXXX` curl --silent --output $output $URL/$num xsltproc --stringparam num $num $STYLESHEET $output rm -f $output
et s'utilise ainsi (sur la station la plus proche du Vieux Port) :
% ./get-station.sh 1156 Statistiques pour la station 1156 Vélos libres : 3 Bornes libres : 4 Nombre total de bornes : 8 Bornes en panne : 1
Ce programme marcherait probablement sans problème avec le service
Vélô à
Toulouse, qui utilise encore le même logiciel
(on trouve même /marseille
dans les URL de http://www.velo.toulouse.fr/Les-stations/Trouver-une-station
).
D'autres systèmes de location de vélos en libre-service utilisent
apparemment une interface bien différente. Ainsi, le service
BIXI de Montréal
fonctionne en publiant un seul fichier,
https://profil.bixi.ca/data/bikeStations.xml
, qui
contient à la fois l'information sur les stations et l'état actuel de
leur occupation. (Merci à Gérôme Sauve pour avoir attiré mon attention
sur ce service et à Pascal Courtois pour son analyse de
l'application avec Firebug.)
Le programme « montréalais » est également en Python mais avec une autre bibliothèque (d'API très semblable à ElementTree), lxml. Voici des exemples d'utilisation :
% python bixi.py 'Cartier / des Carrières' Cartier / des Carrières: 0 bikes, 7 empty docks % python bixi.py 'Mozart / St-Laurent' Mozart / St-Laurent: 4 bikes, 3 empty docks % python bixi.py 'Holt / Fullum' Holt / Fullum: not yet installed
Autre cas, celui du Vélo
Star de Rennes. Il faut s'enregistrer
auprès de l'entrepôt de
données de la ville et obtenir une clé. Ensuite, on lit la
documentation
de l'API (plus besoin de rétro-ingéniérie) et on peut
programmer. Il faut envoyer une requête HTTP et on récupère du XML.
Trivial à faire en Go, dans le programme gostar.go
en utilisant les bibliothèques standard Go http et xml :
% ./gostar 42 Station PONT DE STRASBOURG Bikes available: 3 Slots available: 12
Version PDF de cette page (mais vous pouvez aussi imprimer depuis votre navigateur, il y a une feuille de style prévue pour cela)
Source XML de cette page (cette page est distribuée sous les termes de la licence GFDL)