Numeriblog Google Workspace Google Sheets, le tableur surpuissant XPath, ou comment trouver son chemin dans le Web Scraping

XPath, ou comment trouver son chemin dans le Web Scraping

L’extraction de données sur internet, également appelée « Web Scraping », est une technique qui permet de récupérer des données présentes sur internet à l’aide de programmes informatiques. Nous allons aujourd’hui nous intéresser à la fonction IMPORTXML() […]

personnes ont consulté cet article

6 minutes

Rédigé par Kevin Masliah - il y a 2 ans

XPath, ou comment trouver son chemin dans le Web Scraping

L’extraction de données sur internet, également appelée « Web Scraping », est une technique qui permet de récupérer des données présentes sur internet à l’aide de programmes informatiques.

Nous allons aujourd’hui nous intéresser à la fonction IMPORTXML() qui fait partie des fonctions d’importation de Google Sheets et plus particulièrement au langage de requête XPath, qui permettra, au travers de cette fonction, de cibler la partie de code que vous souhaitez extraire.

Certains d’entre vous se sont peut-être déjà essayés avec une formule de Sheets.

Comme pour toutes les formules, Google nous aide pas à pas dans l’écriture de la syntaxe.

Alors qu’est-ce que nous dit le centre d’aide Google ?

=IMPORTXML(url; requête_xpath; paramètres régionaux)

Importe des données depuis des types de données structurées tels que XML, HTML, CSV, TSV et des flux RSS et ATOM XML.

url : URL de la page à examiner (en le plaçant entre guillemet ou en faisant référence à une cellule)

requête_xpath : requête XPath à exécuter sur les données structurées

Ok ! Mais c’est quoi le XPath ? Et c’est là que les choses se corsent ! 

En gros, Comme pour la formule QUERY(), Google nous fait plus ou moins comprendre qu’il va falloir apprendre un nouveau langage ! Et effectivement, c’est ce que l’on appelle le langage de requête XPath.

Ces requêtes vont nous permettre de cibler la ou les parties du code HTML qui nous intéressent, mais pour cela, il va falloir comprendre comment est écrit (ou coder) le langage HTML.

Le code HTML est composé essentiellement de balises ouvrantes et fermantes (ici en rose) qui peuvent comporter des attributs (ici en orange) avec pour la plupart des valeurs (ici en bleu), le tout pouvant enfermer du texte (ici en noir) celui-là même qui nous est retranscrit sur notre écran à travers la page HTML.

Justement, c’est ce qui nous intéresse ! Récupérer le texte (ou même image) que l’on retrouve sur notre site internet afin de l’exploiter.

Passons aux choses sérieuses !

Disons que je voudrais récupérer des datas sur la page https://webscraper.io/test-sites/e-commerce/static.  

Pour l’exemple, j’ai sélectionné un site créé pour la pratique des novices du Web Scraping, afin de se faire la main et de ne pas perturber un vrai site internet.

Pour commencer, il faut vérifier qu’il est possible de récupérer les datas sur cette page car, oui, il n’est pas possible, avec la fonction IMPORTXML(), de scraper tous les sites. Il semblerait que la formule n’apprécie pas trop le Javascript !

Pour ce faire, allez sur la page à scraper, appuyez sur la touche « F12« , ou faites « clic droit / inspecter« . Une fois l’inspecteur de code ouvert, appuyez simultanément sur « CRTL + SHIFT + P« . Une commande s’ouvre, écrivez « Javascript« , et cliquez sur « Disable JavaScript » afin de désactiver le Javascript sur la page. Appuyez sur la touche « F5 » pour rafraîchir la page ! 

Si la data que vous cherchez à scraper est toujours visible à l’écran ou sur le code HTML, c’est tout bon, ça signifie que vous devriez réussir votre récolte ! Vous pouvez maintenant réactiver le Javascript avec un « CRTL + SHIFT + P » sur l’inspecteur, écrivez « Javascript« 

et enfin cliquez sur « Enable JavaScript » afin de le réactiver ! Rafraîchissez la page et le Javascript fait son retour.

Maintenant allons cibler le code qui nous intéresse sur la page. Il y a plusieurs méthodes, la plus simple quand on débute est de faire « clic droit / inspecter » sur l’élément que l’on souhaite récupérer. De cette manière, l’inspecteur ouvre précisément la partie de code concernée. Vous pouvez sinon inspecter tout le code pour rechercher la partie qui vous intéresse, ou alors faire un « SHIFT + CRTL + S » et le pointer directement avec votre souris.

