Parsing ultra-rapide de page XML ou HTML par JavaScript : Exemples de l'EJP et Tempo d'EDF


Pages en relation :

Le JavaScript sur ZiBASE Multi - Mise en oeuvre

Le JavaScript sur ZiBASE Multi - Opérations sur le réseau IP

Accéder à sa station météo Netatmo

Accès Web full-JavaScript sur ZiBASE Multi : L'exemple de l'API Koubachi

Parsing ultra-rapide de page XML ou HTML par JavaScript : Exemples de l'EJP et Tempo d'EDF


ZiBASE Multi peut en une seule instruction JavaScript récupérer une information dans une page XML ou HTML lue sur le Web et lancer une fonction JavaScript et/ou lancer l'exécution d'un scénario. La présence d'un serveur PHP intermédiaire n'est pas nécessaire : ZiBASE Multi se suffit à elle-même.

L'objectif de cet article est de le montrer en prenant des exemples très pratiques :

-Sur le parsing de page XML, nous reprenons l'API du de l'objet communicant Koubachi déjà évoqué ici.

- Sur le parsing de page HTML, nous détaillons ici la récupération de l'information EJP et Tempo données chaque jour par EDF, pour le jour même et le lendemain.

L'utilisateur peut adapter ces exemples à ses besoins pour faire le parsing des pages son choix.

L'intérêt de cette  technique, valable si une information unique doit être récupérée,  réside dans le fait qu'il n'y a pas de code informatique à développer. Par contre, Il est nécessaire d'élaborer avec soin le "chemin" qui va permettre de retrouver l'information utile dans la page lue. Cet exercice est plus aisé pour une page XML que pour une page HTML car cette dernière n'a pas été conçue dans cet objectif et le mode opératoire pour y arriver reste relativement empirique.

 

 

Dans les 2 cas, XML et HTML, la même instruction est utilisée :

void httpCall(String url, String params, String callbackFunction, String method, String filter, String pageType, String launchScenario )

Voir sa documentation ici.

 

Recherche dans un fichier XML

Cette recherche fait appel à un outil relativement connu et adapté ce format:  XPath. Le plug-in "XPath Checker" de Firefox pour vous aider à déterminer très rapidement  le chemin à utiliser pour atteindre une information. Voir ici.

Exemple du Koubachi

Nous reprenons la page XML du Koubachi fourni en temps réel la plateforme du constructeur. Cette page est semblable à celle-ci.

On se fixe pour objectif la récupération du niveau d'eau de la plante  "Bananier" et l'afficher à l'écran. Au regard de la structure du fichier XML, on parcourt l'arborescence pour atteindre le champ 'vdm-water-level' qui contient le niveau d'eau et on le reporte dans le champ filter=

"/plants/plant[name='Bananier']/vdm-water-level"

On définit ensuite une fonction de CallBack f1( ) pour afficher le résultat.

on a donc :

network.httpCall("https://api.koubachi.com/v2/plants.xml", "user_credentials=xxxxxxxxxxxxxxxxxx&app_key=yyyyyyyyyyyyyyyyyyyyy", "f1", "GET","/plants/plant[name='Bananier']/vdm-water-level","XML");
function f1 (resp,val) {
android.toast(resp);
}

Résultat graphique dans une incrustation





Recherche dans un fichier HTML

Cette recherche fait appel à l'outil  JSOUP qui est bien adapté ce format et, contrairement à XPath, tolère bien les erreurs dans le fichier source (qui sont communes dans les pages HTML).

