Scraping avec Cheerio : comment collecter facilement des données à partir de pages Web

Raluca Penciuc le 21 décembre 2022

Il est loin le temps où vous collectiez et traitiez manuellement les données qui vous aidaient à lancer vos projets. Qu'il s'agisse d'un site web de commerce électronique ou d'un algorithme de génération de leads, une chose est sûre : le processus de collecte de données était fastidieux et prenait beaucoup de temps.

Dans cet article, vous apprendrez comment Cheerio peut vous aider grâce à ses fonctionnalités étendues d'analyse des langages de balisage, d'abord avec quelques exemples triviaux, puis avec un cas d'utilisation réel.

Introduction à Cheerio

"Mais qu'est-ce que Cheerio ?", vous demandez-vous peut-être. Pour tenter de dissiper un malentendu courant, je vais commencer par expliquer ce que Cheerio n'est pas: un navigateur.

La confusion peut venir du fait que Cheerio analyse les documents écrits dans un langage de balisage et propose ensuite une API pour vous aider à manipuler la structure de données résultante. Mais contrairement à un navigateur, Cheerio n'effectue pas de rendu visuel du document, ne charge pas de fichiers CSS et n'exécute pas de Javascript.

En gros, Cheerio reçoit une entrée HTML ou XML, analyse la chaîne et renvoie l'API. Cela le rend incroyablement rapide et facile à utiliser, d'où sa popularité parmi les développeurs Node.js.

Mise en place de l'environnement

Voyons maintenant quelques exemples pratiques de ce que Cheerio peut faire. Tout d'abord, vous devez vous assurer que votre environnement est bien configuré.

Il va sans dire que Node.js doit être installé sur votre machine. Si ce n'est pas le cas, suivez simplement les instructions du site officiel, en fonction de votre système d'exploitation.

Assurez-vous de télécharger la version Long Term Support (LTS) et n'oubliez pas le gestionnaire de paquets Node.js (NPM). Vous pouvez exécuter ces commandes pour vous assurer que l'installation s'est bien déroulée :

node -v
npm -v

Le résultat devrait ressembler à ceci :

blog-image

Maintenant, en ce qui concerne le débat sur l'IDE : pour ce tutoriel, j'utiliserai Visual Studio Code, car il est assez flexible et facile à utiliser, mais vous êtes invités à utiliser l'IDE que vous préférez.

Il suffit de créer un dossier qui contiendra votre petit projet et d'ouvrir un terminal. Exécutez la commande suivante pour configurer un projet Node.js :

npm init -y

Cela créera une version par défaut du fichier package.json, qui pourra être modifiée à tout moment.

Prochaine étape : Je vais installer TypeScript avec les définitions de types pour Node.js :

npm install typescript @types/node -save-dev

J'ai choisi TypeScript dans ce tutoriel pour son typage statique optionnel des objets JavaScript, ce qui rend le code plus résistant aux erreurs de type. 

C'est ce même avantage qui a augmenté régulièrement sa popularité parmi la communauté JavaScript, selon une récente enquête CircleCI sur les langages de programmation les plus populaires.

Pour vérifier l'installation correcte de la commande précédente, vous pouvez exécuter :

npx tsc --version

Je vais maintenant créer le fichier de configuration tsconfig.json à la racine du répertoire du projet, qui doit définir les options du compilateur. Si vous souhaitez mieux comprendre ce fichier et ses propriétés, la documentation officielle de TypeScript est là pour vous aider. 

Si ce n'est pas le cas, il suffit de copier et de coller le texte suivant :

{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist"
},
"lib": ["es2015"]
}

C'est presque fait ! Vous devez maintenant installer Cheerio (évidemment) :

npm install cheerio

Enfin, créez le répertoire src qui contiendra les fichiers de code. En parlant de fichier de code, créez et placez le fichier index.ts dans le répertoire src .

Comment fonctionne Cheerio ?

C'est parfait ! Vous pouvez maintenant commencer.

Pour l'instant, je vais illustrer quelques fonctions de base de Cheerio à l'aide d'un document HTML statique. Copiez et collez simplement le contenu ci-dessous dans un nouveau fichier static.html au sein de votre projet :

<!DOCTYPE html>
<html lang="en">
<head>
<title>Page Name - Static HTML Example</title>
</head>
<body>
<div class="page-heading">
<h1>Page Heading</h1>
</div>
<div class="page-container">
<div class="page-content">
<ul>
<li>
<a href="#">Item 1</a>
<p class="price">$100</p>
<p class="stock">12</p>
</li>
<li>
<a href="#">Item 2</a>
<p class="price">$200</p>
<p class="stock">422</p>
</li>
<li>
<a href="#">Item 3</a>
<p class="price">$150</p>
<p class="stock">5</p>
</li>
</ul>
</div>
</div>
<footer class="page-footer">
<p>Last Updated: Friday, September 23, 2022</p>
</footer>
</body>
</html>

Ensuite, vous devez transmettre le fichier HTML à Cheerio, qui renverra l'API résultante :

