Node.js

Scraper une page web en JavaScript

Initiation au web scraping. Attention, respecter les règles pour ne pas le faire en illégalité.

Farid

Farid

23 juillet 2021

Scraper une page web en JavaScript

Le WebScraping, qu’est-ce que c’est ?

​Le web scraping consiste en la collecte d’informations sur les pages web, la plupart du temps par l’exécution de scripts automatisés.​Dans cet ère du big data et à l’aube d’une nouvelle révolution apportée par l’internet, le scraping est une pratique de plus en plus populaire parmi les développeurs. Alors que toujours plus d’entreprises comprennent l’enjeu stratégique de l’importance de la valorisation des données, le scraping est devenu aujourd’hui une source de valeur mais également une menace importante sur leurs actifs numériques.​

Le scraping et enjeux juridiques

​Nous ne pouvons pas bien sûr nous risquer à vous donner des conseils d’ordre juridique. Sachez juste que le web scraping a déjà été considéré comme illégal par des magistrats dans certains contextes. En France, il peut ainsi être qualifié de vol de données (article 323-3 du Code Pénal) et peut également être sanctionné en application de l’article L342-1 du Code de la propriété intellectuelle qui protège les producteurs de bases de données. C’est par exemple sur cette base que le site EntreParticuliers.com a été condamné à plusieurs centaines de milliers d’euros de dédommagement pour avoir scrappé illégalement Leboncoin. Par ailleurs, ce jugement (TGI de Paris, 1er septembre 2017) avait également retenu la concurrence déloyale.​

Développement d’un petit script en JS

Maintenant que vous êtes prévenus sur les risques du scraping, je vais vous apprendre ici comment mettre en place un petit script de scraping.

Conseils de bonnes pratiques sur le WebScraping

​Avant toute chose, assurez-vous d’avoir vérifiés ces points avants d’écrire votre première ligne de code.

- [ ] Y'a-t-il une API publique qui me permettrait de récuperer les données que je souhaite ? ;
- [ ] J'ai suivi les instructions du fichier robots.txt et consulté les Conditions d’Utilisation du site que je souhaite scraper ;
- [ ] J'ai un User Agent qui me permet de m'identifier et de connaître mes intentions ;
- [ ] Je réalise mes requêtes à une fréquence raisonnable ;
- [ ] Je ne stock que les données dont j'ai besoin et ne garde rien d’autre ;

Etudier le code du site

​Quand on veut scrapper les données d’un site il faut tout d’abord inspecter le html du site en question et identifier tous les élements suivants. Connaître la structure du site nous aidera à écrire notre code.​

  • id
  • class​Si un élément n’est pas identifiable pas une id ou une classe, alors il faudra l’identifier via le chemin entier du noeud.​La dépendance Got (Javascript)​Nous allons utiliser cette dépendance got pour scraper. D’après le package sur npm, got est un
Human-friendly and powerful HTTP request library for Node.js.

Soit en français, une librairie HTTP puissante et surtout pensé pour les humains ;)

Bref, installons la dépendance :​

yarn add got

​Ensuite créer un fichier index.js, et ajoutons ces lignes de commandes :​

import got from 'got';
async const scrapeData() => {
got("https://fr.wikipedia.org/wiki/Web_scraping") // Mettez le lien du site
.then(async (response) => {
console.log(response.body)
})
.catch((err) => {
console.log(err);
});
}

​Si tout se passe bien, nous devrions recevoir tout le html du site copier en chaine de caractères.

Je dis bien “si tout se passe bien”, car certains sites qui ne souhaitent pas être scraper, peuvent mettre en place des protections pour contrer ce genre de manoeuvres.​C’est bien beau tout ca ! Mais comment récupérer des données d’une chaine de caractères ?​Pour se faire on va utiliser cette fois-ci une nouvelle librairie js, jsdom, qui transforme une chaine de caractères en DOM, commençons par installer la dependance avec la ligne de commande suivante :​
yarn add jsdom

​Maintenant il ne reste plus qu’à importer la librairie, et de remplacer notre console.log par cette nouvelle classe que nous vient de JSDOM.​

