Retour au blog
Guides
Mihai MaximLast updated on May 7, 202612 min read

Web Scraping avec Regex : Un guide pratique

Web Scraping avec Regex : Un guide pratique
En bref : le web scraping avec les expressions régulières est particulièrement efficace lorsque vous avez besoin d'extraire des motifs textuels courts et prévisibles (prix, références, adresses e-mail, dates) à partir d'un code HTML dont vous êtes déjà sûr. Associez le module re avec Beautiful Soup, limitez vos motifs à un nœud analysé plutôt qu’au balisage brut, et évitez d’utiliser les expressions régulières pour l’analyse complète de l’arborescence HTML. Ce guide présente un scraper fonctionnel pour les titres et les prix, les fonctionnalités avancées des expressions régulières, ainsi que les pièges qui font trébucher les scrapers en production.

Introduction

La plupart des scrapers Python finissent par atteindre un stade où les sélecteurs CSS et XPath ne suffisent plus. Vous disposez du bon <div>, mais à l'intérieur se trouve une chaîne de caractères telle que "$1,299.00 USD (incl. VAT)" et vous n'avez besoin que du nombre. C'est là que le scraping web avec les expressions régulières prend tout son sens : il s'agit d'une technique d'extraction de texte basée sur des modèles qui cible des formes spécifiques au sein du code HTML brut ou du texte visible derrière une page, au lieu de naviguer dans l'arborescence DOM.

