DEV Community

Cover image for Du Tableau Web au DataFrame Pandas en 30 Secondes
circobit
circobit

Posted on

Du Tableau Web au DataFrame Pandas en 30 Secondes

Vous avez trouvé le dataset parfait sur un site web. Maintenant vous en avez besoin dans Pandas.

L'approche traditionnelle :

import pandas as pd

# En espérant que la structure du site soit simple
tables = pd.read_html('https://example.com/data')

# Deviner quel tableau vous voulez
df = tables[0]  # Peut-être ? Voyons voir...

# Découvrir les problèmes
print(df.dtypes)
# Tout est 'object' (string)
# Les nombres ont des virgules
# Les dates sont illisibles
# Les noms de colonnes ont des espaces

# Passer 30 minutes à nettoyer...
Enter fullscreen mode Exit fullscreen mode

Laissez-moi vous montrer un moyen plus rapide.

Le Problème avec pd.read_html()

La fonction read_html() de Pandas est pratique mais limitée :

  1. Pas de sélection de tableau — Elle récupère tous les tableaux. Vous devinez quel index vous intéresse.

  2. Pas de nettoyage — Les nombres comme « 1 234 567 » restent en chaînes de caractères.

  3. Problèmes CORS — Beaucoup de sites bloquent l'accès programmatique.

  4. Rendu JavaScript — Les tableaux dynamiques n'existent pas dans le HTML brut.

  5. Authentification — Impossible d'accéder au contenu derrière une connexion.

Pour des scripts rapides, ça fonctionne. Pour de vraies analyses, il faut mieux.

Le Workflow de 30 Secondes

Voici ce que je fais vraiment :

Étape 1 : Exporter depuis le navigateur (5 secondes)

Avec HTML Table Exporter :

  1. Je clique sur le tableau que je veux
  2. Je clique sur l'icône de l'extension
  3. Je sélectionne le profil « Pour Pandas »
  4. J'exporte en CSV depuis le tableau mis en surbrillance dans l'extension

L'extension voit exactement ce que votre navigateur voit — contenu rendu en JavaScript, pages authentifiées, tout.

Étape 2 : Charger dans Pandas (5 secondes)

import pandas as pd

df = pd.read_csv('export.csv')
print(df.dtypes)
Enter fullscreen mode Exit fullscreen mode

C'est tout. Les données sont déjà propres.

Ce que « Propre » Signifie Vraiment

Quand j'exporte avec le profil « Pour Pandas », l'extension gère :

Normalisation des nombres

Avant : "1.234.567,89" (format européen)
Après :  1234567.89     (float)

Avant : "1 234,56 €"
Après :  1234.56
Enter fullscreen mode Exit fullscreen mode

Le CSV contient des nombres normalisés que Pandas parse correctement :

# Sans nettoyage :
df['chiffre_affaires'].sum()  # TypeError: can only concatenate str

# Avec nettoyage :
df['chiffre_affaires'].sum()  # 4892341.50 ✓
Enter fullscreen mode Exit fullscreen mode

Conversion des booléens

Avant : "Oui", "Non", "O", "N", "Vrai", "Faux"
Après :  true, false
Enter fullscreen mode Exit fullscreen mode
# Le filtre fonctionne immédiatement
utilisateurs_actifs = df[df['est_actif'] == True]
Enter fullscreen mode Exit fullscreen mode

Gestion des valeurs nulles

Avant : "-", "N/A", "n/a", "", "null", "—"
Après :  (vide, parsé comme NaN)
Enter fullscreen mode Exit fullscreen mode
# La détection des null fonctionne
df['champ_optionnel'].isna().sum()  # Comptage correct
Enter fullscreen mode Exit fullscreen mode

En-têtes en snake_case

Avant : "Chiffre d'Affaires (M€)", "Nombre d'Utilisateurs", "Taux de Croissance %"
Après :  chiffre_affaires_m, nombre_utilisateurs, taux_de_croissance
Enter fullscreen mode Exit fullscreen mode
# Accès propre aux colonnes
df['chiffre_affaires_m']  # Au lieu de df["Chiffre d'Affaires (M€)"]
Enter fullscreen mode Exit fullscreen mode

Exemple Réel : Stats Football FBRef

Imaginons que je veux les statistiques des joueurs de Ligue 1 depuis FBRef.

L'Ancienne Méthode

import pandas as pd
import requests
from bs4 import BeautifulSoup

url = 'https://fbref.com/en/comps/13/stats/Ligue-1-Stats'
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')

# Trouver le bon tableau (il y en a beaucoup)
table = soup.find('table', {'id': 'stats_standard'})

