Web scraping avec Excel / VBA

Web scraping avec Excel et VBA : requêtes vers les pages, analyse du HTML et mise à jour automatique des tableaux sans programme externe.

ÉW
Équipe Web-Scraping.fr
Collecte de données pour votre activité
Publié le: 4 mars 2025

Le web scraping est généralement associé à Python ou à des services spécialisés. Mais si les données doivent atterrir directement dans un tableau, être calculées par des formules et présentées aux collègues, Excel associé à VBA reste l'un des moyens les plus rapides d'obtenir un résultat. Pas besoin d'installer un interpréteur, de configurer un environnement ni d'expliquer au comptable ce qu'est pip install. On ouvre le classeur, on clique sur un bouton — les données sont sur la feuille.

Dans cet article, nous verrons comment fonctionne le scraping avec VBA : quels objets utiliser pour les requêtes HTTP, comment analyser le HTML et le JSON, comment placer le résultat dans les cellules et éviter les blocages. Les exemples sont fonctionnels : vous pouvez les copier dans l'éditeur VBA et les exécuter.

Quand Excel / VBA est un bon choix

VBA est pertinent lorsque :

  • le résultat vit de toute façon dans Excel (rapport, tableau de bord, journal de cotations) ;
  • le volume de données est petit ou moyen — des dizaines à des milliers de lignes, pas des millions ;
  • il faut une automatisation « en un clic » pour des personnes sans compétences en programmation ;
  • la source fournit les données via une simple requête HTTP ou une API ouverte.

Si en revanche vous avez besoin d'une vraie montée en charge, de contourner une protection JavaScript complexe ou d'exécuter des requêtes parallèles, mieux vaut regarder du côté de Python (requests, BeautifulSoup, Playwright). Sur ce type de tâches, VBA atteint vite ses limites.

Les outils disponibles dans VBA

Pour le scraping en VBA, il existe plusieurs « moteurs » principaux :

Objet Rôle Quand l'utiliser
MSXML2.XMLHTTP / ServerXMLHTTP Requêtes HTTP Le moyen principal d'obtenir la réponse du serveur
WinHttp.WinHttpRequest.5.1 Requêtes HTTP Alternative avec des timeouts configurables
HTMLDocument (MSHTML) Analyse du HTML Quand il faut extraire des éléments par balises/classes
RegExp (VBScript) Expressions régulières Extraction ciblée dans le texte
Split / InStr / Mid Fonctions de chaînes Analyse simple de JSON et de texte sans bibliothèques
QueryTables / Power Query Tableaux prêts à l'emploi Quand la page fournit un tableau HTML propre

La plupart de ces objets s'instancient « à la volée » via CreateObject, c'est-à-dire sans ajout manuel de références au projet. C'est pratique : le classeur fonctionne sur n'importe quelle machine équipée d'Excel.

Requête HTTP de base

Le scraper le plus simple consiste à récupérer le texte d'une page. Voici une fonction qui exécute une requête GET et renvoie le HTML ou le JSON sous forme de chaîne :

vba
Function GetResponse(ByVal url As String) As String
    Dim http As Object
    Set http = CreateObject("MSXML2.XMLHTTP")

    http.Open "GET", url, False
    ' On se fait passer pour un navigateur classique : beaucoup de sites bloquent les requêtes sans User-Agent
    http.setRequestHeader "User-Agent", _
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
    http.send

    If http.Status = 200 Then
        GetResponse = http.responseText
    Else
        GetResponse = "ERROR: " & http.Status & " " & http.statusText
    End If

    Set http = Nothing
End Function

Le troisième argument de OpenFalse — signifie une requête synchrone : le code attend la réponse. Pour la plupart des tâches, c'est suffisant. L'en-tête User-Agent est critique : sans lui, une partie des serveurs renvoie un 403 ou un captcha.

Analyser du JSON sans bibliothèques

VBA ne sait pas parser le JSON « nativement », mais pour des réponses simples, les fonctions de chaînes suffisent. Supposons que l'API a renvoyé :

json
{"price": 152.34, "currency": "USD", "symbol": "AAPL"}

On peut extraire la valeur d'un champ avec une petite fonction :

vba
Function ExtractJsonValue(ByVal json As String, ByVal key As String) As String
    Dim pattern As String
    Dim startPos As Long, endPos As Long

    pattern = """" & key & """:"
    startPos = InStr(json, pattern)
    If startPos = 0 Then Exit Function

    startPos = startPos + Len(pattern)
    ' On saute le guillemet si la valeur est une chaîne
    If Mid(json, startPos, 1) = """" Then startPos = startPos + 1

    ' La fin de la valeur : virgule, accolade fermante ou guillemet
    endPos = startPos
    Do While endPos <= Len(json)
        Dim ch As String
        ch = Mid(json, endPos, 1)
        If ch = "," Or ch = "}" Or ch = """" Then Exit Do
        endPos = endPos + 1
    Loop

    ExtractJsonValue = Trim(Mid(json, startPos, endPos - startPos))
