L'API Temps réél Transilen sans API !

Voici un nouveau billet sur les horaires des prochains départs d'une gare du réseau SNCF Transilien... mais cette fois-ci sans recourir aux services de l'API.

L'API "API temps réel Transilien" est pratique, rapide, facile à utiliser et donne les informations suivantes :

  • date du passage du train dans la gare au format jj/mm/aaaa hh:mm
  • numéro du train
  • code mission du train
  • code UIC du terminus
  • statut (état) : retardé, retardé au départ, supprimé

Le module "Prochains Départs" du portail officiel "transilien.mobi" délivre beaucoup plus d'informations, comme les voies de départ et la liste des gares desservies par les trains (avec, bien entendu, les horaires des passages à chaque arrêt)... qu'il est possible de récupérer facilement.

 

Module "Prochains Départs"

Lorsque l'on effectue une recherche sur ce module, le formulaire de saisie nous redirige vers la page des résultats via l'url :

https://transilien.mobi/train/result?idOrigin=xxx&idDest=yyy

où xxx correspond au code TR3A (TT0020 / TVS) de la gare de départ et yyy à celui de la gare d'arrivée (voir Référentiel des gares de voyageurs)

Par exemple :

https://transilien.mobi/train/result?idOrigin=PSL&idDest=HRY

 

Si vous regardez avec attention le code source de cette page, vous remarquerez un champ input contenant la liste des résultats au format json :

<input type="hidden" name="infos" id="infos" value="[{ ... }]" />

Je vous laisse le soin de parcourir cette réponse json pour découvrir la richesse des informations retournées. Tout y est ! Voici quelques infos intéressantes :

  • trainNumber : numéro du train
  • trainMissionCode : code mission du train
  • trainDate : date de paasage du train
  • trainHour : heure de passage du train
  • trainLane : voie de départ
  • codeMention : statut/état du train
    • N : à l'heure
    • S : supprimé
    • T : retardé
  • mention : commentaire lié au codeMention

 

Toujours depuis cette page présentant les résultats, si vous cliquez sur un train, vous accéderez aux détails du parcours avec les gares desservies et les horaires de passage à chacun des arrêts...

En inspectant un le code source, vous remarquerez que ces informations sont retournées via une requête ajax :

url: '/getDetailForTrain?idTrain='+trainNumber+'&theoric='+trainInfos[index].theorique+'&origine=PSL&destination=HRY&now='+now,

Ici, l'objet "trainInfos" correspond simplement à l'objet json vu précédemment.

Si vous renvoyer manuellement cette requête et que vous regardez sa réponse, vous pourrez constater qu'elle est tout aussi riche que la précédente.

 

 

Récupération des données

1. Récupération de la liste des prochains départ

Il vous faudra au minimum le code TR3A de la gare de départ. Pour récupérer la liste des prochains départs nous allons procéder de la manière suivante :

  1. envoi d'une requête de type GET
  2. récupération du contenu du champ "infos" et de l'objet json
$idOrigin="PSL";
$idDest="HRY";
$url="https://transilien.mobi/train/result?idOrigin=".$idOrigin."&idDest=".$idDest;

// 1. Envoi de la requête
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // retourner les données brutes (données binaires)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  // ne pas vérifier le certificat
curl_setopt($ch, CURLOPT_HEADER, false); // ne pas inclure l'en-tête dans la valeur de retour.

$output = curl_exec($ch);
curl_close($ch);

// 2. Extraction du champ "infos" et de l'objet json
$html = new DOMDocument();
@$html->loadHTML($output);
$html->saveHTML();
$fieldInfos = $html->getElementbyId("infos")->getAttribute("value");

$listeTrains = json_decode($fieldInfos, TRUE);

Il ne nous reste plus qu'à extraire les informations qui nous intéressent (trainLane par exemple !)

 

 

2. Récupération de la liste des gares desservies et les horaires de passage à chacun des arrêts

Maintenant que nous avons l'objet json contenant la liste des prochains départs, nous pouvons récupérer, pour chaque train la liste des gares desservies.

Pour passer la (les requêtes), il nous faut les infos suivantes :

  • origine : nous l'avions déjà ; il s'agit du code TR3A de la gare d'origine
  • destination : idem ; il s'agit du code TR3A de la gare de destination
  • idTrain : le numéro du train => index "trainNumber" de l'objet json
  • theoric : index "theorique" (true / false) de l'objet json
  • now : encore un booléen ;  celui-ci est dépendant de la valeur de l'index "trainNumber"
    • par défaut il est positionné à true
    • si la valeur de l'index "trainNumber" n'est pas renseignée, elle est remplacé par celle de l'index "trainExternalCode et "now" est positionné à "false".

De façon minimaliste :


foreach ($listeTrains as $item ) {
    $train = new stdClass();
    $train->trainNumber = $item['trainNumber'];
    $train->now = 'true';
    if( strlen($train->trainNumber) == 0 ) {
        $train->trainNumber = $item['trainExternalCode'];
        $train->now = 'false';
    }
    
    $train->trainHour = $item['trainHour']; // Heure de départ
    $train->trainLane = $item['trainLane']; // Voie de départ
    $train->codeMention = $item['codeMention']; // statut du train
    $train->theorique = $item['theorique'];
    $train->theoriqueString = ($train->theorique) ? 'true' : 'false';
    
    $aryDepart[] = $train;
}

 

Puis on passe les requêtes :

foreach ($aryDepart as $depart) {
    $url = "https://transilien.mobi/getDetailForTrain?idTrain=".urlencode($depart->trainNumber)."&theoric=".urlencode($depart->theoriqueString)."&origine=".$idOrigin."&destination=".$idDest."&now=".urlencode($depart->now);
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_HEADER, false);
    $output = curl_exec($ch);
    curl_close($ch);

    $listeArrets = json_decode($output, TRUE);

}

 

Et le tour est joué !

 

Cependant je ne saurais trop vous conseiller l'utilisation de l'API officielle, même si elle ne permet pas une telle richesse de données.