Web scraping Python : extraire des données web et les analyser avec Pandas, pas à pas
- Thématique
- Data & business intelligence
- Mis à jour
- Lecture
- 12 min
- Formation
- Python Data Science : Du Web Scraping à l'Analyse Pandas
L'essentiel en 30 secondes
- Le web scraping Python consiste à télécharger le code HTML d'une page avec Requests, puis à en extraire les informations utiles avec BeautifulSoup.
- Pandas range ensuite les données collectées dans un DataFrame, une table en mémoire que l'on nettoie, filtre, trie, agrège et exporte vers Excel ou CSV.
- Avant de scraper un site, vérifiez s'il propose une API, lisez ses conditions d'utilisation et son fichier robots.txt, et espacez vos requêtes.
- Les pages dont le contenu est généré en JavaScript nécessitent un navigateur automatisé comme Selenium ou Playwright, car Requests ne récupère que le HTML initial.
- Travailler dans un environnement virtuel (venv) isole les bibliothèques de chaque projet et évite les conflits de versions.
Sommaire de l'article
- Qu’est-ce que le web scraping avec Python ?
- À quoi sert le web scraping en data science ?
- Scraper de façon responsable : les règles à respecter
- Comment faire du web scraping avec Python : les étapes
- Analyser les données avec Pandas
- Astuces et bonnes pratiques de scraping
- Les erreurs fréquentes en web scraping Python
- Quel outil choisir pour extraire des données web ?
- Comment progresser en web scraping et en data science Python ?
- En résumé
Le web scraping Python consiste à écrire un script qui télécharge des pages web et en extrait automatiquement les informations utiles : prix, titres, caractéristiques de produits, annonces, résultats sportifs. Associé à Pandas, il permet ensuite de nettoyer ces données, de les analyser et de les exporter vers Excel, en quelques lignes de code.
Ce guide s’adresse aux débutants en programmation comme aux analystes qui veulent automatiser une collecte d’informations. Vous y verrez comment préparer votre environnement, lire la structure d’une page HTML, écrire un script d’extraction complet, parcourir plusieurs pages, puis manipuler les résultats dans un DataFrame Pandas.
Qu’est-ce que le web scraping avec Python ?
Le web scraping est l’extraction automatisée de données depuis des pages web. En Python, un script envoie une requête HTTP au site (bibliothèque Requests), reçoit le code HTML de la page, l’analyse (bibliothèque BeautifulSoup) pour isoler les éléments voulus, puis enregistre le résultat dans une structure exploitable, le plus souvent un DataFrame Pandas.
Le processus suit toujours quatre temps :
- Télécharger la page (requête HTTP GET).
- Analyser le HTML pour construire un arbre de balises navigable.
- Extraire les éléments ciblés grâce à leurs balises, classes ou attributs.
- Structurer et exporter les données : liste de dictionnaires, DataFrame, puis fichier Excel ou CSV.
Python domine ce domaine pour une raison simple : il réunit dans un même langage la collecte (Requests, BeautifulSoup, Selenium, Scrapy) et l’analyse de données (Pandas, Matplotlib, scikit-learn). On passe de la page web au graphique sans changer d’outil.
À quoi sert le web scraping en data science ?
Les usages professionnels sont nombreux, dès lors qu’une information est publique mais qu’aucun export n’est proposé :
- Veille tarifaire : suivre l’évolution des prix d’un catalogue concurrent.
- Études de marché : recenser des offres, des annonces ou des caractéristiques de produits.
- Constitution de jeux de données : alimenter une analyse statistique ou un modèle de machine learning.
- Suivi de contenus : repérer les nouveautés d’une page de publications ou d’un site institutionnel.
- Consolidation : rassembler dans un tableau unique des informations dispersées sur des dizaines de pages.
Avant de coder, posez-vous une question : le site propose-t-il une API ou un export ? Une API renvoie des données déjà structurées (souvent en JSON), plus fiables et plus stables qu’un scraping qui cassera à la prochaine refonte du site.
Scraper de façon responsable : les règles à respecter
Le scraping touche aux droits des sites et, parfois, aux données personnelles. Quelques règles s’imposent :
- Lisez les conditions d’utilisation du site : certaines interdisent explicitement la collecte automatisée.
- Consultez le fichier robots.txt (à la racine du domaine, par exemple
/robots.txt) : il indique les zones que le site ne souhaite pas voir parcourues par des robots. - Espacez vos requêtes avec une pause entre chaque page, et ne lancez pas des centaines de requêtes simultanées.
- Identifiez-vous avec un en-tête User-Agent explicite plutôt que de vous faire passer pour un autre service.
- Ne contournez jamais une authentification, un paywall ou une protection anti-robot.
- Données personnelles : noms, e-mails, téléphones sont soumis au RGPD, même s’ils sont publiés en ligne.
Pour vous entraîner sans risque, utilisez des sites conçus pour cela, comme books.toscrape.com, un faux catalogue de livres créé spécialement pour apprendre le scraping. C’est lui que nous utilisons dans les exemples ci-dessous.
Comment faire du web scraping avec Python : les étapes
Étape 1 — Installer Python et créer un environnement virtuel
Installez la dernière version stable de Python depuis le site officiel python.org. Sous Windows, cochez l’option Add python.exe to PATH pendant l’installation.
Créez ensuite un dossier de projet et un environnement virtuel, qui isole les bibliothèques de ce projet :
mkdir scraping-livres
cd scraping-livres
python -m venv .venv
# Activation sous Windows
.venv\Scripts\activate
# Activation sous macOS / Linux
source .venv/bin/activate
pip install requests beautifulsoup4 pandas openpyxl jupyter
Dans Visual Studio Code, installez l’extension Python, ouvrez le dossier, puis choisissez l’interpréteur de l’environnement virtuel avec Ctrl+Maj+P > Python: Select Interpreter.
Étape 2 — Tester une première requête
Commencez par vérifier que Python communique bien avec le web. Sur une API de test, la réponse arrive directement en JSON :
import requests
reponse = requests.get("https://jsonplaceholder.typicode.com/users", timeout=10)
print(reponse.status_code) # 200 si tout va bien
utilisateurs = reponse.json() # liste de dictionnaires Python
print(utilisateurs[0]["name"])
Sur une page web classique, la réponse est du HTML : reponse.text contient le code source de la page, que l’on va maintenant analyser.
Étape 3 — Comprendre la structure HTML de la page
Ouvrez la page dans votre navigateur, faites un clic droit sur un élément (le prix d’un livre) puis Inspecter. Les outils de développement affichent la balise correspondante. Sur books.toscrape.com, chaque livre est décrit ainsi :
- un bloc
articlede classeproduct_pod; - le titre complet dans l’attribut
titledu lien situé dans leh3; - le prix dans un paragraphe de classe
price_color; - la note dans un paragraphe de classe
star-rating, suivie d’un mot (OneàFive).
Repérer ce motif répété est la clé : on écrit l’extraction pour un bloc, puis on la répète sur tous.
Étape 4 — Écrire le script d’extraction
import requests
from bs4 import BeautifulSoup
URL = "https://books.toscrape.com/catalogue/page-1.html"
EN_TETES = {"User-Agent": "Mozilla/5.0 (projet de formation Python)"}
reponse = requests.get(URL, headers=EN_TETES, timeout=10)
reponse.raise_for_status() # stoppe le script en cas d'erreur HTTP
reponse.encoding = "utf-8" # évite les caractères mal décodés
soup = BeautifulSoup(reponse.text, "html.parser")
livres = []
for bloc in soup.select("article.product_pod"):
livres.append({
"titre": bloc.h3.a["title"],
"prix": bloc.select_one("p.price_color").get_text(strip=True),
"note": bloc.select_one("p.star-rating")["class"][1],
})
print(len(livres), "livres extraits")
print(livres[0])
Les deux méthodes essentielles de BeautifulSoup sont select(), qui renvoie tous les éléments correspondant à un sélecteur CSS, et select_one(), qui renvoie le premier. get_text(strip=True) récupère le texte sans espaces superflus, et la notation element["attribut"] lit la valeur d’un attribut.
Étape 5 — Automatiser le scraping sur plusieurs pages
Le catalogue est réparti sur plusieurs pages numérotées. On transforme le code en fonction, puis on boucle sur les numéros de page, avec une pause entre chaque requête :
import time
import requests
from bs4 import BeautifulSoup
EN_TETES = {"User-Agent": "Mozilla/5.0 (projet de formation Python)"}
session = requests.Session()
def extraire_page(numero):
url = f"https://books.toscrape.com/catalogue/page-{numero}.html"
reponse = session.get(url, headers=EN_TETES, timeout=10)
if reponse.status_code == 404:
return None # plus de page : on s'arrête
reponse.raise_for_status()
reponse.encoding = "utf-8"
soup = BeautifulSoup(reponse.text, "html.parser")
resultats = []
for bloc in soup.select("article.product_pod"):
resultats.append({
"titre": bloc.h3.a["title"],
"prix": bloc.select_one("p.price_color").get_text(strip=True),
"note": bloc.select_one("p.star-rating")["class"][1],
"page": numero,
})
return resultats
tous_les_livres = []
numero = 1
while True:
page = extraire_page(numero)
if not page:
break
tous_les_livres.extend(page)
numero += 1
time.sleep(1) # une seconde entre deux pages
print(len(tous_les_livres), "livres au total")
Cette version a trois qualités : elle s’arrête d’elle-même quand il n’y a plus de page, elle réutilise la connexion grâce à requests.Session(), et elle ménage le serveur avec time.sleep(). C’est le type de refactoring qui rend un script maintenable : une fonction par tâche, des constantes en haut, aucune valeur répétée.
Étape 6 — Charger les résultats dans un DataFrame Pandas
import pandas as pd
df = pd.DataFrame(tous_les_livres)
print(df.shape) # (nombre de lignes, nombre de colonnes)
print(df.head()) # 5 premières lignes
df.info() # types et valeurs non nulles par colonne
Une liste de dictionnaires se convertit directement en DataFrame : chaque clé devient une colonne, chaque dictionnaire une ligne.
Étape 7 — Exporter vers Excel ou CSV
df.to_excel("livres.xlsx", index=False) # nécessite openpyxl
df.to_csv("livres.csv", index=False, encoding="utf-8-sig") # accents lisibles dans Excel
Certains tutoriels utilisent la bibliothèque xlwt, qui produit l’ancien format .xls. Elle fonctionne, mais n’est plus maintenue : pour un fichier .xlsx moderne, passez par Pandas et openpyxl.
Analyser les données avec Pandas
Une fois les données dans un DataFrame, Pandas devient votre tableur programmable. Le plus confortable pour explorer est Jupyter Notebook (lancez jupyter notebook dans le terminal, ou ouvrez un fichier .ipynb dans VS Code) : chaque cellule s’exécute séparément et affiche son résultat juste en dessous.
Series et DataFrame : les deux structures de base
Une Series est une colonne de valeurs avec un index ; un DataFrame est un ensemble de Series qui partagent le même index. df["prix"] renvoie une Series, df[["titre", "prix"]] renvoie un DataFrame de deux colonnes.
Nettoyer et typer les colonnes
Les prix extraits sont du texte (« £51.77 ») et les notes des mots (« Three »). Il faut les convertir pour calculer :
df["prix"] = (
df["prix"]
.str.replace("£", "", regex=False)
.astype(float)
)
correspondance = {"One": 1, "Two": 2, "Three": 3, "Four": 4, "Five": 5}
df["note"] = df["note"].map(correspondance)
df = df.drop_duplicates(subset="titre")
print(df.isna().sum()) # valeurs manquantes par colonne
Filtrer, trier et agréger
# Livres à plus de 50 £, du plus cher au moins cher
chers = df[df["prix"] > 50].sort_values("prix", ascending=False)
# Livres bien notés et abordables
bons_plans = df[(df["note"] >= 4) & (df["prix"] < 20)]
# Statistiques par note
synthese = df.groupby("note")["prix"].agg(["count", "mean", "min", "max"]).round(2)
print(synthese)
# Statistiques descriptives globales
print(df["prix"].describe())
Les conditions se combinent avec & (et) et | (ou), chaque condition entre parenthèses. groupby() joue le rôle d’un tableau croisé dynamique : il regroupe les lignes et calcule une agrégation par groupe.
Les opérations Pandas à connaître
| Besoin | Code Pandas | Équivalent Excel |
|---|---|---|
| Aperçu des données | df.head(), df.info() | Parcourir la feuille |
| Sélectionner des colonnes | df[["titre", "prix"]] | Masquer des colonnes |
| Filtrer des lignes | df[df["prix"] > 50] | Filtre automatique |
| Trier | df.sort_values("prix") | Trier de A à Z |
| Créer une colonne | df["prix_ttc"] = df["prix"] * 1.2 | Formule dans une colonne |
| Agréger par groupe | df.groupby("note")["prix"].mean() | Tableau croisé dynamique |
| Joindre deux tables | pd.merge(df1, df2, on="id") | RECHERCHEX |
| Supprimer les doublons | df.drop_duplicates() | Supprimer les doublons |
Astuces et bonnes pratiques de scraping
- Commencez par pandas.read_html : si les données sont déjà dans un tableau HTML,
pd.read_html(url)renvoie directement une liste de DataFrames (bibliothèque lxml requise). - Protégez chaque extraction : si un élément manque sur une fiche,
select_one()renvoieNoneet l’accès à un attribut provoque une erreur. Testez la présence de l’élément avant de lire son contenu. - Enregistrez le HTML brut d’une page pendant le développement pour travailler hors ligne et ne pas solliciter le site à chaque test.
- Journalisez la page en cours et les erreurs rencontrées : sur un long scraping, vous saurez où reprendre.
- Sauvegardez régulièrement les résultats intermédiaires, par exemple toutes les dix pages.
- Surveillez les changements du site : une refonte suffit à casser les sélecteurs. Un script de scraping demande une maintenance régulière.
Repérer l’API cachée d’un site dynamique
Avant de sortir un navigateur automatisé, ouvrez les outils de développement (F12), onglet Réseau, puis filtrez sur Fetch/XHR et rechargez la page. Beaucoup de sites dynamiques chargent leurs données depuis une URL qui renvoie du JSON. Si cette requête est accessible sans authentification et que les conditions du site le permettent, l’interroger directement avec requests.get(...).json() est plus rapide, plus léger et plus stable que d’analyser le HTML affiché.
Visualiser rapidement les résultats
Pandas s’appuie sur Matplotlib pour produire un premier graphique en une ligne, pratique pour vérifier la cohérence des données collectées :
df["prix"].plot(kind="hist", bins=20, title="Répartition des prix")
df.groupby("note")["prix"].mean().plot(kind="bar", title="Prix moyen par note")
Un histogramme montre immédiatement une valeur aberrante (un prix à zéro, un prix multiplié par cent) qui trahit une erreur d’extraction ou de conversion. Pour des analyses statistiques plus poussées, le langage R est une alternative solide à Pandas, très utilisée dans la recherche et les études.
Les erreurs fréquentes en web scraping Python
| Erreur | Cause | Solution |
|---|---|---|
AttributeError: 'NoneType' object has no attribute... | Le sélecteur ne trouve pas l’élément | Vérifier le sélecteur dans l’inspecteur, tester if element: |
| La liste extraite est vide | Contenu généré en JavaScript | Chercher l’API appelée par la page ou utiliser Selenium/Playwright |
| Caractères bizarres (« £ ») | Mauvais encodage détecté | Définir reponse.encoding = "utf-8" |
| Erreur 403 ou 429 | Blocage ou trop de requêtes | Ralentir, respecter les règles du site, ne pas insister |
ModuleNotFoundError | Bibliothèque installée hors de l’environnement virtuel | Activer le venv puis relancer pip install |
| Somme ou moyenne impossible sur une colonne | Valeurs restées en texte | Nettoyer puis convertir avec astype(float) ou pd.to_numeric |
| Fichier CSV illisible dans Excel | Encodage ou séparateur | encoding="utf-8-sig" et, si besoin, sep=";" |
Quel outil choisir pour extraire des données web ?
| Outil | Idéal pour | Limites |
|---|---|---|
| API officielle | Données structurées et stables | N’existe pas toujours, quotas possibles |
pandas.read_html | Tableaux HTML simples | Uniquement les balises de tableau |
| Requests + BeautifulSoup | La majorité des sites statiques | Ne lit pas le contenu généré en JavaScript |
| Selenium ou Playwright | Sites dynamiques, clics, défilement | Plus lent, plus lourd à installer |
| Scrapy | Collectes à grande échelle, nombreux sites | Courbe d’apprentissage plus élevée |
| Power Query (onglet Web) | Récupérer un tableau web sans coder | Peu adapté aux pages complexes et à la pagination |
Si votre objectif est seulement d’importer un tableau web dans un rapport, sans écrire de code, le connecteur Web de Power Query suffit souvent : notre guide Power Query dans Power BI le présente.
Comment progresser en web scraping et en data science Python ?
Voici un parcours réaliste pour devenir autonome :
- Les bases de Python (une à deux semaines) : variables, listes, dictionnaires, boucles, fonctions. Notre guide pour apprendre Python détaille cette étape.
- HTML et sélecteurs CSS (quelques heures) : balises, classes, attributs, inspecteur du navigateur.
- Premier scraper : une page, puis plusieurs pages avec pagination et export.
- Pandas : Series, DataFrames, nettoyage, filtres, groupby, jointures.
- Aller plus loin : sites dynamiques, stockage en base de données, visualisation, puis modèles prédictifs.
Pour être accompagné sur les premières étapes, la formation vidéo Python du web scraping à l’analyse Pandas d’EspritAcadémique dure 3 h 15, ne demande aucun prérequis et suit une démarche 100 % pratique. Elle couvre notamment :
- l’installation de Python, la création d’un environnement virtuel et la configuration de VS Code ;
- le test d’une première API et l’affichage de données brutes ;
- l’analyse du code HTML et l’écriture pas à pas d’un script d’extraction de prix ;
- l’automatisation sur plusieurs pages et l’export des résultats vers Excel ;
- la découverte de Jupyter Notebook et les fondamentaux de Pandas, des Series aux DataFrames.
Une fois vos données collectées, deux prolongements naturels s’offrent à vous : les stocker et les interroger dans une base, avec notre guide pour apprendre SQL, ou les exploiter dans des modèles prédictifs, présentés dans notre article sur le machine learning.
En résumé
Le web scraping avec Python repose sur un enchaînement simple : Requests télécharge la page, BeautifulSoup en extrait les éléments grâce aux sélecteurs CSS, une boucle parcourt les pages avec des pauses, et Pandas transforme le résultat en DataFrame que l’on nettoie, analyse et exporte. Vérifiez toujours l’existence d’une API et les règles du site avant de collecter, et structurez votre code en fonctions pour qu’il reste facile à maintenir.
Questions fréquentes
Le web scraping est-il légal ?
Le scraping n'est pas interdit en soi, mais son usage est encadré. Respectez les conditions d'utilisation du site, ne contournez pas une authentification, ne surchargez pas le serveur et ne réutilisez pas de contenus protégés par le droit d'auteur ou les bases de données. Si vous collectez des données personnelles, le RGPD s'applique. En cas de doute pour un projet commercial, demandez un avis juridique.
Quelle bibliothèque Python utiliser pour le web scraping ?
Pour la plupart des sites, le duo Requests et BeautifulSoup suffit : Requests télécharge la page, BeautifulSoup l'analyse. Pour extraire un simple tableau HTML, pandas.read_html est encore plus rapide. Pour les sites dynamiques en JavaScript, utilisez Selenium ou Playwright. Pour des collectes à grande échelle sur des milliers de pages, le framework Scrapy est plus adapté.
Quelle est la différence entre une Series et un DataFrame dans Pandas ?
Une Series est une colonne unique de valeurs, associée à un index. Un DataFrame est un tableau à deux dimensions composé de plusieurs Series qui partagent le même index, comme une feuille Excel avec des colonnes nommées. Sélectionner une colonne d'un DataFrame, par exemple df["prix"], renvoie une Series.
Faut-il connaître Python avant d'apprendre le web scraping ?
Des bases suffisent : variables, listes, dictionnaires, boucles for et fonctions. Le scraping est d'ailleurs un excellent projet pour apprendre Python, car le résultat est concret et immédiat. Il faut aussi comprendre la structure d'une page HTML, c'est-à-dire les balises, les classes et les attributs, pour savoir quoi cibler.
Comment exporter des données scrapées vers Excel ?
Rangez les données dans un DataFrame Pandas, puis appelez df.to_excel("fichier.xlsx", index=False). Cette méthode nécessite la bibliothèque openpyxl, à installer avec pip. Pour un fichier CSV lisible directement dans Excel avec les accents, utilisez df.to_csv("fichier.csv", index=False, encoding="utf-8-sig").
Pourquoi mon script de scraping ne trouve aucun élément ?
Trois causes dominent. Le contenu est chargé en JavaScript et absent du HTML reçu par Requests. Le sélecteur CSS ne correspond pas exactement à la structure réelle de la page. Ou le site renvoie une page d'erreur ou de blocage. Affichez reponse.status_code et une partie de reponse.text pour vérifier ce que vous avez réellement reçu.