End Function

Cette approche fonctionne pour des objets plats. Si la structure est imbriquée et complexe, mieux vaut intégrer un parseur JSON prêt à l'emploi pour VBA (par exemple le module open source VBA-JSON de Tim Hall) : il transforme la réponse en Dictionary et Collection, faciles à manipuler.

L'enchaînement « requête HTTP → analyse du JSON → écriture dans une cellule » est le modèle de base sur lequel repose le scraping des taux de change. La plupart des services de banques centrales et des API de devises renvoient justement du JSON ou du XML, et la fonction d'extraction de valeurs décrite ci-dessus couvre 80 % des cas. Une analyse détaillée d'une solution complète avec mise à jour automatique par minuterie se trouve dans l'article « Scraping des taux de change ».

Analyser le HTML avec MSHTML

Quand les données ne sont pas dans une API mais directement dans le balisage de la page, l'objet HTMLDocument est pratique. Il permet de rechercher des éléments comme dans un navigateur : par id, par balises et par classes.

vba
Function ParseHtmlElement(ByVal url As String, ByVal elementId As String) As String
    Dim http As Object, htmlDoc As Object
    Set http = CreateObject("MSXML2.XMLHTTP")

    http.Open "GET", url, False
    http.setRequestHeader "User-Agent", "Mozilla/5.0"
    http.send

    Set htmlDoc = CreateObject("htmlfile")
    htmlDoc.body.innerHTML = http.responseText

    Dim el As Object
    Set el = htmlDoc.getElementById(elementId)
    If Not el Is Nothing Then
        ParseHtmlElement = Trim(el.innerText)
    End If

    Set http = Nothing
    Set htmlDoc = Nothing
End Function

S'il faut extraire plusieurs éléments par classe ou par balise, on parcourt la collection :

vba
Sub ParseAllRows(ByVal url As String)
    Dim http As Object, htmlDoc As Object
    Set http = CreateObject("MSXML2.XMLHTTP")
    http.Open "GET", url, False
    http.setRequestHeader "User-Agent", "Mozilla/5.0"
    http.send

    Set htmlDoc = CreateObject("htmlfile")
    htmlDoc.body.innerHTML = http.responseText

    Dim rows As Object, i As Long
    Set rows = htmlDoc.getElementsByTagName("tr")

    For i = 0 To rows.Length - 1
        ' On écrit le texte de chaque ligne du tableau sur la feuille, à partir de la 2e ligne
        Cells(i + 2, 1).Value = Trim(rows.Item(i).innerText)
    Next i

    Set http = Nothing
    Set htmlDoc = Nothing
End Sub

Expressions régulières

Parfois, la valeur recherchée est cachée dans le texte sans enveloppe pratique. C'est là que RegExp vient à la rescousse :

vba
Function ExtractByRegex(ByVal text As String, ByVal pattern As String) As String
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")
    re.Global = False
    re.IgnoreCase = True
    re.pattern = pattern

    Dim matches As Object
    Set matches = re.Execute(text)
    If matches.Count > 0 Then
        ' On renvoie le premier groupe de capture
        ExtractByRegex = matches(0).SubMatches(0)
    End If

    Set re = Nothing
End Function

' Exemple : extraire un nombre d'une chaîne du type "Prix : 152.34 EUR"
' value = ExtractByRegex(s, "Prix\s*:\s*([\d\.]+)")

Écrire le résultat sur la feuille

Écrire les données cellule par cellule est lent. S'il y a beaucoup de lignes, regroupez-les dans un tableau et déchargez-les en une seule affectation :

vba
Sub WriteArrayFast(data() As Variant)
    Dim n As Long
    n = UBound(data) - LBound(data) + 1
    ' On décharge toute la colonne en une seule opération
    Range("A1").Resize(n, 1).Value = Application.Transpose(data)
End Sub

Ce déchargement est des dizaines de fois plus rapide qu'une boucle qui écrit dans chaque cellule, surtout avec la mise à jour de l'écran désactivée :

vba
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' ... scraping et écriture ...
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True

Exemple pratique : scraper un tableau de cotations

Construisons un petit scraper qui parcourt une liste de tickers, interroge le prix via une API fictive et place le résultat sur la feuille.