Ce guide s'adresse aux développeurs Python de niveau intermédiaire qui savent déjà comment récupérer une page avec requests et l'analyser avec Beautiful Soup, et qui souhaitent désormais intégrer les expressions régulières à cette boîte à outils sans fragiliser le scraper. Nous verrons quand le web scraping avec des expressions régulières est la bonne solution (et quand ce n'est vraiment pas le cas), une fiche de référence des tokens axée sur le scraping, un scraper de titres et de prix fonctionnel qui génère des fichiers CSV structurés, ainsi que les fonctionnalités avancées re (groupes nommés, lookarounds, drapeaux, re.compile) qui permettent de conserver la lisibilité des modèles à mesure que le projet évolue. Nous aborderons également en toute honnêteté les limites des expressions régulières face au HTML dynamique et mal formé, et les cas où il vaut mieux recourir à des sélecteurs ou à une API de scraping gérée.

Quand les expressions régulières sont-elles le bon outil pour le scraping (et quand ne le sont-elles pas)

Les expressions régulières sont excellentes pour les motifs textuels courts et bien définis : prix, dates, numéros ISBN, numéros de téléphone, hachages, paramètres de requête dans les URL. Elles constituent un mauvais choix pour parcourir des arborescences HTML arbitraires comportant des balises imbriquées, des attributs facultatifs et des espaces incohérents.

Une grille de décision simple pour le scraping web avec les expressions régulières :

  • Optez pour les expressions régulières lorsque le champ a une structure stable (\d+\.\d{2}, un e-mail, un UUID), que la page est du HTML rendu par le serveur et que vous pouvez déjà isoler le nœud environnant à l'aide d'un parseur.
  • Évitez les expressions régulières lorsque les données sont enfouies dans des balises profondément imbriquées, que le balisage change de nom de classe à chaque déploiement, ou que la page est générée par JavaScript et que les valeurs souhaitées n'apparaissent qu'après l'exécution des scripts par le navigateur.

Aide-mémoire des tokens d'expressions régulières pour le scraping

Vous n'avez besoin que d'un petit ensemble de tokens pour presque toutes les tâches de scraping web avec les expressions régulières. Le tableau ci-dessous est axé sur le scraping : chaque exemple correspond à quelque chose que vous pourriez réellement extraire du code HTML.

Token

Ce qu'il correspond

Exemple de scraping

\d

Tout chiffre (0–9)

\d+ pour un prix tel que 1299

\w

Caractère de mot (lettres, chiffres, _)

\w+ pour un slug ou une référence

\s

Tout espace

Tolérance à la mise en forme HTML irrégulière

.

Tout caractère sauf le retour à la ligne

(.*?) à l'intérieur d'une balise, avec re.DOTALL pour les lignes multiples

^ / $

Début / fin de chaîne (ou de ligne)

Ancrage d'un nœud de texte propre

* + ?

0+, 1+, 0–1 occurrences (glouton)

\s* entre les balises

*? +?

Variantes non gloutonnes

(.*?)</h2> pour s'arrêter à la première balise de fermeture

[...]

Classe de caractères

[A-Z]{2,3} pour un code de devise

(...)

Groupe de capture

Extraire uniquement le prix de "$1,299.00 USD"

(?P<name>...)

Capture nommée

(?P<price>\d+\.\d{2})

(?=...) / (?<=...)

Regard en avant / regard en arrière

\d+(?= USD) pour faire correspondre les chiffres avant USD

\\

Échappement

Faire correspondre un littéral . ou $ en HTML

Pour tout ce qui va au-delà, référez-vous à la documentation du module Python re et au guide officiel sur les expressions régulières plutôt que de copier-coller des informations provenant de blogs au hasard.

Étape par étape : extraire les titres et les prix des produits avec Python

Pour illustrer cela, nous allons extraire une page statique de liste de produits et récupérer deux champs : le titre du produit et le prix. Choisissez n'importe quel environnement de test ou boutique de démonstration que vous êtes autorisé à extraire ; le modèle ci-dessous suppose un code HTML généré par le serveur avec une fiche par produit. Les quatre sous-étapes couvrent la configuration de l'environnement, la récupération et l'isolation des fiches, l'écriture des modèles et l'enregistrement de la sortie structurée.

Configurer Python, requests et Beautiful Soup

Un environnement virtuel propre permet de contenir les dépendances et de garder un historique de shell clair. Le module re est fourni avec la bibliothèque standard ; les seules installations tierces nécessaires sont donc le client HTTP et le parseur. Si vous évaluez différents outils de récupération, notre tour d’horizon des clients HTTP Python constitue une bonne lecture complémentaire.

python -m venv .venv
source .venv/bin/activate     # Windows: .venv\Scripts\activate
pip install requests beautifulsoup4
import csv
import re
import requests
from bs4 import BeautifulSoup

Récupérez la page et isolez les fiches produits

Restreignez toujours le champ d'application avant d'utiliser une expression régulière. Appliquer des modèles à l'ensemble d'un document HTML, c'est le meilleur moyen de faire correspondre par erreur la mauvaise balise deux mille lignes plus bas. Utilisez Beautiful Soup pour extraire les fiches produits, puis traitez le code HTML de chaque fiche de manière isolée. Si requests.get renvoie une <body> et que les données se trouvent dans une <script> ou ne se chargent qu’après l’exécution du JS, l’expression régulière sur la réponse brute ne vous sera d’aucune utilité ; vous aurez besoin d’un navigateur sans interface graphique ou d’une API de rendu.

URL = "https://example.com/products"  # replace with a target you are allowed to scrape
html = requests.get(URL, timeout=15).text
soup = BeautifulSoup(html, "html.parser")
cards = soup.find_all("div", attrs={"data-testid": "product-card"})

Écrivez des expressions régulières pour les titres et les prix

Ancrer vos expressions à des attributs stables, et non à des noms de classes CSS hachés comme css-7u5e79. Ces hachages de classe sont régénérés à chaque déploiement front-end et votre scraper cessera de fonctionner sans avertissement. Préférez les data-* les attributs, les balises sémantiques (<h4>, <h2>) ou le balisage itemprop balises lorsque le site les expose.

TITLE_RE = re.compile(r'<h4[^>]*itemprop="name"[^>]*>(.*?)</h4>', re.DOTALL)
PRICE_RE = re.compile(r'<span[^>]*itemprop="price"[^>]*>\s*\$?([\d,]+\.\d{2})\s*</span>')

Trois points à noter lorsque vous utilisez le scraping web par expressions régulières à ce niveau :

  • (.*?) n'est pas glouton ; sans le ? votre correspondance de titre s'étendrait sans problème sur plusieurs cartes.
  • [^>]* permet à la balise d'avoir d'autres attributs (class, id, des hooks d'analyse) sans interrompre la correspondance.
  • re.DOTALL permet à . de faire correspondre les sauts de ligne afin qu'un titre qui passe à la ligne suivante soit tout de même capturé.

Parcourez les résultats et enregistrez-les dans un fichier structuré

Les dumps en texte brut conviennent pour le débogage, mais vous aurez presque toujours besoin de CSV ou de JSON pour le travail en aval. Le CSV avec des en-têtes explicites rend la sortie auto-documentée et facile à charger dans pandas ou un tableur. Conservez le HTML brut, le CSV parsemé et les journaux d'exécution dans des dossiers séparés afin que les nouvelles exécutions ne s'écrasent pas mutuellement.

rows = []
for card in cards:
    html_chunk = str(card)
    t = TITLE_RE.search(html_chunk)
    p = PRICE_RE.search(html_chunk)
    rows.append({
        "title": t.group(1).strip() if t else "",
        "price_usd": p.group(1) if p else "",
    })

with open("data/products.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["title", "price_usd"])
    writer.writeheader()
    writer.writerows(rows)

Pour les champs imbriqués (variantes, spécifications), passez au format JSON.

Associez les expressions régulières à Beautiful Soup pour une extraction plus propre

Les expressions régulières et un véritable parseur HTML ne sont pas concurrents ; ce sont des couches. Beautiful Soup parcourt l'arborescence et vous fournit une chaîne ciblée, et l'utilisation d'expressions régulières avec Beautiful Soup transforme cette chaîne en le champ exact que vous souhaitez. C'est beaucoup plus sûr que d'effectuer un web scraping avec des expressions régulières sur la réponse brute.

Deux modèles à retenir. Premièrement, transmettez une expression régulière compilée directement à find_all ou find pour filtrer les balises par valeur d'attribut :

price_tags = soup.find_all("span", class_=re.compile(r"^price"))

Deuxièmement, recherchez les éléments dont le texte visible correspond à un modèle :

in_stock = soup.find_all(string=re.compile(r"\bIn stock\b", re.IGNORECASE))

Si vous souhaitez approfondir vos connaissances sur le parseur, notre guide pratique de Beautiful Soup couvre les sélecteurs, la navigation et les cas limites.

Modèles d'expressions régulières avancés que les développeurs de scrapers devraient connaître

Une fois les bases acquises, quelques re fonctionnalités rendent le scraping web avec les expressions régulières beaucoup plus facile à maintenir.

  • Les groupes nommés ((?P<name>...)) remplacent l'indexation positionnelle, qui est fragile. m.group("price") est auto-documenté et résiste au réordonnancement des motifs.
  • Les regardants vers l'avant et vers l'arrière vous permettent d'effectuer des correspondances sans consommer. \d+(?= USD) ne capture un nombre que si USD le suit ; (?<=Price:\s)\$\d+ capture $199 uniquement après l'étiquette littérale.
  • Les indicateurs permettent de raccourcir les motifs. re.IGNORECASE pour In Stock vs in stock, re.DOTALL so . traverse les sauts de ligne, re.VERBOSE ce qui vous permet d'écrire des motifs sur plusieurs lignes avec des commentaires.
  • re.compile Cela s'avère payant lorsque vous parcourez des milliers de pages : compilez une seule fois, réutilisez dans la boucle et gagnez un gain de vitesse modeste mais réel.
  • re.finditer traite les correspondances de manière paresseuse, ce qui est plus économe en mémoire que findall pour les documents volumineux.
PRICE = re.compile(r"\$(?P<amount>[\d,]+\.\d{2})(?=\s*USD)", re.IGNORECASE)
for m in PRICE.finditer(page_text):
    print(m.group("amount"))

Pièges courants et limites du scraping web avec les expressions régulières

Liste honnête des éléments qui vous feront trébucher :

  • Les noms de classes hachés (css-7u5e79 eag3qlw7) changent à chaque déploiement. Privilégiez plutôt les data-*, itempropou sur des balises sémantiques à la place.
  • Les balises imbriquées font échouer les (.*?) lorsque le code HTML interne contient la même balise que celle que vous essayez de fermer.
  • Un code HTML mal formé (balises non fermées, guillemets mal appariés) rend les expressions régulières instables ; un véritable analyseur syntaxique le tolère.
  • Le contenu généré par JavaScript ne se trouve tout simplement pas dans le corps de la réponse. Les expressions régulières ne peuvent pas faire apparaître des données que le serveur n’a jamais envoyées.
  • Des problèmes d'encodage s'immiscent via &amp;, &#x27;et les guillemets typographiques ; normalisez le texte avant la correspondance.

Lorsque deux de ces problèmes surviennent simultanément, passez à des sélecteurs ou à une API de rendu qui renvoie du code HTML post-JS.

Expressions régulières vs XPath et sélecteurs CSS : lequel choisir

Utilisez les sélecteurs pour la structure, les expressions régulières pour le texte à l'intérieur de cette structure. Les sélecteurs CSS sont concis et rapides pour les recherches basées sur les classes et les balises ; XPath est plus expressif lorsque vous avez besoin d'axes, de positions ou de prédicats textuels. Les expressions régulières interviennent une fois que vous avez le bon nœud et que vous devez analyser sa chaîne de caractères. Notre guide XPath et la comparaison entre XPath et les sélecteurs CSS approfondissent le sujet si vous devez choisir entre les deux.

Points clés

  • Considérez le web scraping avec les expressions régulières comme un outil de précision pour les motifs de texte courts et prévisibles ; conservez la navigation complète dans l'arborescence HTML dans Beautiful Soup ou lxml.
  • Ancrer toujours les modèles à des attributs stables (data-*, itemprop, balises sémantiques), et non à des noms de classes CSS hachés qui changent à chaque déploiement.
  • Combinez find/find_all avec re.compile afin que les modèles s'exécutent sur des nœuds isolés plutôt que sur l'ensemble du corps de la réponse.
  • Utilisez des groupes nommés, des lookaheads re.DOTALL, re.IGNORECASEet re.compile dès que votre scraper dépasse le cadre d'une seule page.
  • Enregistrez le résultat au format CSV (ou JSON pour les données imbriquées), avec des en-têtes explicites et une structure de dossiers claire pour garantir la reproductibilité.

FAQ

Puis-je scraper des pages rendues en JavaScript uniquement avec des expressions régulières ?

Non. Les expressions régulières correspondent à des caractères déjà présents dans la réponse. Si les valeurs dont vous avez besoin sont injectées dans le DOM par du JavaScript côté client, le code HTML brut renvoyé par requests ne les contient tout simplement pas. Vous avez besoin d'un navigateur sans interface graphique (Playwright, Puppeteer, Selenium) ou d'une API de rendu qui renvoie le code HTML post-JS ; vous pourrez alors appliquer des expressions régulières à ce résultat.

Comment tester des modèles d'expressions régulières avant de les mettre en production ?

Utilisez un testeur interactif tel que regex101 ou pythex pour valider les modèles par rapport à des extraits HTML représentatifs, en sélectionnant la variante Python. Ajoutez ensuite de petits tests unitaires qui exécutent chaque modèle sur un fichier de fixture enregistré et vérifient les groupes capturés. Les fixtures vous protègent lorsque le site change, car un test échoué indique le modèle exact qui a posé problème.

Dois-je utiliser re.compile() lorsque je scrape un grand nombre de pages ?

Oui. re.compile() Cette fonction analyse le motif une seule fois et réutilise l'objet compilé à chaque appel, ce qui évite les coûts d'analyse répétés à l'intérieur des boucles intensives. Le gain de performance sur une seule correspondance est faible, mais il s'accumule sur des milliers de pages. Le principal avantage réside dans la lisibilité : les motifs compilés peuvent être placés au niveau supérieur du module avec des noms clairs, au lieu d'être des littéraux de chaîne en ligne.

Quelle est la différence entre la correspondance gloutonne et non gloutonne lors du scraping de HTML ?

Les quantificateurs gloutons (*, +) font correspondre autant de texte que possible, ce qui peut englober du contenu sur plusieurs enregistrements. Les variantes non gourmandes (*?, +?) ne font correspondre qu'un minimum de texte, s'arrêtant à la première fermeture valide. Pour l'extraction HTML, (.*?)</h4> capture correctement un titre ; (.*)</h4> engloutirait l'intégralité du document jusqu'à la dernière </h4>.

Comment gérer les correspondances multilignes et les espaces inhabituels dans le code HTML extrait ?

Passez re.DOTALL so . correspond aux sauts de ligne, et re.MULTILINE si vous ancrez avec ^ ou $ par ligne. Pour les espaces irréguliers à l'intérieur des balises, utilisez \s* (zéro ou plusieurs espaces, y compris les sauts de ligne) entre les tokens attendus plutôt que des espaces littéraux. Normalisez les entités (&amp;, &nbsp;) et les guillemets Unicode avant la correspondance afin qu'ils ne cassent pas silencieusement des motifs par ailleurs corrects.

Conclusion et prochaines étapes

Le web scraping avec les expressions régulières est un outil puissant, mais pas universel. Utilisez-le là où il fait ses preuves : disséquer des chaînes courtes et prévisibles à l'intérieur du code HTML que vous avez déjà isolé à l'aide d'un parseur. Ancrez vos modèles sur des attributs stables, privilégiez les groupes nommés et les modèles compilés, et passez aux sélecteurs ou à une couche de rendu dès que la page devient trop lourde en JavaScript ou que le balisage s'imbrique. La plupart des scrapers de production finissent par utiliser conjointement les expressions régulières, Beautiful Soup et des clients HTTP ; choisissez la couche qui correspond au champ que vous extrayez et arrêtez-vous là.

Si vous préférez ne pas avoir à vous occuper des proxys, des tentatives de reconnexion et des CAPTCHA pendant que vous vous concentrez sur les modèles, la WebScrapingAPI de notre équipe renvoie du code HTML rendu et du JSON structuré via un point de terminaison unique, de sorte que votre re code Python et Beautiful Soup continue de fonctionner pendant que la couche de requêtes est gérée pour vous. À partir de là, la lecture suivante tout indiquée est notre guide plus complet sur le web scraping en Python et le guide de traitement des données pour transformer les champs extraits en enregistrements propres.

À propos de l'auteur
Mihai Maxim, Développeur Full Stack @ WebScrapingAPI
Mihai MaximDéveloppeur Full Stack

Mihai Maxim est développeur Full Stack chez WebScrapingAPI ; il participe à l'ensemble du produit et contribue à la création d'outils et de fonctionnalités fiables pour la plateforme.

Commencez à créer

Prêt à faire évoluer votre système de collecte de données ?

Rejoignez plus de 2 000 entreprises qui utilisent WebScrapingAPI pour extraire des données Web à l'échelle de l'entreprise, sans aucun coût d'infrastructure.