import fs from 'fs'
import * as cheerio from 'cheerio'

const staticHTML = fs.readFileSync('static.html')
const $ = cheerio.load(staticHTML)

Si vous recevez une erreur à cette étape, assurez-vous que le fichier d'entrée contient un document HTML valide. Depuis la version 1.0.0 de Cheerio, ce critère est également vérifié.

Vous pouvez maintenant commencer à expérimenter ce que Cheerio a à offrir. Le paquetage NPM est bien connu pour sa syntaxe de type jQuery et l'utilisation de sélecteurs CSS pour extraire les nœuds que vous recherchez. Vous pouvez consulter leur documentation officielle pour vous faire une idée plus précise.

Supposons que vous souhaitiez extraire le titre de la page :

const title = $('title').text()
console.log("Static HTML page title :", title)

Nous devrions tester cela, n'est-ce pas ? Vous utilisez Typescript, vous devez donc compiler le code, ce qui créera le répertoire dist , puis exécutera le fichier index.js associé. Pour simplifier, je définirai le script suivant dans le fichier package.json:

"scripts": {
"test": "npx tsc && node dist/index.js",
}

Ainsi, je n'ai plus qu'à courir :

npm run test

et le script traitera les deux étapes que je viens de décrire.

D'accord, mais que faire si le sélecteur correspond à plus d'un élément HTML ? Essayons d'extraire le nom et la valeur du stock des éléments présentés dans la liste non ordonnée :

const itemStocks = {}
$('li').each((index, element) => {
const name = $(element).find('a').text()
const stock = $(element).find('p.stock').text()
itemStocks[name] = stock
})
console.log("All items stock:", itemStocks)

Exécutez à nouveau le script de raccourci, et la sortie de votre terminal devrait ressembler à ceci :

Static HTML page title: Page Name - Static HTML Example
All items stock: { 'Item 1': '12', 'Item 2': '422', 'Item 3': '5' }

Cas d'utilisation de Cheerio

C'était donc la partie émergée de l'iceberg. Cheerio est également capable d'analyser des documents XML, d'extraire le style des éléments HTML et même de modifier les attributs des nœuds.

Mais comment Cheerio peut-il aider dans un cas d'utilisation réel ?

Imaginons que nous souhaitions recueillir des données pour entraîner un modèle d'apprentissage automatique en vue d'un futur projet plus important. Habituellement, vous recherchez sur Google des fichiers d'entraînement et vous les téléchargez, ou vous utilisez l'API du site web.

Mais que faire lorsque vous ne parvenez pas à trouver des fichiers pertinents ou que le site web que vous consultez ne fournit pas d'API, limite le débit des données ou n'offre pas l'intégralité des données que vous voyez sur une page ?

C'est là que le web scraping s'avère utile. Si vous êtes curieux de connaître d'autres cas pratiques d'utilisation du web scraping, vous pouvez consulter cet article bien écrit de notre blog.

Revenons à nos moutons. Pour les besoins de l'exemple, considérons que nous sommes dans cette situation précise : nous voulons des données, et les données sont introuvables. Rappelons que Cheerio ne s'occupe ni de l'extraction HTML, ni du chargement CSS, ni de l'exécution JS.

Ainsi, dans notre tutoriel, j'utilise Puppeteer pour naviguer sur le site web, récupérer le code HTML et le sauvegarder dans un fichier. Ensuite, je répéterai le processus de la section précédente.

Pour être plus précis, je souhaite recueillir les avis du public sur Reddit concernant un module de batterie populaire et centraliser les données dans un fichier unique qui sera ensuite utilisé pour un modèle d'entraînement ML potentiel. La suite peut également varier : analyse des sentiments, étude de marché, etc.

blog-image

Demande du code HTML

Voyons comment ce cas d'utilisation se traduira dans le code. Tout d'abord, vous devez installer le paquetage NPM de Puppeteer :

npm install puppeteer

Je vais également créer un nouveau fichier reddit.ts, pour que le projet soit mieux organisé, et définir un nouveau script dans le fichier package.json:

"scripts": {
"test": "npx tsc && node dist/index.js",
"parse": "npx tsc && node dist/reddit.js"
},

Pour obtenir le document HTML, je définirai une fonction ressemblant à ceci :

import fs from 'fs'
import puppeteer from 'puppeteer'
import * as cheerio from 'cheerio'

async function getContent(url: string): Promise<void> {

// Open the browser and a new tab
const browser = await puppeteer.launch()
const page = await browser.newPage()

// Navigate to the URL and write the content to file
await page.goto(url)
const pageContent = await page.content()
fs.writeFileSync("reddit.html", pageContent)

// Close the browser
await browser.close()
console.log("Got the HTML. Check the reddit.html file.")
}

Pour tester rapidement cette fonction, ajoutez un point d'entrée dans votre code et appelez la fonction :

async function main() {


const targetURL = 'https://old.reddit.com/r/Drumming/comments/r3tidc/yamaha_ead10/'
await getContent(targetURL)
}