# Le parser manuellement parce que les en-têtes sont complexes
# FBRef utilise des en-têtes groupés : "Playing Time" couvre plusieurs colonnes
# Ça casse pd.read_html()

# 45 minutes plus tard...
Enter fullscreen mode Exit fullscreen mode

La Nouvelle Méthode

  1. Ouvrir FBRef dans le navigateur
  2. Cliquer sur l'extension → sélectionner le tableau → exporter avec le profil « Pour Pandas »
  3. Charger :
df = pd.read_csv('fbref_stats.csv')
print(df.columns.tolist())
# ['player', 'nation', 'squad', 'playing_time_mp',
#  'playing_time_starts', 'performance_gls', ...]
Enter fullscreen mode Exit fullscreen mode

Les en-têtes groupés (« Playing Time », « Performance ») sont fusionnés avec les sous-en-têtes automatiquement.

Le Code que Je N'Écris Plus

Voici le code de nettoyage que j'écrivais pour chaque scrape web :

def nettoyer_donnees_web(df):
    """La fonction dont je n'ai plus besoin."""

    # Corriger les colonnes numériques
    for col in df.select_dtypes(include='object'):
        try:
            # Supprimer les symboles monétaires
            cleaned = df[col].str.replace(r'[$€£¥]', '', regex=True)
            # Supprimer les séparateurs de milliers
            cleaned = cleaned.str.replace(',', '')
            # Convertir
            df[col] = pd.to_numeric(cleaned, errors='ignore')
        except:
            pass

    # Corriger les colonnes booléennes
    bool_map = {
        'oui': True, 'non': False,
        'true': True, 'false': False,
        'o': True, 'n': False,
        '1': True, '0': False,
    }
    for col in df.columns:
        if df[col].str.lower().isin(bool_map.keys()).all():
            df[col] = df[col].str.lower().map(bool_map)

    # Corriger les valeurs nulles
    null_values = ['', '-', 'N/A', 'n/a', 'null', 'NULL', '', '']
    df = df.replace(null_values, np.nan)

    # Corriger les noms de colonnes
    df.columns = (df.columns
        .str.lower()
        .str.replace(r'[^a-z0-9]+', '_', regex=True)
        .str.strip('_'))

    return df
Enter fullscreen mode Exit fullscreen mode

Cette fonction tournait sur chaque dataset. Maintenant l'export s'en charge.

Quand Utiliser Quoi

Scénario Meilleure approche
Analyse ponctuelle Export navigateur → CSV → Pandas
Scraping récurrent Script Python avec requests
Sites JavaScript Export navigateur (voit le contenu rendu)
Données authentifiées Export navigateur (utilise votre session)
API disponible Utiliser l'API directement
Tableau statique simple pd.read_html() suffit

Astuce Pro : JSON pour les données complexes

Pour des données imbriquées ou typées, exportez en JSON :

import pandas as pd
import json

with open('export.json') as f:
    data = json.load(f)

df = pd.DataFrame(data)
Enter fullscreen mode Exit fullscreen mode

L'export JSON préserve les types :

  • Les nombres restent des nombres (pas des chaînes)
  • Les booléens restent des booléens
  • Les nulls restent null
print(df.dtypes)
# player         object
# goals          int64   # Déjà numérique !
# is_starter     bool    # Déjà booléen !
# injury_date    object  # Parsable en datetime
Enter fullscreen mode Exit fullscreen mode

Pour en savoir plus sur les exports et formats disponibles, consultez Les 5 Meilleures Extensions Chrome pour Exporter des Tableaux.

Résumé du Workflow

Ancien workflow (30+ minutes) :

  1. Écrire un script de scraping
  2. Gérer les problèmes CORS/auth
  3. Parser du HTML complexe
  4. Nettoyer les nombres
  5. Nettoyer les booléens
  6. Nettoyer les nulls
  7. Corriger les noms de colonnes
  8. Débugger les cas limites
  9. Enfin : analyser

Nouveau workflow (30 secondes) :

  1. Cliquer sur l'extension
  2. Exporter avec un profil de nettoyage
  3. pd.read_csv()
  4. Analyser

Essayez

  1. Installez HTML Table Exporter
  2. Trouvez un tableau que vous voulez analyser
  3. Exportez avec les profils de nettoyage
  4. Chargez dans Pandas

La version gratuite gère les exports de base. PRO ajoute les profils de nettoyage et les exports optimisés pour Pandas.

En savoir plus sur gauchogrid.com/fr/html-table-exporter ou essayez-le sur le Chrome Web Store.


Quel est votre workflow actuel pour récupérer des données web dans Pandas ? Je suis curieux de savoir combien de temps vous passez sur l'étape de nettoyage. Laissez un commentaire ci-dessous.

Top comments (0)