Le guide ultime pour construire un scraper web avec Pyppeteer

Mihnea-Octavian Manolache le 28 février 2023

blog-image

Lorsqu'il s'agit de Python et d'automatisation web, Selenium est la référence. Du moins jusqu'à présent. En raison du succès de Puppeteer dans la communauté JavaScript, les développeurs Python ont commencé à s'y intéresser de plus en plus. C'est ainsi que Pyppeteer a vu le jour. Mais qu'est-ce que Pyppeteer exactement ? Et pourquoi devrions-nous le choisir plutôt que Selenium ? Est-il suffisamment fiable pour construire une solution complexe ? C'est à toutes ces questions et à bien d'autres encore que nous allons répondre dans l'article d'aujourd'hui. Mon objectif pour aujourd'hui est que si vous lisez cet article, vous repartiez avec au moins.. :

  • Une définition de Pyppeteer et de ses cas d'utilisation
  • Une compréhension de la comparaison entre Pyppeteer et Selenium
  • Une implémentation réelle d'un scraper web utilisant Pyppeteer

Alors préparez-vous, car aujourd'hui nous allons parler et mettre la main à la pâte !

Qu'est-ce que Pyppeteer et comment l'utiliser ?

Si vous lisez ceci, il y a de fortes chances que vous soyez déjà familier avec ce qu'est le scripting web en général. Et vous avez probablement déjà entendu parler de Puppeteer ou de Selenium, selon votre langage de programmation préféré. Mais Pyppeteer est en effet plus récent sur la scène du web scraping. Pour faire court, Pyppeteer ressemble beaucoup plus à Puppeteer qu'à Selenium.

Puppeteer est une bibliothèque Node.js qui facilite le contrôle d'une version headless de Chrome via le protocole DevTools. Pyppeteer est un portage Python de Puppeteer. Tout comme le Puppeteer original, Pyppeteer est une bibliothèque, écrite en Python, qui automatise fondamentalement un navigateur. En d'autres termes, Pyppeteer est une implémentation Python de l'API Puppeteer, qui vous permet d'utiliser les fonctionnalités de Puppeteer dans un environnement Python. La principale différence entre les deux est le langage utilisé.

Terminologie de Pyppeteer à connaître

Avant d'aller plus loin, je pense que nous devrions discuter de certains termes couramment utilisés dans le contexte de Pyppeteer :

  • Sans tête: Il s'agit de lancer un navigateur sans interface utilisateur graphique (GUI). En d'autres termes, il fonctionne "en coulisse" et vous ne pouvez pas le voir à l'écran. Cette technique est généralement utilisée pour réduire l'utilisation des ressources lors du scraping.
  • Plein la tête: Inversement, un navigateur "à tête pleine" est un navigateur qui fonctionne avec une interface graphique. C'est le contraire d'un navigateur sans tête et il est souvent utilisé pour tester, déboguer ou interagir manuellement avec des pages web.
  • Contexte du navigateur: Il s'agit d'un état partagé par toutes les pages d'un navigateur. Il est généralement utilisé pour définir les paramètres du navigateur, tels que les cookies, les en-têtes HTTP et la géolocalisation.
  • DOM: Le modèle d'objet de document (DOM) est une interface de programmation pour les documents HTML et XML. Il représente la structure d'une page web sous la forme d'un arbre dont les nœuds représentent les éléments. Pyppeteer vous permet d'interagir avec les éléments d'une page en manipulant le DOM.
  • Éléments: Les éléments constitutifs d'une page web. Ils sont définis à l'aide de balises, d'attributs et de valeurs.

Bien sûr, ce n'est pas tout et vous en apprendrez davantage en cours de route. Mais je tenais à ce que vous en ayez une idée générale afin que nous ayons un point de départ solide. Je suis convaincu que la connaissance de ces termes vous aidera à mieux comprendre l'essence de cet article.

Pourquoi utiliser Pyppeteer dans votre projet de scraping ?

Je pense qu'il y a deux aspects à cette question. Le premier est de savoir pourquoi Pyppeteer est un bon choix pour le web scraping en général. Le second est pourquoi utiliser Pyppeteer plutôt que Selenium. En général, les avantages de Pyppeteer sont les suivants :

  • Évaluation de JavaScript: Pyppeteer fournit une fonction `page.evaluate()`. Elle vous permet d'exécuter du code JavaScript dans le contexte de la page.
  • Contrôle du réseau: Pyppeteer fournit une méthode `page.on()`. Elle vous permet d'écouter les événements réseau, tels que les requêtes et les réponses, qui se produisent sur une page.
  • Traçage et enregistrement: Pyppeteer vous permet de tracer l'activité du navigateur et d'enregistrer les messages du navigateur à partir d'une page. Cela facilite le débogage, le traçage et la compréhension de ce que fait un site web.

