Que signifie « navigateur sans interface graphique Python » ?
De manière générale, un navigateur est un programme informatique qui permet aux utilisateurs de naviguer et d’interagir avec une page web. Un navigateur sans interface graphique est exactement cela, mais sans interface utilisateur graphique. Cela signifie qu’un navigateur sans interface graphique Python est un programme capable de :
- Naviguer vers n'importe quel site web sur Internet
- Afficher les fichiers JavaScript fournis par le site web
- Interagir avec les composants de cette page web
Le fait qu'il n'y ait pas d'interface graphique (GUI) associée soulève certaines questions concernant l'interaction. Pourtant, la réponse est assez simple. Comme il n'y a pas d'interface graphique, les utilisateurs ne peuvent pas interagir directement avec la page. C'est là que les pilotes Web entrent en jeu. Un pilote Web est une interface qui permet l'introspection et le contrôle. En termes simples, les pilotes Web sont des frameworks qui nous permettent de contrôler par programmation divers navigateurs Web.
Il existe plusieurs frameworks permettant l'automatisation des navigateurs en Python. Mais le principal est Selenium. Selenium est une suite d'outils principalement conçue pour les tests automatisés. Mais dans la pratique, elle est également largement utilisée pour le web scraping.
Pourquoi utiliser un navigateur sans interface graphique en Python ?
Selon l'en-tête de la page d'accueil de Selenium :
« Selenium automatise les navigateurs. C'est tout ! Ce que vous faites de cette puissance ne dépend que de vous. »
Cela nous amène à penser que les navigateurs automatisés ont divers cas d’utilisation. Mais pourquoi les exécuter en mode sans interface graphique ? Eh bien, la réponse est une fois de plus simple. Un navigateur Python sans interface graphique utilise moins de ressources (CPU et mémoire) qu’un navigateur avec interface graphique. Et cela s’explique principalement par l’absence d’éléments graphiques à afficher.
Une fois encore, « moins » reste « plus » par rapport à un client HTTP basique comme `requests` de Python, par exemple. Et cela s’explique par le fait que le navigateur sans interface graphique ouvre tout de même de nombreux processus afin d’interagir avec la page et de rendre les fichiers JavaScript. Comme vous le savez, `requests` est incapable de rendre du JavaScript. Vous ne pouvez récupérer que du HTML brut en l’utilisant. Et de nos jours, cela est loin d’être suffisant pour le web scraping. La plupart des plateformes web modernes s’appuient fortement sur JavaScript pour alimenter le DOM. Par exemple, si vous essayez d’utiliser `curl` sur une application React, vous obtiendrez une page web vide vous demandant d’« activer JavaScript » :
<!doctype html>
<html lang="en">
<head>
...
</head>
<body>
<noscript> You need to enable JavaScript to run this app. </noscript>
<div id="root"></div>
</body>
</html>
Bien que vous ne puissiez pas le faire avec `requests`, vous pouvez y parvenir avec un navigateur sans interface graphique. Cela répond à l’une de nos questions initiales. Les scrapers web modernes utilisent des navigateurs sans interface graphique plutôt que `requests`, car sinon, la réponse serait incomplète.
Quels sont les inconvénients d’un navigateur sans interface graphique ?
Le principal inconvénient d’un navigateur sans interface graphique Python (et de la plupart des navigateurs automatisés) est son empreinte digitale. Si vous suivez mes articles, vous savez que je parle parfois de furtivité. Il s’agit de la capacité d’un navigateur automatisé à passer inaperçu.
Et en Python, les navigateurs sans interface utilisateur sont facilement identifiables. Pour commencer, vérifier une simple propriété du navigateur telle que `navigator.webdriver` permet de savoir instantanément si un navigateur est contrôlé par un pilote Web. En web scraping, l’un des principaux défis consiste à trouver des moyens d’éviter la détection. Nous appelons cela des méthodes ou techniques d’évasion. Vous pouvez en savoir plus à ce sujet ici.
Chez Web Scraping API, par exemple, nous avons une équipe dédiée qui travaille en permanence sur notre mode furtif. Cela permet de garantir que l'empreinte digitale de notre navigateur est unique et indétectable à chaque requête.
Navigateurs sans interface utilisateur disponibles avec Python Selenium
Tout d'abord, sachez que Selenium est très puissant. Et il ne se limite même pas à Python. Il existe des clients Selenium et des pilotes Web pour C#, Ruby, Java, Python et même JavaScript. Et la prise en charge des pilotes Web Selenium est encore plus impressionnante. Elle couvre tous les principaux navigateurs :
Dans le domaine du web scraping, les navigateurs sans interface utilisateur Python les plus utilisés sont Chrome et Firefox. Je pense que cela s'explique principalement par le fait que ces deux navigateurs sont à la fois performants et multiplateformes. Vous pouvez par exemple développer votre projet de web scraping dans un environnement MacOS, puis le déployer facilement sous Linux.
Comment ouvrir un navigateur sans interface graphique en Python
Maintenant que nous avons abordé quelques concepts théoriques, je pense que nous pouvons passer sans crainte à la partie pratique. Dans cette section, je vais vous montrer comment créer un scraper web avec Selenium. Pour ce projet, assurez-vous que votre machine est équipée de Python et de Chrome.
#1 : Configurer l'environnement
Comme d'habitude, en Python, nous devons encapsuler tout cela dans un environnement virtuel. Si vous n'êtes pas familier avec les environnements virtuels, lisez d'abord ceci. Ouvrons maintenant une nouvelle fenêtre de terminal et nous allons :
- Créer un nouveau dossier
- Accéder au dossier
- Créer un nouvel environnement virtuel
- Activer l'environnement virtuel
~ mkdir headless_scraper
~ cd headless_scraper
~ python3 -m venv env
~ source env/bin/activate
#2 : Installer les dépendances
Il est évident que nous avons besoin de Selenium et d’un pilote Web pour notre projet. Heureusement, nous pouvons installer les deux à l’aide du gestionnaire de paquets de Python, `pip`. Dans la même fenêtre de terminal, tapez la commande suivante :
~ pip install selenium webdriver-manager
Vous êtes désormais prêt à vous lancer ! Nous pouvons passer au codage proprement dit. Petite mise en garde : cet article se concentre sur l'interaction avec un navigateur sans interface graphique. Une solution complète de web scraping nécessite beaucoup plus d'efforts. Mais je suis sûr que si vous suivez nos articles de blog, vous y parviendrez en un rien de temps.
#3 : Ouvrir un navigateur automatisé
Jusqu'à présent, nous avons le projet, mais aucun fichier à exécuter. Créons un nouveau fichier `.py` et ouvrons-le dans notre IDE :
~ touch headles_scraper.py
~ code .
Vous devriez maintenant être dans Visual Studio Code ou votre IDE. Vous pouvez commencer par importer les paquets nécessaires dans `handle_scraper.py` :
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
Ce dernier est un paquet qui vous aide à gérer facilement les pilotes Web pour les différents navigateurs pris en charge par Selenium. Vous pouvez en savoir plus à ce sujet ici. Ensuite, nous voulons créer un nouveau navigateur avec Selenium et ouvrir un site Web :
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('https://webscrapingapi.com')
Exécutez ce fichier maintenant et vous verrez qu'il fonctionne. Mais au lieu d'utiliser un navigateur Python sans interface graphique, il ouvre une fenêtre Chrome avec interface graphique :
#4 : Passer en mode sans interface graphique
Nous avons prévu de créer un scraper web économe en ressources. Idéalement, nous voulons donc ouvrir un navigateur sans interface graphique avec Selenium. Heureusement, il existe une méthode simple pour faire passer Selenium du mode avec interface graphique au mode sans interface graphique. Il suffit d'utiliser les options du pilote web Chrome. Importons donc `Options` et ajoutons deux lignes de code supplémentaires :
...
from selenium.webdriver.chrome.options import Options
...
options = Options()
options.headless = True
driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
driver.get('https://webscrapingapi.com')
Relancez votre script. Comme vous pouvez le constater, aucune fenêtre ne s'ouvre cette fois-ci. Mais fonctionne-t-il vraiment en arrière-plan ? Un moyen rapide de le visualiser et de le vérifier consiste à prendre une capture d'écran à l'aide de Selenium. Il suffit d'ajouter cette ligne à la fin de votre script :
driver.get_screenshot_as_file('headless.png')
Si tout s'est bien passé, vous devriez obtenir la même image que moi :
#5 : Ajouter des capacités de scraping
Qu'est-ce qu'un web scraper ? Eh bien, à la base, un web scraper est un programme qui appelle un point de terminaison sur un serveur et y collecte des données. Avec les sites web, ces données se composent généralement de fichiers HTML. Mais certains serveurs fournissent aujourd'hui également des objets JSON. Restons donc sur ce terme : données. Pour la section suivante, visons plus haut. Utilisons la programmation orientée objet ! Nos objectifs sont les suivants :
- Créer une classe Scraper
- Ajouter une méthode pour extraire les données brutes
- Ajouter une méthode pour extraire des données d'un élément unique
- Ajouter une méthode pour extraire des données à partir d'éléments de la même classe
Nous avons donc trois méthodes de base à créer. Mais à des fins d’apprentissage, ces trois méthodes ouvrent la voie non seulement au web scraping, mais aussi à la POO avec Python. Et je trouve ça plutôt cool ! Supprimons maintenant tout ce que nous avons codé et repartons de zéro :
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webelement import WebElement
class Scraper:
def __init__(self, headless: bool = True) -> None:
self.headless = headless
pass
def setup_scraper(self) -> None:
self.options = Options()
self.options.headless = self.headless
self.driver = webdriver.Chrome(options=self.options)
def navigate(self, target) -> None:
self.driver.get(target) if target else print('[!] No target given. Please specify a URL.')
def extract_raw_data(self) -> str:
return self.driver.page_source
def extract_single_element(self, selector: str, selector_type: By = By.CSS_SELECTOR) -> WebElement:
return self.driver.find_element(selector_type, selector)
def extract_all_elements(self, selector: str, selector_type: By = By.CSS_SELECTOR) -> list[WebElement]:
return self.driver.find_elements(selector_type, selector)
J'ai ajouté des annotations de type pour faciliter la compréhension, plutôt que pour améliorer les performances. De cette façon, vous pouvez réellement visualiser l'application d'un point de vue E/S. À présent, les méthodes sont assez explicites. Nous n'effectuons aucune action sur les données, nous nous contentons de les renvoyer. Si vous le souhaitez, cela peut constituer un point de départ pour créer un scraper complexe avec un navigateur Python sans interface graphique.
Pour l'instant, l'exécution du fichier ne fait rien. C'est parce que nous avons seulement déclaré notre Scraper et ses méthodes. Nous devons maintenant les utiliser. Ajoutons donc les lignes de code suivantes :
# Initialize a new Scraper and navigate to a target
scraper = Scraper()
scraper.setup_scraper()
scraper.navigate('https://httpbin.org')
# Extract and print the entire HTML document
raw_data = scraper.extract_raw_data()
print(raw_data)
# Extract and print an element by its class name
single_element = scraper.extract_single_element('title', By.CLASS_NAME)
print(single_element.text)
# Extract and print all elements belonging to a tag type
all_elements = scraper.extract_all_elements('a', By.TAG_NAME)
print([el.get_attribute('href') for el in all_elements])
Et voilà. Si vous exécutez votre script maintenant, vous verrez que quelque chose se passe. Encore une fois, il s'agit simplement d'un prototype conçu pour vous aider à démarrer. Si vous souhaitez en savoir plus sur la manière dont un navigateur Python sans interface graphique peut être utilisé pour le web scraping, je vous mets au défi de :
- Lire la documentation Selenium
- Ajouter des fonctionnalités supplémentaires au script que nous avons créé aujourd’hui
De cette façon, vous acquerrez des connaissances et ajouterez un projet à votre portfolio.
Quelles sont les meilleures alternatives aux navigateurs headless Python ?
Python est l'un des langages de programmation les plus populaires pour créer des scrapers web. Pourtant, ce n'est pas la seule solution. Ce n'est pas non plus la meilleure ! Dans cette section, nous aborderons les alternatives au navigateur headless Python. Nous commencerons par expliquer pourquoi il est intéressant d'étudier des solutions alternatives, puis nous examinerons des exemples concrets.
La principale raison pour laquelle vous opteriez pour une alternative à la création d’un scraper web Python par vous-même est liée aux ressources. Une solution complète de scraping web nécessite de mettre en place un système de rotation d’IP, certaines techniques d’évasion, de prendre en compte les performances, et ce ne sont là que quelques exemples. La création d’un scraper web est donc non seulement coûteuse, mais aussi chronophage. Sans compter que la maintenance de l’infrastructure engendre encore plus de coûts.
Le deuxième inconvénient du navigateur headless Python concerne les performances. Bien que Python soit un excellent langage et très convivial, il n’est pas particulièrement réputé pour sa rapidité. Contrairement à Java par exemple (qui dispose également d’un package Selenium), Python est à la fois un langage à typage dynamique et interprété. Ces deux caractéristiques le rendent beaucoup plus lent par rapport à d’autres langages. Maintenant que nous avons une compréhension générale, entrons dans les détails. Voici les 5 meilleures alternatives à Selenium et au navigateur headless Python :
N° 1 : API de web scraping
Si vous souhaitez remédier au premier inconvénient que nous avons identifié, vous devez vous tourner vers des fournisseurs de scraping tiers. Et Web Scraping API propose une suite complète de scraping. De plus, notre service regorge de fonctionnalités telles que :
- Système de rotation d'adresses IP pour les proxys de centres de données et résidentiels
- Mode furtif
- Des solveurs de Captcha
À elles seules, ces trois fonctionnalités rendent pratiquement impossible pour une cible de détecter notre scraper et de le bloquer. Et puis il y a les fonctionnalités de scraping. Avec l'API de scraping Web, vous pouvez extraire des données à l'aide de sélecteurs, passer d'un type d'appareil à l'autre, prendre des captures d'écran, et bien plus encore. Vous trouverez la liste complète des fonctionnalités ici.
#2 : Puppeteer
Puppeteer est l'équivalent de Selenium pour JavaScript. C'est l'une des bibliothèques les plus utilisées pour l'automatisation Web. Contrairement à Selenium, Puppeteer est par défaut en mode headless. Vous n'avez donc pas besoin d'ajouter de code supplémentaire pour le rendre headless. Ce qui est encore plus intéressant, c'est qu'il existe également une implémentation de l'API Puppeteer pour Python. Vous pouvez consulter cet article de blog où j'explique en détail comment créer un scraper web avec Puppeteer.
#3 : Playwright
Playwright est un autre outil d'automatisation Web développé par des contributeurs de Microsoft. Il est populaire principalement parce qu'il prend en charge divers langages et plateformes. Sa devise est d'ailleurs « N'importe quel navigateur, n'importe quelle plateforme ». Son API est accessible sur n'importe quel système d'exploitation et avec l'un des langages suivants :
Voici les principales alternatives à un navigateur headless Python. Mais il existe également d'autres outils. ZombieJS ou HtmlUnit ne sont que deux exemples parmi tant d'autres. Je pense que le choix d'une technologie est à la fois une question de performances et de préférence personnelle. Je vous encourage donc à les tester tous et à choisir celui qui vous convient le mieux.
Conclusions
L'utilisation d'un navigateur Python sans interface graphique présente des avantages et des inconvénients. D'un côté, vous pouvez créer une solution personnalisée à laquelle vous pouvez toujours ajouter des fonctionnalités. De l'autre, le développement et la maintenance peuvent s'avérer assez coûteux. Et il y a aussi la question de la discrétion. Si vous avez besoin d'une solution professionnelle, je pense qu'il vaut mieux faire appel à un fournisseur tiers. Sinon, à des fins d'apprentissage, je vous encouragerai toujours à vous familiariser avec cette technologie.