Je vais débuter par les liens des menus de produits (“Computers” et “Phones”), comme ça, je pourrais naviguer de lien en lien. « clic droit / inspecter » sur « Computers« . En bougeant la souris sur le code, chaque élément est mis en surbrillance pour mieux le repérer.

Mon 1er lien est dans une balise « a« , cette balise « a » comporte un attribut « href« , et cette attribut « href » à pour valeur « /test-sites/e-commerce/static/computers« , qui correspond à la fin de l’URL de la page, auquel il faudra pécéder « https://webscraper.io » pour pouvoir reconstruire l’URL complet. Le texte «  Computers  » (avec les espace), qui correspond au nom de la page, n’est visible qu’en cliquant sur la balise “a”. Celui-ci est enfermé entre les 2 balises « a« , l’ouvrante (<a>) et la fermante (</a>).

Pour récupérer le XPath, il y a plusieurs méthodes, la plus simple, et celle que j’apprécie le moins, « clic droit / copy / copy XPath » ou « clic droit / copy / copy full XPath« .

On va tester le XPath avec un “CRTL + F” dans l’inspecteur de code, je colle ma requête, et je vérifie sur la droite le nombre de réponses pour être sûr de bien cibler le code. Si le nombre est plus ou moins que celui attendu c’est qu’il y a un problème ! 

/html/body/div[1]/div[3]/div/div[1]/div/div/ul/li[2]/a

« copy full XPath » vous donnera un chemin “absolue”, en partant de la balise « html« , c’est-à-dire au démarrage du code.

Explications du XPath : vous ciblez une balise « a« , contenu dans la deuxième balise « li » (2ème à cause du [2], cela indique qu’il y en a plusieurs), contenu dans une balise « ul« , contenu dans une balise « div« ,…. et ainsi de suite jusqu’à la balise « html« . Chacune des balises est précédée du symbole « / » signifiant un chemin « absolu« , c’est-à-dire un lien direct, comme si les balises étaient « l’enfant de » ou « le parent de« .

//*[@id= »side-menu »]/li[2]/a

« copy XPath » vous donnera un chemin “relatif” ,donc plus court. 

Explication du XPath : vous ciblez une balise « a« , contenu dans la deuxième balise « li« , contenu dans toutes les balises qui comporte un attribut « id » (le symbole « @ » indique qu’il s’agit d’un attribut) qui a pour valeur « side-menu« , le tout entre crochet « [] » et le symbole « * » signifiant « tous« . Contrairement au premier exemple, le XPath commence par « //« , ce qui signifie un chemin « relatif« , en quelque sorte, celà permet de sauter des balises.

Comme je vous l’ai dit précédemment, je ne suis pas trop fan de ces méthodes car elles ne sont qu’un enchaînement de balise. Aucune personnalisation avec des attributs, ni des valeurs. Surtout, le résultat n’est pas bon, on ciblera le “a” et non le “href”. 

L’autre méthode consiste à recréer vous-même un chemin unique, en ciblant des attributs et/ou des valeurs propres aux balises. 

Dans ce cas j’aurais tendance à l’écrire avec une légère différence.

//a[@class=”category-link “]/@href

Explication : je récupère le “href” (lien), compris dans toutes les balises “a” ayant un attribut “class” qui a pour valeur “category-link ”. Et là, je récupère tous les liens compris dans les menus qui m’intéressent, soit les menus “Computers” et “Phones”.

Pour les noms des menus, même chose, sauf que je remplace le “@href” par “text()” afin de récupérer cette fois tous les textes entre les balises “a”. 

//a[@class=”category-link “]/text()

Par contre, petit problème pour le texte, j’ai récupéré des cellules vides non visibles dans le code, je vais donc écrire que je ne veux récupérer que le premier “text()” des balises “a” en ajoutant “[1]” a la fin de la requête, soit :

//a[@class=”category-link “]/text()[1]

Je vais maintenant me balader dans les liens, pour récupérer les sous menus. Pour cela j’ouvre la page du premier lien, “clic droit / inspecter” sur le sous menu “Laptops”, “CTRL + F” pour vérifier mon XPath afin d’être sûr de cibler la bonne partie du code.

