Scraping
Bas-niveau
Au contraire de Selenium, weboob est un framework basé sur la bibliothèque requests
, qui ne télécharge que les adresses demandées, sans lire les images, feuilles de styles CSS, et javascripts. weboob n'exécute pas non plus le code javascript contenu dans les pages visitées. Tout cela a l'avantage d'être très léger sur le réseau, est plus rapide à l'exécution et consomme bien moins de mémoire.
Observer un site web
Quand on veut scraper un site, il faut chercher sur le site où se trouvent les informations qui nous intéressent. Cela commence par trouver la ou les adresses des pages qui nous intéressent. Quand il s'agira d'écrire le code, il faudra également trouver quel est le parcours nécessaire pour arriver sur cette page, par exemple, il faut bien souvent passer par la page de login d'abord.
XXX Sur certains sites, dès qu'on est identifié, on pourra simplement se rendre sur l'adresse de la page qui nous intéresse. Sur d'autres sites, il faudra peut-être obligatoirement passer par une page d'accueil avant, puis un menu.
Outils du navigateur
Pour vraiment voir les requêtes et réponses qui transitent sur le réseau, il faut utiliser les outils de développement du navigateur, que l'on peut ouvrir en appuyant sur "F12" puis en passant sur l'onglet "Réseau". À ce moment là, on verra apparaitre les interactions réelles entre le navigateur et le site, et non strictement ce qu'affiche le navigateur, qui sont parfois deux choses très différentes. Il vaut mieux ouvrir cet inspecteur de requêtes avant de commencer toute la navigation sur le site, car il n'affiche que les requêtes qui sont faites après que l'inspecteur est ouvert.
Il est recommandé d'utiliser les filtres "HTML" et "XHR". Cela masquera les images, CSS qui ne contiennent aucune donnée utile, uniquement de la mise en forme. Cela masquera également les javascripts dont nous n'avons généralement pas besoin, ceux-ci servent généralement à la mise en forme aussi et sont donc inutiles. Parfois, les javascripts servent également à la navigation, mais ne sont pas nécessaires car on se contentera de réimplémenter nous-même la navigation en Python dans le connecteur weboob, sans exécuter le javascript.
La page principale
Bien qu'on ne voit qu'une URL dans la barre d'adresse, la page affichée par le navigateur n'est pas obtenue en faisant une seule requête. Par exemple, les images sont le plus souvent obtenues par des requêtes différentes.
Certains sites séparent le modèle et la vue en différentes requêtes. C'est à dire que le code HTML n'est qu'un modèle sans les données, un code javascript obtiendra les données par une requête différente (qui aura peut-être une réponse en JSON), et le javascript modifiera l'arbre DOM dynamiquement pour insérer du HTML contenant les données récupérées. Dans ce cas, il ne sera pas nécessaire de faire la requête qui renvoie la page HTML modèle (inutile) mais directement la requête qui nous renverra les données utiles.
Reproduire la navigation
Il va falloir écrire le code Python faisant la même navigation, en ne conservant que ce qui est utile. Comme nous l'avons vu, seules certaines requêtes sont utiles/nécessaires.
Il faut bien identifier les GET
et POST
, comprendre les paramètres passés, en faisant les requêtes plusieurs fois avec un navigateur, en consultant différentes pages, et en comparant ce qui change et en notant ce qui ne change pas.
De même que pour les pages, en faisant une requête, seuls certains paramètres et en-têtes sont utiles :
- les cookies sont généralement insérés par le site au login, pas la peine de les traiter manuellement
- l'entête
Host
est mis automatiquement par weboob - un certain nombre d'entêtes sont inutiles, comme
Accept-Language
,Cache-*
,Connection
,Origin
,Pragma
, etc.
Parser les pages
Une fois les bonnes requêtes trouvées, il faut identifier le contenu de la page.
Il ne faut jamais utiliser les outils du navigateur type "Copy XPath" car les expressions XPaths générées sont très fragiles et peu résilientes. Il faut plutôt observer la page et comprendre son agencement, quels éléments HTML ou classes CSS sont indicatives de là où se trouve l'information à extraire.
À ne pas faire (Copy XPath) :
/html/body/div[2]/div[2]/div[1]/div[2]/ul/li
Sur le site pris en example (http://somafm.com/), on peut trouver un XPath équivalent bien meilleur :
//div[@id="stations"]//li
Il est :
- plus court
- plus lisible et compréhensible
- plus solide (l'id du div est "stations", il ne contiendra pas autre chose que ce qui nous intéresse, moins sensible aux modifications du site)
Parfois, il est plus intéressant de se baser sur la présence d'un texte dans la page.
//td[contains(text(), "Prénom")]/following::td[1]
Attention
En utilisant la fonction "inspecteur DOM" du navigateur, on verra une version interprétée du HTML par le navigateur.
Par exemple, le navigateur ajoutera des éléments <tbody>
dans chaque <table>
s'ils n'étaient pas présents dans le code HTML renvoyé par le site, ce que ne fera pas weboob (ou une quelconque bibliothèque de parsing HTML).
Aussi, si la page est construite via javascript, la réponse HTML du serveur ne contiendra pas une partie de la page, qui sera alors ajoutée a posteriori par du javascript. weboob n'exécutant pas le javascript, certaines parties seront donc manquantes. Il faudra chercher d'où proviennent les données insérées après, le plus souvent d'une requête/réponse différente.
Dans tous ces cas, il faut se baser sur la fonction "Afficher la source" (Ctrl+U), ou bien regarder les réponses dans l'inspecteur réseau.