Une introduction au Web Scraping avec Cheerio

Le web scraping est une technique qui permet d’obtenir des données d’un site web particulier. Les sites Web utilisent HTML pour décrire leur contenu. Si le HTML est propre et sémantique, il est facile de l’utiliser pour localiser des données utiles.

Vous utiliserez généralement un grattoir Web pour obtenir et surveiller les données et suivre les modifications futures de celles-ci.

Concepts jQuery à connaître avant d’utiliser Cheerio

jQuery est l’un des packages JavaScript les plus populaires qui existent. Il facilite le travail avec le modèle d’objet de document (DOM), la gestion des événements, l’animation, etc. Cheerio est un package de scraping Web qui s’appuie sur jQuery, partageant la même syntaxe et la même API, tout en facilitant l’analyse des documents HTML ou XML.

Avant d’apprendre à utiliser Cheerio, il est important de savoir comment sélectionner des éléments HTML avec jQuery. Heureusement, jQuery prend en charge la plupart des sélecteurs CSS3, ce qui facilite la récupération des éléments du DOM. Jetez un oeil au code suivant :

 $("#container");

Dans le bloc de code ci-dessus, jQuery sélectionne les éléments avec l’id de « container ». Une implémentation similaire utilisant l’ancien JavaScript normal ressemblerait à ceci :

 document.querySelectorAll("#container");

En comparant les deux derniers blocs de code, vous pouvez voir que le premier bloc de code est beaucoup plus facile à lire que le second. C’est la beauté de jQuery.

jQuery possède également des méthodes utiles telles que text(), html(), etc., qui permettent de manipuler des éléments HTML. Il existe plusieurs méthodes que vous pouvez utiliser pour parcourir le DOM, comme parent(), siblings(), prev() et next().

La méthode each() de jQuery est très populaire dans de nombreux projets Cheerio. Il vous permet d’itérer sur des objets et des tableaux. La syntaxe de la méthode each() ressemble à ceci :

 $(<element>).each(<array or object>, callback)

Dans le bloc de code ci-dessus, le rappel s’exécute pour chaque itération du tableau ou de l’argument de l’objet.

Chargement HTML avec Cheerio

Pour commencer à analyser des données HTML ou XML avec Cheerio, vous pouvez utiliser la méthode cheerio.load(). Jetez un oeil à cet exemple:

 const $ = cheerio.load('<html><body><h1>Hello, world!</h1></body></html>');
console.log($('h1').text())

Ce bloc de code utilise la méthode jQuery text() pour récupérer le contenu textuel de l’élément h1. La syntaxe complète de la méthode load() ressemble à ceci :

 load(content, options, mode)

Le paramètre de contenu fait référence aux données HTML ou XML réelles que vous transmettez à la méthode load(). options est un objet optionnel qui peut modifier le comportement de la méthode. Par défaut, la méthode load() introduit les éléments html, head et body s’ils manquent. Si vous souhaitez arrêter ce comportement, assurez-vous que vous avez défini mode sur false.

Gratter les nouvelles des hackers avec Cheerio

Le code utilisé dans ce projet est disponible dans un Référentiel GitHub et est libre d’utilisation sous la licence MIT.

Il est temps de combiner tout ce que vous avez appris jusqu’à présent et de créer un simple grattoir Web. Hacker News est un site Web populaire pour les entrepreneurs et les innovateurs. C’est également un site Web idéal pour exploiter vos compétences en matière de grattage Web, car il se charge rapidement, possède une interface très simple et ne diffuse aucune annonce.

Assurez-vous que Node.js et le gestionnaire de packages de nœuds sont en cours d’exécution sur votre machine. Créez un dossier vide, puis un fichier package.json, et ajoutez le JSON suivant dans le fichier :

 {
  "name": "web-scraper",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "nodemon index.js"
  },
  "author": "",
  "license": "MIT",
  "dependencies": {
    "cheerio": "^1.0.0-rc.12",
    "express": "^4.18.2"
  },
  "devDependencies": {
    "nodemon": "^3.0.1"
  }
}

Après cela, ouvrez le terminal et exécutez :

 npm i

Cela devrait installer les dépendances nécessaires dont vous avez besoin pour construire le grattoir. Ces packages incluent Cheerio pour analyser le code HTML, ExpressJS pour créer le serveur et, en tant que dépendance de développement, Nodemon, un utilitaire qui écoute les modifications apportées au projet et redémarre automatiquement le serveur.

Configurer les choses et créer les fonctions nécessaires

Créez un fichier index.js et, dans ce fichier, créez une variable constante appelée « PORT ». Définissez PORT sur 5500 (ou le nombre que vous choisissez), puis importez respectivement les packages Cheerio et Express.

 const PORT = 5500;
const cheerio = require("cheerio");
const express = require("express");
const app = express();

Définissez ensuite trois variables : url, html et finishPage. Définissez l’URL sur l’URL Hacker News.

 const url="https://news.ycombinator.com";
let html;
let finishedPage;

Créez maintenant une fonction appelée getHeader() qui renvoie du code HTML que le navigateur doit afficher.

 function getHeader(){
    return `
        <div style="display:flex; flex-direction:column; align-items:center;">
        <h1 style="text-transform:capitalize">Scraper News</h1>
        <div style="display:flex; gap:10px; align-items:center;">
        <a href="https://www.makeuseof.com/" id="news" onClick='showLoading()'>Home</a>
        <a href="https://wilku.top/best" id="best" onClick='showLoading()'>Best</a>
        <a href="https://wilku.top/newest" id="newest" onClick='showLoading()'>Newest</a>
        <a href="https://wilku.top/ask" id="ask" onClick='showLoading()'>Ask</a>
        <a href="https://wilku.top/jobs" id="jobs" onClick='showLoading()'>Jobs</a>
        </div>
        <p class="loading" style="display:none;">Loading...</p>
        </div>
`}