Je vois que mon “href” est dans une balise “a”, dans une balise “li”, puis dans une balise “ul” avec un attribut “class” différent des autres, qui a pour valeur “nav nav-second-level collapse in” !

//ul[@class= »nav nav-second-level collapse in »]/li/a/@href

Je vérifie le nombre de résultats, 2, c’est bon j’ai bien mes 2 liens des sous menus “Laptops” et “Tablets”, du menu “Computers”.

Je remplace ensuite “@href” par “text()” et j’ai bien mes 2 résultats, tout va bien ! 

//ul[@class= »nav nav-second-level collapse in »]/li/a/text()

Je passe donc au deuxième menu, même procédé ! je vais sur la page “Phones”, “F12” pour inspecter, “CTRL + F” pour vérifier le XPath, je réessaye les mêmes requêtes car le code est identique.

//ul[@class= »nav nav-second-level collapse in »]/li/a/@href

//ul[@class= »nav nav-second-level collapse in »]/li/a/text()

Et je récupère bien le lien et le nom du sous-menu “Touch”, tout fonctionne, c’est parfait. Je peux donc naviguer dans chaque sous menu pour récupérer cette fois tous les produits ! 

Après être allé sur chacune des pages produits des sous menus, je remarque que 3 choses : 

premièrement, il n’y a que 6 produits par page ;

deuxièmement, il y a plusieurs pages produits par page de sous menu (20 pour “Laptops”, 4 pour “Tablets”, et 2 pour “Touch”) ;

troisièmement, en cliquant sur les pages produits, l’url change en ajoutant “?page=” et le numéro de la page.

En conclusion, pour naviguer de page en page, il me suffit juste d’ajouter “?page=” et le numéro de la page souhaitée à mon URL. Et cela fonctionne même pour la page 1 ! Magnifique !

Maintenant que l’on a trouvé le moyen de paginer, on regarde ce que l’on peut récupérer sur chaque produit !

2 options s’offrent à nous, prendre les infos de chaque produit sur la page où se trouvent tous les produits, ou alors naviguer dans la page de chaque produit. Il est possible que vous trouviez plus de détails intéressants sur la page du produit… ou pas ! 

Après vérification, il y des infos intéressantes, mais celles-ci évoluent après un clic sur un bouton, malheureusement, avec la fonction IMPORTXML(), vous n’allez pas pouvoir simuler un clic de la souris, et donc faire apparaître ces infos. Vous ne pourrez donc pas les scraper ! Cependant, Google Apps Script vous permettra de le faire, mais nous verrons ça dans un autre article.

Je vous laisse continuer seul l’entraînement, essayer de récupérer toutes les infos de chaque article, de chaque page produits, de chaque sous menu.

En bonus, si vous souhaitez récupérer les images, cibler l’attribut “src” (vous terminerez donc votre requête avec “@src”) afin de scraper l’url de l’image, et imbriquer le dans la fonction IMAGE(), et laissez opérer la magie. 

Voici la démonstration de l’exercice sur un Google Sheets.

La prochaine fois, on verra ensemble les notions d’ancestor, following-sibling, preceding-sibling, contains, not contains, starts-with et ends-with. Elles vous permettront d’encore mieux cibler le code, en naviguant dedans sous forme de conditions !

À bientôt pour la suite.

Besoin d'un peu plus d'aide sur Sheets ?

Des formateurs sont disponibles toute l'année pour vous accompagner et optimiser votre utilisation de Sheets, que ce soit pour votre entreprise ou pour vos besoins personnels !

Découvrir nos formations Sheets

Rédacteur

S’abonner
Notification pour
1 Commentaire
Le plus ancien
Le plus récent Le plus populaire
Commentaires en ligne
Afficher tous les commentaires
DUPONT

Bonjour,
Bravo pour cet article de qualité
Il serait également intéressant d’aborder la récupération d’informations depuis un xml local et montrer les solutions existantes.
En effet, j’utiliser le drive auparavant pour récupérer les informations du xml (peu fiable et peu réactif) ; c’est pourquoi je suis désormais passer sur Google cloud storage (gratuit au vu du volume de stockage utilisé).
J’enregistre mon XML et récupéré l’URL publique.
Bien à vous.