Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Ève

Accéder au service Vélib en REST

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)