main()
.then(() => {console.log("All done!")})
.catch(e => {console.log("Unexpected error occurred:", e.message)})

Le fichier reddit.html devrait apparaître dans l'arborescence de votre projet, qui contiendra le document HTML que nous voulons.

Où sont mes nœuds ?

Maintenant, une partie un peu plus difficile : vous devez identifier les nœuds qui sont d'intérêt pour notre cas d'utilisation. Retournez dans votre navigateur (le vrai) et naviguez jusqu'à l'URL cible. Placez le curseur de votre souris sur la section des commentaires, cliquez avec le bouton droit de la souris et choisissez l'option "Inspecter".

L'onglet Developer Tools s'ouvre, affichant exactement le même document HTML que vous avez précédemment enregistré sur votre machine.

blog-image

Pour extraire uniquement les commentaires, vous devez identifier les sélecteurs propres à cette section de la page. Vous pouvez remarquer que toute la liste des commentaires se trouve dans un conteneur div avec une classe sitetable nestedlisting.

En allant plus loin, chaque commentaire individuel a un élément form comme parent, avec la classe usertext warn-on-unload. Ensuite, en bas, vous pouvez voir que le texte de chaque commentaire est réparti entre plusieurs éléments p.

Analyse et enregistrement des données

Voyons comment cela fonctionne dans le code :

function parseComments(): void {

// Load the HTML document
const staticHTML = fs.readFileSync('reddit.html')
const $ = cheerio.load(staticHTML)

// Get the comments section
const commentsSection = $('div.sitetable.nestedlisting')

// Iterate each comment
const comments = []


$(commentsSection).find('form.usertext.warn-on-unload').each((index, comment) => {
let commentText = ""

// Iterate each comment section and concatenate them
$(comment).find('p').each((index, piece) => {
commentText += $(piece).text() + '\n'
})

comments.push(commentText)
})

// Write the results to external file
fs.writeFileSync("comments.json", JSON.stringify({comments}))
}

D'accord, et maintenant mettons à jour le point d'entrée avec la fonction nouvellement définie et voyons comment ce code fonctionne ensemble :

async function main() {

const targetURL = 'https://old.reddit.com/r/Drumming/comments/r3tidc/yamaha_ead10/'
await getContent(targetURL)
parseComments()
}

main()
.then(() => {console.log("All done. Check the comments.csv file.")})
.catch(e => {console.log("Unexpected error occurred:", e.message)})

Exécuter le code avec le script défini précédemment :

npm run parse

Il faudra environ 5 à 10 secondes au navigateur sans tête pour s'ouvrir et naviguer jusqu'à l'URL cible. Si vous êtes plus curieux, vous pouvez ajouter des timestamps au début et à la fin de chacune de nos fonctions pour vraiment voir à quel point Cheerio est rapide.

Le fichier comments.json devrait être notre résultat final :

blog-image

Ce cas d'utilisation peut être facilement étendu à l'analyse du nombre de "upvotes" et de "downvotes" pour chaque commentaire, ou à l'obtention des réponses imbriquées dans les commentaires. Les possibilités sont infinies.

À emporter

Merci d'être arrivé jusqu'à la fin de ce tutoriel. J'espère que vous avez compris à quel point Cheerio est indispensable au processus d'extraction de données et comment l'intégrer rapidement dans votre prochain projet de scraping.

Nous utilisons également Cheerio dans notre produit, WebScrapingAPI. Si vous êtes confrontés aux nombreux défis que pose le web scraping (blocages d'IP, détection des robots, etc.), essayez Cheerio.

Nouvelles et mises à jour

Restez au courant des derniers guides et nouvelles sur le web scraping en vous inscrivant à notre lettre d'information.

We care about the protection of your data. Read our <l>Privacy Policy</l>.Privacy Policy.

Articles connexes

vignette
GuidesGuide de démarrage rapide de l'API Web Scraping

Commencez avec WebScrapingAPI, la solution ultime de web scraping ! Collectez des données en temps réel, contournez les systèmes anti-bots et bénéficiez d'une assistance professionnelle.

Mihnea-Octavian Manolache
avatar de l'auteur
Mihnea-Octavian Manolache
9 minutes de lecture
vignette
La science du Web ScrapingLe Web Scraping en toute simplicité : l'importance de l'analyse des données

Découvrez comment extraire et organiser efficacement des données pour le web scraping et l'analyse de données grâce à l'analyse de données, aux bibliothèques d'analyse HTML et aux métadonnées schema.org.

Suciu Dan
avatar de l'auteur
Suciu Dan
12 minutes de lecture
vignette
GuidesComment construire un scraper et télécharger un fichier avec Puppeteer

Découvrez 3 façons de télécharger des fichiers avec Puppeteer et construisez un scraper web qui fait exactement cela.

Mihnea-Octavian Manolache
avatar de l'auteur
Mihnea-Octavian Manolache
8 minutes de lecture