Nous vous recommandons de suffixer l'argument pageType avec le label "DEBUG" ou ":DEBUG" et de construire la chaîne de caractères filter pas à pas en observant le résultat présenté sous forme de "toast" à l'écran. (résultat qui est également reporté dans le suivi d'activité). Retirer l'option  "DEBUG" à la fin.

Exemple du contrat EJP d'EDF

L'information EJP est disponible ici :

http://particuliers.edf.com/gestion-de-mon-contrat/options-tarifaires/option-ejp/l-observatoire-2584.html

L'exercice consiste à trouver dans le code HTML où trouver l'information. On distingue 2 tables, l'une pour le jour, l'autre pour le lendemain.

On remarque

d'une part,

que l'attribut de balise td  'tabEJP1_1-hx tabEJPy_1-l1' suffit à distinguer la région (x=2:Nord, x=3=PACA, x=4:Ouest, x=5:Sud) et  le jour / lendemain (y=1:jour,  y=2:lendemain)  pour le lendemain.

D'autre part, qu'une image définit l'état EJP: ejp_oui.png: JOUR EJP, ejp_non.png: JOUR NON-EJP, ejp_nd.png: INDEFINI.

Le filtre sera alors par exemple pour le jour même pour la région "Sud" =

"td[headers=tabEJP1_1-h5 tabEJP1_1-l1]//img[src=/FRONT/NetExpress/img/ejp_oui.png]"

Se reporter à la notice du sélecteur JSOUP pour en comprendre la syntaxe (assez rugueuse comme pour XPath) :

Lien utile ici. Syntaxe formelle ici.

On choisit ici de lancer le scenario SC2 si le jour est EJP et SC3 si le jour même n'est pas EJP. L'URL ne comporte pas de paramètres et il  n'est pas déclaré ici de fonction callBack.

On a donc :

network.httpCall("https://particuliers.edf.com/gestion-de-mon-contrat/options-tarifaires/option-ejp/l-observatoire-2584.html","","","GET","td[headers=tabEJP1_1-h5 tabEJP1_1-l1]//img[src=/FRONT/NetExpress/img/ejp_oui.png]","HTMLDEBUG", "SC2:SC3");

Exemple de fonction sur EJP

 

 

Comment fonctionne le filtre ?

Les expressions JSOUP sont  séparées par '//' et sont évaluées l'une après l'autre. Chacune définit un ensemble d'items sélectionnés dans l'ensemble fourni par l'expression précédente. Cet ensemble se réduit donc à chaque expression supplémentaire. Si cet ensemble devient vide, alors il est inutile de continuer : L'élément recherché n'a pas été trouvé.

Le filtre ne vise pas en soi à fournir in fine, une chaine de caractères élémentaire "courte", voir une information binaire "présent/absent". Son résultat peut aller de 0 caractère à la totalité du document HTML en passant par tous les intermédiaires. Bien-sûr, plus le filtrage sera abouti, plus le travail de la fonction callBack sera allégé.

 

 

Exemple du contrat Tempo d'EDF

L'information Tempo est disponible ici :

http://particuliers.edf.com/gestion-de-mon-contrat/options-tarifaires/option-tempo/la-couleur-du-jour-2585.html

On procède de la même façon en observant le source HTML.

On vise ici à déclencher le scénario SC2 seulement si la période est définie comme "Blanc" sur le jour même.

Plusieurs filtres apparaissent utilisables :

"div.TempoDay:contains(Tempo d'aujourd'hui)//ul.tempoColor//li.white:contains(X)"

"div.TempoDay:contains(Tempo d'aujourd'hui)//ul.tempoHours//li.white"

"div.TempoDay:contains(Tempo d'aujourd'hui)//ul.tempoHours//span.period:contains(Blanc)"

Nous choisissons :

network.httpCall("http://particuliers.edf.com/gestion-de-mon-contrat/options-tarifaires/option-tempo/la-couleur-du-jour-2585.html","","","GET","div.TempoDay:contains(Tempo d'aujourd'hui)//ul.tempoHours//li.white","HTMLDEBUG", "SC2");


Exemple de fonction sur Tempo


 

NB : Il  est toujours possible de retourner un état non-binaire avec XPATH ou JSOUP, il suffit pour cela de soumettre à la fonction CallBack un résultat moins affiné par le filtre. Bien-entendu dans ce cas, le déclenchement direct de scénario par httpCall() devient alors inutilisable car avec un résultat non binaire (résultat binaire : trouvé/non-trouvé).

Remarque :

JSOUP sait également décoder les fichiers XML, c'est donc une alternative à XPath.

En équivalence à l'usage de XPath vu précédemment et appliqué au Koubachi, on aurait pu avoir avec JSOUP :

network.httpCall("https://api.koubachi.com/v2/plants.xml", "user_credentials=xxxxxxxxxxxxxxxxxx&app_key=yyyyyyyyyyyyyyy", "f1", "GET",
"plants//plant//:has(name:contains(Bananier))//vdm-water-level//ITEMS_BODY:RET","JSOUPDEBUG");

ou avec "raccourci" :

network.httpCall("https://api.koubachi.com/v2/plants.xml", "user_credentials=xxxxxxxxxxxxxxxxxx&app_key=yyyyyyyyyyyyyyy", "f1", "GET",
"plant:has(name:contains(Bananier))//vdm-water-level//ITEMS_BODY:RET","JSOUPDEBUG");