Par rapport à Selenium, il est assez similaire, dans la mesure où les deux sont utilisés pour automatiser un navigateur web. Cependant, Pyppeteer présente quelques différences et avantages clés par rapport à Selenium :

  • Simplicité: Pyppeteer a une API plus simple et plus cohérente que Selenium, ce qui le rend plus facile à utiliser pour les débutants. L'API de Pyppeteer est construite sur le protocole DevTools, qui est proche du navigateur, et elle est facile à apprendre et à utiliser.
  • Performance: Pyppeteer peut être plus rapide que Selenium car il est construit sur le protocole DevTools. Ce protocole est conçu pour le débogage de pages web et il est beaucoup plus rapide que Selenium WebDriver.
  • Meilleur contrôle du réseau: Pyppeteer permet un meilleur contrôle des paramètres réseau du navigateur, tels que l'interception des requêtes et le blocage des requêtes/réponses. Il est ainsi plus facile de tester et de diagnostiquer les problèmes liés au réseau.

Et bien sûr, il y a aussi une question de choix. Prenons mon cas. Au quotidien, je code en JavaScript. Et je connais bien Puppeteer. Mais mon langage de programmation préféré est Python. Donc si je devais construire un Scraper avec une technologie connue dans un langage que je préfère, j'opterais probablement pour Pyppeteer.

Ceci étant dit, je pense que nous avons couvert l'aspect "discours" de cet article. Il est temps de commencer à coder.

Comment créer un scraper web avec Pyppeteer

Avant de commencer à coder, laissez-moi vous présenter la documentation officielle de Pyppeteer. Je suis un partisan de l'utilisation de la documentation officielle lorsque l'on se sent bloqué. Ceci avant de poser des questions à la communauté (comme sur Stackoverflow). Je trouve généralement que la plupart des réponses peuvent être trouvées en lisant d'abord la documentation. Prenez donc ceci comme une gentille demande de ma part. Lorsque vous êtes bloqué, consultez la documentation, puis cherchez des réponses et ne posez des questions qu'en dernier recours.

#1 : Mise en place de l'environnement

Tout d'abord, en tant que développeur Python, vous êtes probablement familier avec les environnements virtuels. La première chose à faire est donc de créer un environnement virtuel pour notre projet. Voici généralement la séquence de commandes que j'utilise :

# Créer un nouveau répertoire et y naviguer

~ " mkdir py_project && cd py_project

# Créer l'environnement virtuel

~ " python3 -m venv env

# Activer l'environnement virtuel

~ " source env/bin/activate

En ce qui concerne l'environnement virtuel, tout est prêt. Il est temps de passer à l'installation de Pyppeteer. Puisque votre terminal est ouvert, tapez simplement :

# Installer le paquetage en utilisant pip

~ " python3 -m pip install pyppeteer

# Ouvrir le projet dans votre IDE

~ " code .

#2 : Créer un simple scraper Pyppeteer

La dernière commande ouvre Visual Studio Code ou votre IDE préféré. Maintenant que vous êtes dans l'environnement de développement, créons un nouveau fichier `.py` qui contiendra notre code. J'appellerai mon fichier `scraper.py`. Notez que Pyppeteer supporte nativement l'exécution asynchrone. Importons donc à la fois `asyncio` et `pyppeteer` dans notre fichier :

import asyncio
from pyppeteer import launch

Ceci fait, nous pouvons passer à un code plus compliqué. En général, je ne suis pas le plus grand défenseur de la programmation fonctionnelle. Cependant, je pense que diviser le code en petits morceaux permet un meilleur apprentissage. Enveloppons donc notre code dans une fonction :

async def scrape(url) :

browser = await launch()

page = await browser.newPage()

await page.goto(url)

content = await page.content()

await browser.close()



return content

blog-image

Cette fonction prend une URL en entrée et lance un navigateur sans tête à l'aide de pyppeteer. Ensuite, elle navigue vers l'URL fournie, récupère le contenu de la page et ferme le navigateur. La valeur renvoyée n'est rien d'autre que le code HTML collecté à partir de la page. Vous pouvez utiliser cette fonction pour récupérer presque n'importe quel site web. Pour utiliser la fonction, vous devez l'appeler dans une boucle d'événement `asyncio`, comme ceci :

