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 :
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 Open — False — 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é :
{"price": 152.34, "currency": "USD", "symbol": "AAPL"}
On peut extraire la valeur d'un champ avec une petite fonction :
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.
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 :
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 :
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 :
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 :
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.
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.
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.txtet 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.