vba
Sub ParseQuotes()
    Dim tickers As Variant
    tickers = Array("AAPL", "MSFT", "GOOGL", "TSLA")

    Dim i As Long, url As String, response As String, price As String

    ' En-têtes du tableau
    Cells(1, 1).Value = "Ticker"
    Cells(1, 2).Value = "Prix"
    Cells(1, 3).Value = "Heure"

    Application.ScreenUpdating = False

    For i = LBound(tickers) To UBound(tickers)
        url = "https://example-api.com/quote?symbol=" & tickers(i)
        response = GetResponse(url)              ' fonction de la section ci-dessus
        price = ExtractJsonValue(response, "price")

        Cells(i + 2, 1).Value = tickers(i)
        Cells(i + 2, 2).Value = Val(price)
        Cells(i + 2, 3).Value = Now

        ' Pause entre les requêtes pour ne pas surcharger le serveur et éviter un blocage
        Application.Wait Now + TimeValue("0:00:01")
    Next i

    Application.ScreenUpdating = True
    MsgBox "Termine : " & (UBound(tickers) + 1) & " cotations chargees", vbInformation
End Sub

Il s'agit d'un squelette simplifié. En pratique, pour le scraping des cotations boursières, on ajoute l'analyse du volume des échanges, des variations en pourcentage, des données historiques, ainsi que la gestion des week-ends et des heures de fermeture de la bourse. Pour l'implémentation complète avec mise à jour automatique et mise en forme conditionnelle, consultez l'article « Scraping des cotations boursières ».

Gestion des erreurs et robustesse

Les requêtes réseau échouent : serveur qui ne répond pas, timeout, format incorrect. Le scraper doit y survivre, et non planter à la première erreur.

vba
Function SafeGet(ByVal url As String, Optional retries As Long = 3) As String
    Dim attempt As Long
    For attempt = 1 To retries
        On Error Resume Next
        Dim http As Object
        Set http = CreateObject("WinHttp.WinHttpRequest.5.1")
        http.SetTimeouts 5000, 5000, 10000, 10000   ' resolve, connect, send, receive
        http.Open "GET", url, False
        http.setRequestHeader "User-Agent", "Mozilla/5.0"
        http.send

        If Err.Number = 0 And http.Status = 200 Then
            SafeGet = http.responseText
            On Error GoTo 0
            Exit Function
        End If
        On Error GoTo 0

        ' La pause avant chaque nouvelle tentative augmente a chaque fois
        Application.Wait Now + TimeValue("0:00:0" & attempt)
    Next attempt

    SafeGet = ""   ' toutes les tentatives sont epuisees
End Function

L'objet WinHttpRequest est ici plus pratique que XMLHTTP précisément grâce à la méthode SetTimeouts : on peut définir explicitement les délais d'attente et éviter de rester bloqué indéfiniment.

Éthique et limites

Quelques règles qui économisent les nerfs et la réputation :

  • Lisez le robots.txt et les conditions d'utilisation. Tous les sites n'autorisent pas la collecte automatisée de données.
  • Faites des pauses entre les requêtes. Des dizaines de requêtes par seconde ressemblent à une attaque et mènent au bannissement de l'IP.
  • Privilégiez les API officielles. Si la source dispose d'une API, utilisez-la : c'est plus stable et légal.
  • Ne collectez pas de données personnelles sans base légale ni consentement.
  • Mettez le résultat en cache. Si le taux de change est mis à jour une fois par jour, inutile de solliciter le serveur toutes les minutes.

Alternative sans code : Power Query

Il faut mentionner que pour de nombreuses tâches, VBA n'est même pas nécessaire. Power Query, intégré à Excel (Données → Obtenir des données → À partir du web), sait charger des tableaux HTML et des réponses JSON via l'interface, avec actualisation automatique planifiée. Si la source fournit un tableau propre ou une API REST sans authentification compliquée, Power Query résoudra la tâche plus vite et sans une seule ligne de code. VBA reste utile lorsqu'il faut de la logique, des branchements, des boucles sur une liste et une analyse non standard.

Conclusion

Le scraping en VBA se construit à partir de quelques briques : requête HTTP (XMLHTTP ou WinHttp), analyse de la réponse (fonctions de chaînes, RegExp ou HTMLDocument), écriture dans les cellules et gestion des erreurs. Une fois cet ensemble maîtrisé, vous pouvez automatiser la collecte de pratiquement n'importe quelles données tabulaires directement dans votre classeur Excel habituel.

Deux scénarios classiques idéaux pour s'entraîner :

  • Le scraping des taux de change — une source JSON/XML simple, parfaite pour un premier scraper.
  • Le scraping des cotations boursières — un peu plus complexe : liste de tickers, mises à jour fréquentes, mise en forme.

Les deux sont traités dans des articles dédiés — commencez par celui qui est le plus proche de votre besoin ; les fonctions décrites ici (GetResponse, ExtractJsonValue, SafeGet) serviront de socle commun aux deux.