async def main() :

content = await scrape('https://www.example.com')

print(content)

loop = asyncio.get_event_loop()

loop.run_until_complete(main())

#3 : Ajouter des fonctionnalités

Jusqu'à présent, nous disposons d'un grattoir fonctionnel. Mais c'est à peu près tout ce que nous avons. Si vous voulez construire un scraper web plus avancé avec Pyppeteer, vous devrez lui ajouter plus de fonctionnalités. Alerte au spoiler : nous allons plonger dans le monde de la programmation orientée objet. Mais d'abord, traçons nos objectifs. Que voulons-nous que notre scraper soit capable de faire ?

  1. Initialiser le navigateur avec quelques valeurs personnalisées
  2. Naviguer et extraire le contenu d'une page web
  3. Écrire du texte dans un champ de saisie
  4. Extraire la valeur d'un seul élément
  5. Extraire de la valeur d'éléments multiples

3.1. Options personnalisées

Créons donc une nouvelle classe `Scraper` pour l'instant et nous ajouterons ses méthodes par la suite :

class Scraper :

def __init__(self, launch_options : dict) -> None :

self.options = launch_options['options']

self.viewPort = launch_options['viewPort'] if 'viewPort' in launch_options else None

pass

Le seul argument que nous utilisons pour notre Scraper est un dictionnaire `launch_options`. Comme vous le voyez, il contient deux clés. Une clé définit les options de lancement de Pyppeteer. La seconde option est soit `None`, soit un dictionnaire contenant la `largeur` et la `hauteur` du `viewPort`. C'est ce dernier qui est utilisé pour cette méthode.

3.2. Naviguer vers une page

Si vous regardez la fonction que nous avons utilisée précédemment, vous verrez que nous couvrons à la fois la navigation et l'extraction de données brutes à partir d'une URL spécifique. La seule chose qu'il nous reste à faire est de modifier la fonction et de la transformer en une méthode pour notre Scraper :

async def goto(self, url : str) -> None :

self.browser = await launch(options=self.options)

self.page = await self.browser.newPage()

await self.page.setViewport(self.viewPort) if self.viewPort != None else print('[i] Using default viewport')

await self.page.goto(url)

Cette méthode est assez simple. Tout d'abord, elle lance un nouveau navigateur, avec les options personnalisées que nous avons définies précédemment. Elle crée ensuite une nouvelle page et, si notre dictionnaire `launch_options` contient `viewPort`, elle définit le viewPort de la page. Sinon, il affiche un simple message. Enfin, et ce n'est pas le moins important, il nous emmène à la cible.

3.3. Extraire des données brutes d'une page

Encore une fois, nous avons la méthode dans notre fonction initiale `scraper`. Nous attendrons seulement que la `page.content()` se charge et renvoie sa valeur :

async def get_full_content(self) -> str :

content = await self.page.content()

return content

3.4. Écrire du texte dans un champ de saisie

Pour écrire quelque chose dans un champ de saisie à l'aide de Pyppeteer, vous aurez besoin de deux choses. Premièrement, localiser l'élément. Deuxièmement, lui ajouter une valeur. Heureusement, Pyppeteer dispose de méthodes pour ces deux actions :

async def type_value(self, selector : str, value : str) -> None :

element = await self.page.querySelector(selector)

await element.type(value)

3.5. Extraire la valeur de la page

Rappelez-vous que nous voulons pouvoir extraire la valeur d'un seul élément ou les valeurs de plusieurs éléments. Nous pourrions utiliser une seule méthode pour les deux. Mais j'aime bien que les choses soient séparées. Pour l'instant, je vais donc ajouter deux méthodes supplémentaires :

async def extract_one(self, selector) -> str :

element = await self.page.querySelector(selector)

text = await element.getProperty("textContent")

return await text.jsonValue()

Ici, nous localisons l'élément en utilisant la méthode `querySelector`. Nous attendons ensuite le `textContent` et retournons son `jsonValue()`. D'un autre côté, lorsque nous voulons sélectionner de nombreux éléments, nous utiliserons `querySelector` :

async def extract_many(self, selector) -> list :

result = []

elements = await self.page.querySelectorAll(selector)

for element in elements :

text = await element.getProperty("textContent")

result.append(await text.jsonValue())

return result

