Présentation du web scraping avec Puppeteer
Google a conçu Puppeteer pour fournir une interface simple mais puissante dans Node.js permettant d'automatiser des tests et diverses tâches à l'aide du moteur de navigation Chromium. Il fonctionne en mode sans interface graphique par défaut, mais peut être configuré pour exécuter Chrome ou Chromium en mode complet.
L'API développée par l'équipe Puppeteer utilise le protocole DevTools pour prendre le contrôle d'un navigateur web, tel que Chrome, et effectuer différentes tâches, telles que :
- Prendre des captures d'écran et générer des PDF des pages
- Automatiser l'envoi de formulaires
- Tester l'interface utilisateur (cliquer sur des boutons, saisir du texte au clavier, etc.)
- Extraire une SPA et générer du contenu pré-rendu (rendu côté serveur)
La plupart des actions que vous pouvez effectuer manuellement dans le navigateur peuvent également être réalisées à l'aide de Puppeteer. De plus, elles peuvent être automatisées, ce qui vous permet de gagner du temps et de vous concentrer sur d'autres tâches.
Puppeteer a également été conçu pour être convivial pour les développeurs. Les personnes familiarisées avec d'autres frameworks de test populaires, tels que Mocha, se sentiront tout de suite à l'aise avec Puppeteer et trouveront une communauté active offrant un soutien pour Puppeteer. Cela a conduit à une croissance massive de sa popularité parmi les développeurs.
Bien sûr, Puppeteer ne se limite pas aux tests. Après tout, s’il peut faire tout ce qu’un navigateur standard peut faire, il peut s’avérer extrêmement utile pour les scrapers web. Il permet notamment d’exécuter du code JavaScript afin que le scraper puisse accéder au code HTML de la page et d’imiter le comportement d’un utilisateur normal en faisant défiler la page ou en cliquant sur des sections aléatoires.
Ces fonctionnalités indispensables font des navigateurs headless un composant essentiel de tout outil commercial d'extraction de données et de tous les scrapers web maison, à l'exception des plus simples.
Prérequis
Avant toute chose, assurez-vous que les versions à jour de Node.js et de Puppeteer sont installées sur votre machine. Si ce n'est pas le cas, vous pouvez suivre les étapes ci-dessous pour installer tous les prérequis.
Vous pouvez télécharger et installer Node.js à partir d'ici. Le gestionnaire de paquets par défaut de Node, npm, est préinstallé avec Node.js.
Pour installer la bibliothèque Puppeteer, vous pouvez exécuter la commande suivante dans le répertoire racine de votre projet :
npm install puppeteer
# or "yarn add puppeteer"
Notez que lorsque vous installez Puppeteer, la dernière version de Chromium, dont la compatibilité avec l'API est garantie, est également téléchargée.
Puppeteer en action
Cette bibliothèque offre de nombreuses possibilités. Comme nous nous concentrons principalement sur le web scraping, nous aborderons les cas d'utilisation qui sont les plus susceptibles de vous intéresser si vous souhaitez extraire des données du Web.
Prendre une capture d'écran
Commençons par un exemple simple. Nous allons écrire un script qui permettra de réaliser une capture d'écran d'un site web de notre choix.
Gardez à l'esprit que Puppeteer est une bibliothèque basée sur les promesses (elle effectue des appels asynchrones vers l'instance Chrome sans interface graphique en arrière-plan). Veillons donc à garder le code propre en utilisant async/await.
Commencez par créer un nouveau fichier nommé index.js dans le répertoire racine de votre projet.
Dans ce fichier, nous devons définir une fonction asynchrone et l'utiliser pour encapsuler tout le code Puppeteer.
const puppeteer = require('puppeteer')
async function snapScreenshot() {
try {
const URL = 'https://old.reddit.com/'
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.goto(URL)
await page.screenshot({ path: 'screenshot.png' })
await browser.close()
} catch (error) {
console.error(error)
}
}
snapScreenshot()
Tout d’abord, une instance du navigateur est lancée à l’aide de la commande puppeteer.launch(). Ensuite, nous créons une nouvelle page à l’aide de l’instance du navigateur. Pour accéder au site web souhaité, nous pouvons utiliser la méthode goto(), en passant l’URL en paramètre. Pour prendre une capture d’écran, nous utiliserons la méthode screenshot(). Nous devons également indiquer l’emplacement où l’image sera enregistrée.
Notez que Puppeteer définit une taille de page initiale de 800×600px, qui détermine la taille de la capture d'écran. Vous pouvez personnaliser la taille de la page à l'aide de la méthode setViewport().
N'oubliez pas de fermer l'instance du navigateur. Il ne vous reste plus qu'à exécuter node index.js dans le terminal.
C'est vraiment aussi simple que ça ! Vous devriez maintenant voir un nouveau fichier nommé screenshot.png dans le dossier de votre projet.
Soumettre un formulaire
Si, pour une raison quelconque, le site web que vous souhaitez scraper n'affiche pas le contenu tant que vous n'êtes pas connecté, vous pouvez automatiser le processus de connexion avec Puppeteer.
Tout d'abord, nous devons inspecter le site web que nous scrapons et trouver les champs de connexion. Pour cela, il suffit de cliquer avec le bouton droit sur l'élément et de choisir l'option Inspecter.
Dans mon cas, les champs de saisie se trouvent dans un formulaire de classe login-form. Nous pouvons saisir les identifiants de connexion à l'aide de la méthode type().
De plus, si vous souhaitez vous assurer que les actions correctes sont effectuées, vous pouvez ajouter le paramètre headless et le définir sur false lorsque vous lancez l'instance Puppeteer. Vous verrez alors comment Puppeteer effectue l'ensemble du processus à votre place.
const puppeteer = require('puppeteer')
async function login() {
try {
const URL = 'https://old.reddit.com/'
const browser = await puppeteer.launch({headless: false})
const page = await browser.newPage()
await page.goto(URL)
await page.type('.login-form input[name="user"]', 'EMAIL@gmail.com')
await page.type('.login-form input[name="passwd"]', 'PASSWORD')
await Promise.all([
page.click('.login-form .submit button'),
page.waitForNavigation(),
]);
await browser.close()
} catch (error) {
console.error(error)
}
}
login()
Pour simuler un clic de souris, nous pouvons utiliser la méthode click(). Après avoir cliqué sur le bouton de connexion, nous devons attendre que la page se charge. Nous pouvons le faire avec la méthode waitForNavigation().
Si nous avons saisi les identifiants corrects, nous devrions maintenant être connectés !
Extraire plusieurs pages
Je vais utiliser le subreddit /r/learnprogramming pour cet article. Nous voulons donc accéder au site web, récupérer le titre et l'URL de chaque publication. Nous utiliserons la méthode evaluate() pour cela.
Le code devrait ressembler à ceci :
const puppeteer = require('puppeteer')
async function tutorial() {
try {
const URL = 'https://old.reddit.com/r/learnprogramming/'
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.goto(URL)
let data = await page.evaluate(() => {
let results = []
let items = document.querySelectorAll('.thing')
items.forEach((item) => {
results.push({
url: item.getAttribute('data-url'),
title: item.querySelector('.title').innerText,
})
})
return results
})
console.log(data)
await browser.close()
} catch (error) {
console.error(error)
}
}
tutorial()
En utilisant la méthode Inspect présentée précédemment, nous pouvons récupérer tous les messages en ciblant le sélecteur .thing. Nous les parcourons un par un, et pour chacun d'entre eux, nous récupérons l'URL et le titre, puis nous les ajoutons à un tableau.
Une fois le processus terminé, vous pouvez voir le résultat dans votre console.
Parfait, nous avons extrait la première page. Mais comment extraire plusieurs pages de ce subreddit ?
C'est plus simple que vous ne le pensez. Voici le code :
const puppeteer = require('puppeteer')
async function tutorial() {
try {
const URL = 'https://old.reddit.com/r/learnprogramming/'
const browser = await puppeteer.launch({headless: false})
const page = await browser.newPage()
await page.goto(URL)
let pagesToScrape = 5;
let currentPage = 1;
let data = []
while (currentPage <= pagesToScrape) {
let newResults = await page.evaluate(() => {
let results = []
let items = document.querySelectorAll('.thing')
items.forEach((item) => {
results.push({
url: item.getAttribute('data-url'),
text: item.querySelector('.title').innerText,
})
})
return results
})
data = data.concat(newResults)
if (currentPage < pagesToScrape) {
await page.click('.next-button a')
await page.waitForSelector('.thing')
await page.waitForSelector('.next-button a')
}
currentPage++;
}
console.log(data)
await browser.close()
} catch (error) {
console.error(error)
}
}
tutorial()
Nous avons besoin d'une variable pour savoir combien de pages nous voulons extraire et d'une autre variable pour la page actuelle. Tant que la page actuelle est inférieure ou égale au nombre de pages que nous voulons extraire, nous récupérons l'URL et le titre de chaque message de la page. Une fois chaque page extraite, nous concaténons les nouveaux résultats avec ceux déjà extraits.
Ensuite, nous cliquons sur le bouton « Page suivante » et répétons le processus de scraping jusqu’à atteindre le nombre souhaité de pages extraites. Nous devons également incrémenter la page actuelle après chaque page.
Une option encore plus simple
Félicitations ! Vous avez réussi à créer votre propre scraper web avec Puppeteer. J'espère que ce tutoriel vous a plu !
Cela dit, le script que nous avons créé dans ce guide ne peut pas effectuer de tâches complexes. Il lui manque quelques éléments clés qui rendent le scraping web fluide. L'utilisation de proxys mobiles ou résidentiels et la résolution de CAPTCHA ne sont que quelques-unes des fonctionnalités manquantes.
Si vous recherchez une méthode plus professionnelle pour extraire des données, découvrez ce que WebScrapingAPI peut accomplir et voyez si cela vous convient. Il existe une offre gratuite, vous n'avez donc qu'à investir 30 minutes de votre temps.
Bon web scraping !