import got from 'got';
import { JSDOM } from "jsdom";
async const scrapeData() => {
got("https://fr.wikipedia.org/wiki/Web_scraping")
.then(async (response) => {
const dom = new JSDOM(response.body);
return dom;
})
.then(async (response) => {
console.log(response)
})
.catch((err) => {
console.log(err);
});
}

Le DOM ?

D’après wikipedia :

le Document Object Model (DOM) est une interface de programmation normalisée par le W3C, qui permet à des scripts d’examiner et de modifier le contenu du navigateur web.

Nous avons donc besoin d’accéder au DOM afin de récupérer les noeuds des éléments que nous souhaitons scraper. Et si vous avez déjà utiliser du javascript basique ou jquery, vous savez à peu près comment ça marche.​

Que faire ensuite ?

Maintenant qu’on a récupéré le dom du site tout est possible, nous pouvons accéder à toutes les données que nous voulons en se servant des balises récupérées lors de nos travaux préliminaires.​Il existe plusieurs méthodes pour récupérer nos balises identifiées plus haut. Certains méthodes sont directement intégrés dans le navigateur, donc vous pouvez les utiliser directement. Voir la documentation de Firefox.

Dans notre cas, nous allons utiliser querySelector() qui permet de récupérer le premier élément d’une liste de classes, balises ou tout simplement un élément avec le bon id le chemin exact, la classe etc…​Dans mon cas je vais tenter de récupérer le titre de ma page Wikipédia et son introduction.​

Récupération du titre

Commençons par le titre. Malheureusement en inspectant la page je me suis rendu compte que la balise span qui contient le titre n’a ni id ni class. Si vous êtes dans mon cas, la solution la plus simple pour remédier au problème, est de trouver le plus proche parent contenant un id ou une classe (attention cependant si c’est une classe il faut préciser il s’agit du combientième) et ensuite suivre le chemin a partir de ce parent.

Dans mon cas, je m’aperçois que le “grand père” est une balise h1 a un id qui est firstHeading et que le “père” est une balise i. Donc, pour récupérer mon span, je me retrouve avec le code suite :​

document.querySelector('h1#firstHeading > i > span').textContent;

​La propriété textContent permet de récupérer le texte a l’intérieur de la balise selectionnée.​

Récupération de l’introduction

Maintenant je fais la meme chose pour l’introduction qui a un “grand père” qui est une balise div avec l’id “mw-content-text” et un “père” avec une balise div. Du coup on a :

document.querySelector('div#mw-content-text > div > p').textContent

Application dans le code

Maintenant pour l’utiliser dans il suffit de mettre ces bouts de codes dans notre promesse et d’afficher le résultat.

Voici donc le code final :​

import got from 'got';
import { JSDOM } from "jsdom";
got("https://fr.wikipedia.org/wiki/Web_scraping")
.then(async (response) => {
const dom = new JSDOM(response.body);
return dom;
})
.then(async (response) => {
const title = document.querySelector('h1#firstHeading > i > span').textContent;
const introduction = document.querySelector('div#mw-content-text > div > p').textContent;
console.log('titre', title);
console.log('introduction', introduction);
})
.catch((err) => {
console.log(err);
});
}

​Voilà un petit avant goût de comment scraper les données avec got et jsdom. Cependant beaucoup de sites bloquent, grâce à des anti-bot, l’accès a leurs informations. Dans ce cas, il faudra passer par des outils d’automatisation tel que Puppeteer qui est une librairie Node, développée par Google qui permet de contrôler une instance du navigateur Chrome Headless. Mais là, c’est tout un autre sujet.​

Conclusion

​Le web scraping peut servir à un tas de choses mais surtout de stocker les données qu’on veut d’un site. Cependant il faut être vigilant et respecter les bonnes pratiques car cela peut être apparenté à du vol, et outre le fait que ça puisse être condamnable par l’État. La bonne conscience du développeur est la première de ses qualités ;).

Technologies dans cet article ...

Back-End

Node.js

Node.js