Cette méthode fonctionne de la même manière que `extract_one`. La seule différence est sa valeur de retour. Cette fois, nous retournons une liste de tous les textes contenus dans les éléments sélectionnés. Et je pense qu'avec cet ajout, nous avons atteint tous nos objectifs.

#4 : Rendre l'opération furtive

Dans le domaine du web scraping, la furtivité peut être décrite comme la capacité à passer inaperçu. Bien entendu, la création d'un scraper totalement indétectable demande beaucoup de travail. Par exemple, le mode furtif de Web Scraping API est maintenu par une équipe dédiée. Les efforts déployés à cet effet font que l'empreinte digitale de notre scraper est unique à chaque requête.

Mais mon objectif global pour ce tutoriel est de vous mettre sur la bonne voie. Et le bon chemin pour un web scraper complet avec Pyppeteer implique d'y ajouter des fonctionnalités de furtivité. Heureusement, tout comme il y a `puppeteer-extra-plugin-stealth` dans Node, il y a aussi un paquet pour Python. Et il s'appelle intuitivement `pyppeteer-stealth`. Pour l'ajouter à votre projet, il faut d'abord l'installer en utilisant pip :

~ " python3 -m pip install pyppeteer_stealth

Importez-le ensuite dans votre projet et ajoutez-y une ligne de code supplémentaire :

async def goto(self, url : str) -> None :

self.browser = await launch(options=self.options)

self.page = await self.browser.newPage()

# Make it stealthy

await stealth(self.page)

await self.page.setViewport(self.viewPort) if self.viewPort != None else print('[i] Using default viewport')

await self.page.goto(url)

Et voici comment vous exécutez votre scraper. J'ai ajouté quelques commentaires au code pour mettre en évidence ce que fait chaque étape :

async def main():

# Define the launch options dictionary

launch_options = {

'options': {

'headless': False,

'autoClose': True

},

'viewPort': {

'width': 1600,

'height': 900

}

}

# Initialize a new scraper

scraper = Scraper(launch_options)

# Navigae to your target

await scraper.goto('https://russmaxdesign.github.io/accessible-forms/accessible-name-input01.html')

# Type `This is me` inside the input field

await scraper.type_value(

'#fish',

'This is me')

# Scrape the entire page

content = await scraper.get_full_content()

print(content)

# Scrape one single element

el = await scraper.extract_one('body > div:nth-child(14) > ul')

print(el)

# Scrape multiple elements

els = await scraper.extract_many('p')

print(els)

loop = asyncio.get_event_loop()

loop.run_until_complete(main())

Conclusion

Pyppeteer est un outil extraordinaire pour le web scraping. Il porte l'ensemble de l'API Puppeteer en Python, ce qui permet à la communauté Python d'utiliser cette technologie sans apprendre le JavaScript. De plus, je ne pense pas qu'il remplace Selenium, mais c'est certainement une bonne alternative.

J'espère que l'article d'aujourd'hui a ajouté de la valeur à votre parcours d'apprentissage. Et comme j'aime repousser les limites de chacun, je vous mets au défi de compléter ce que vous avez appris aujourd'hui. Le scraper que nous avons construit ensemble est un très bon point de départ et introduit un élément clé de la programmation : OOP. Je vous mets donc au défi d'ajouter d'autres méthodes à `Scraper` et de le rendre vraiment étonnant.

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
GuidesSERP Scraping API - Guide de démarrage

Collectez sans effort des données en temps réel à partir des moteurs de recherche à l'aide de l'API SERP Scraping. Améliorez vos analyses de marché, votre référencement et vos recherches thématiques en toute simplicité. Commencez dès aujourd'hui !

WebscrapingAPI
avatar de l'auteur
WebscrapingAPI
7 minutes de lecture
vignette
GuidesComment récupérer les données des produits Amazon : Un guide complet des meilleures pratiques et des outils

Explorez les complexités du scraping des données de produits Amazon avec notre guide approfondi. Des meilleures pratiques aux outils tels que l'API Amazon Scraper, en passant par les considérations juridiques, apprenez à relever les défis, à contourner les CAPTCHA et à extraire efficacement des informations précieuses.

Suciu Dan
avatar de l'auteur
Suciu Dan
15 minutes de lecture
vignette
GuidesApprendre à contourner la détection de Cloudflare avec le meilleur navigateur Selenium

Apprenez quel est le meilleur navigateur pour contourner les systèmes de détection de Cloudflare lorsque vous faites du web scraping avec Selenium.

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