La création d’une autre fonction getScript() qui renvoie du JavaScript pour que le navigateur s’exécute. Assurez-vous de passer le type de variable en tant qu’argument lorsque vous l’appelez.

 function getScript(type){
    return `
    <script>
    document.title = "${type.substring(1)}"

    window.addEventListener("DOMContentLoaded", (e) => {
      let navLinks = [...document.querySelectorAll("a")];
      let current = document.querySelector("#${type.substring(1)}");
      document.body.style = "margin:0 auto; max-width:600px;";
      navLinks.forEach(x => x.style = "color:black; text-decoration:none;");
      current.style.textDecoration = "underline";
      current.style.color = "black";
      current.style.padding = "3px";
      current.style.pointerEvents = "none";
    })

    function showLoading(e){
      document.querySelector(".loading").style.display = "block";
      document.querySelector(".loading").style.textAlign = "center";
    }
    </script>`
}

Enfin, créez une fonction asynchrone appelée fetchAndRenderPage(). Cette fonction fait exactement ce que vous pensez : elle récupère une page dans Hacker News, l’analyse et la formate avec Cheerio, puis renvoie du code HTML au client pour le rendu.

 async function fetchAndRenderPage(type, res) {
    const response = await fetch(`${url}${type}`)
    html = await response.text();
}

Sur Hacker News, il existe différents types de messages disponibles. Il y a les « nouvelles », qui sont les choses sur la première page, les messages cherchant des réponses d’autres membres de Hacker News ont l’étiquette, « demander ». Les publications les plus populaires portent le libellé « meilleur », les derniers messages portent le libellé « le plus récent » et les messages concernant les offres d’emploi portent le libellé « emplois ».

fetchAndRenderPage() récupère la liste des messages de la page Hacker News en fonction du type que vous transmettez comme argument. Si l’opération de récupération réussit, la fonction lie la variable html au texte de réponse.

Ensuite, ajoutez les lignes suivantes à la fonction :

 res.set('Content-Type', 'text/html');
res.write(getHeader());

const $ = cheerio.load(html);
const articles = [];
let i = 1;

Dans le bloc de code ci-dessus, la méthode set() définit le champ d’en-tête HTTP. La méthode write() est responsable de l’envoi d’un morceau du corps de la réponse. La fonction load() prend en html comme argument.

Ensuite, ajoutez les lignes suivantes pour sélectionner les enfants respectifs de tous les éléments avec la classe « titleline ».

 $('.titleline').children('a').each(function(){
    let title = $(this).text();
    articles.push(`<h4>${i}. ${title}</h4>`);
    i++;
})

Dans ce bloc de code, chaque itération récupère le contenu textuel de l’élément HTML cible et le stocke dans la variable title.

Ensuite, poussez la réponse de la fonction getScript() dans le tableau articles. Créez ensuite une variable, finishPage, qui contiendra le code HTML final à envoyer au navigateur. Enfin, utilisez la méthode write () pour envoyer la page finie sous forme de bloc et terminez le processus de réponse avec la méthode end ().

 articles.push(getScript(type))
finishedPage = articles.reduce((c, n) => c + n);
res.write(finishedPage);
res.end();

Définition des routes pour gérer les requêtes GET

Juste sous la fonction fetchAndRenderPage, utilisez la méthode express get() pour définir les routes respectives pour différents types de publications. Utilisez ensuite la méthode listen pour écouter les connexions au port spécifié sur votre réseau local.

 app.get("https://www.makeuseof.com/", (req, res) => {
    fetchAndRenderPage('/news', res);
})

app.get("https://wilku.top/best", (req, res) => {
    fetchAndRenderPage("https://wilku.top/best", res);
})

app.get("https://wilku.top/newest", (req, res) => {
    fetchAndRenderPage("https://wilku.top/newest", res);
})

app.get("https://wilku.top/ask", (req, res) => {
    fetchAndRenderPage("https://wilku.top/ask", res);
})

app.get("https://wilku.top/jobs", (req, res) => {
    fetchAndRenderPage("https://wilku.top/jobs", res);
})

app.listen(PORT)

Dans le bloc de code ci-dessus, chaque méthode get a une fonction de rappel qui appelle la fonction fetchAndRenderPage en transmettant les types respectifs et les objets res.

Lorsque vous ouvrez votre terminal et exécutez npm run start. Le serveur devrait démarrer, puis vous pouvez visiter localhost:5500 dans votre navigateur pour voir les résultats.

Félicitations, vous venez de réussir à gratter Hacker News et à récupérer les titres des publications sans avoir besoin d’une API externe.

Aller plus loin avec le Web Scraping

Avec les données que vous extrayez de Hacker News, vous pouvez créer diverses visualisations telles que des tableaux, des graphiques et des nuages ​​​​de mots pour présenter des informations et des tendances dans un format plus digeste.

Vous pouvez également extraire des profils d’utilisateurs pour analyser la réputation des utilisateurs sur la plate-forme en fonction de facteurs tels que les votes positifs reçus, les commentaires faits, etc.