Comment puis-je extraire des données d'un site Web et remplir une feuille Excel à l'aide de VBA?
Je souhaite extraire des données de betexplorer.com. Je souhaite extraire deux données différentes de l'URL suivante:
https://www.betexplorer.com/soccer/s...eague-1/stats/
Je voudrais extraire les matchs joués et les matchs restants Je voudrais extraire les buts à domicile et à l'extérieur (par match)
J'ai le code pour le faire et c'est comme suit:
Option Explicit
Sub GetSoccerStats()
'Set a reference (VBE > Tools > References) to the following libraries:
' 1) Microsoft XML, v6.0
' 2) Microsoft HTML Object Library
Dim xmlReq As New MSXML2.XMLHTTP60
Dim objDoc As New MSHTML.HTMLDocument
Dim objTable As MSHTML.htmlTable
Dim objTableRow As MSHTML.htmlTableRow
Dim strURL As String
Dim strResp As String
Dim strText As String
Dim rw As Long
strURL = "https://www.betexplorer.com/soccer/south-korea/k-league-1/stats/"
With xmlReq
.Open "GET", strURL, False
.send
If .Status <> 200 Then
MsgBox "Error " & .Status & ": " & .statusText
Exit Sub
End If
strResp = .responseText
End With
Worksheets.Add
objDoc.body.innerHTML = strResp
Set objTable = objDoc.getElementsByClassName("table-main leaguestats")(0)
If Not objTable Is Nothing Then
rw = 1
For Each objTableRow In objTable.Rows
strText = objTableRow.Cells(0).innerText
Select Case strText
Case "Matches played", "Matches remaining", "Home goals", "Away goals"
Cells(rw, "a").Value = objTableRow.Cells(0).innerText
Cells(rw, "b").Value = objTableRow.Cells(1).innerText
Cells(rw, "c").Value = objTableRow.Cells(2).innerText
rw = rw + 1
End Select
Next objTableRow
Columns("a").AutoFit
End If
Set xmlReq = Nothing
Set objDoc = Nothing
Set objTable = Nothing
Set objTableRow = Nothing
End Sub
Ce code fonctionne mais je veux aller plus loin.
Je souhaite en fait exécuter cette macro pour de nombreuses URL différentes sur le même site. J'ai une feuille de calcul déjà créée qui contient une liste des ligues de football (dans les lignes), les colonnes contiennent les données.
Vous pouvez trouver le fichier ici: https://www.dropbox.com/s/77sol24sty75w5z/Avg%20Goals.xlsm?dl=0
Il s'agit d'un fichier dans lequel j'ajouterai des ligues aux lignes au fur et à mesure. Est-il possible d'adapter le code qui extrait les données pour qu'il puisse peupler les colonnes de ma feuille? Je n'ai pas besoin de saisir les noms des données (matchs restants, buts à domicile, buts à l'extérieur, etc.) comme le fait ce code, j'ai seulement besoin des chiffres. Les chiffres extraits devraient remplir les colonnes selon la feuille (de sorte que chaque ligne contient les données pour chaque ligue. Comme vous pouvez le voir, il y a quelques ligues, il faudrait donc parcourir chaque ligne, puis utiliser l'URL correspondante pour cela. rangée.
Vous remarquerez qu'il y a une colonne qui contient le mot ACTUEL. Cela indique qu'il doit utiliser l'URL dans la colonne URL actuelle. Si je change la valeur en LAST, je voudrais qu'il utilise l'URL dans la colonne Dernière URL.
Pour chaque ligue, ce sera différent si j'utilise CURRENT ou LAST.
Voici une image de la sortie attendue:
Toute aide est grandement appréciée.
Conformément à votre code, les données de ces éléments seront affichées dans les colonnes M: T. J'ai une fonction d'assistance GetLinks
, qui génère un tableau d'URL finales à utiliser en fonction de la valeur de la colonne K:
inputArray = GetLinks(inputArray)
Ce tableau est en boucle et des requêtes xhr sont émises pour l'information. Toutes les informations sur les résultats sont stockées dans un tableau, results
qui est écrit en une seule fois sur la feuille à la fin.
Je travaille avec un tableau tout au long car vous ne voulez pas continuer à lire à partir de la feuille; c'est une opération coûteuse qui ralentit votre code. Pour la même raison, si <> 200 se produit, j'imprime dans la fenêtre immédiate le message et l'url afin de ne pas ralentir le code. Vous avez effectivement un journal que vous pouvez consulter à la fin.
Les résultats récupérés sont écrits à partir de la colonne M, mais comme les données sont dans un tableau, vous pouvez facilement écrire là où vous le souhaitez; changez simplement la cellule de début pour coller à partir M4
de la cellule la plus à gauche de votre choix. Vos colonnes existantes n'ont pas de pourcentages, donc je me sentais en sécurité pour supposer que vous vous attendiez à ce que les données écrites soient dans de nouvelles colonnes (peut-être même dans une feuille différente).
Option Explicit
Public Sub GetSoccerStats()
Dim xmlReq As New MSXML2.XMLHTTP60, response As String
Dim objDoc As New MSHTML.HTMLDocument, text As String
Dim lastRow As Long, dataSheet As Worksheet, inputArray(), i As Long
Set dataSheet = ThisWorkbook.Worksheets("AVG GOAL DATA")
With dataSheet
lastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
End With
inputArray = dataSheet.Range("J4:L" & lastRow).Value
inputArray = GetLinks(inputArray)
Dim results(), r As Long, c As Long
ReDim results(1 To UBound(inputArray, 1), 1 To 8)
With xmlReq
For i = LBound(inputArray, 1) To UBound(inputArray, 1)
r = r + 1
.Open "GET", inputArray(i, 4), False
.send
If .Status <> 200 Then
Debug.Print inputArray(i, 4), vbTab, "Error " & .Status & ": " & .statusText
Else
response = .responseText
objDoc.body.innerHTML = response
Dim objTable As MSHTML.HTMLTable, objTableRow As MSHTML.HTMLTableRow
Set objTable = objDoc.getElementsByClassName("table-main leaguestats")(0)
If Not objTable Is Nothing Then
c = 1
For Each objTableRow In objTable.Rows
text = objTableRow.Cells(0).innerText
Select Case text
Case "Matches played", "Matches remaining", "Home goals", "Away goals"
results(r, c) = objTableRow.Cells(1).innerText
results(r, c + 1) = objTableRow.Cells(2).innerText
c = c + 2
End Select
Next objTableRow
End If
End If
Set objTable = Nothing
Next
End With
dataSheet.Range("M4").Resize(UBound(results, 1), UBound(results, 2)) = results
End Sub
Public Function GetLinks(ByRef inputArray As Variant) As Variant
Dim i As Long
ReDim Preserve inputArray(1 To UBound(inputArray, 1), 1 To UBound(inputArray, 2) + 1)
For i = LBound(inputArray, 1) To UBound(inputArray, 1)
inputArray(i, 4) = IIf(inputArray(i, 1) = "CURRENT", inputArray(i, 2), inputArray(i, 3))
Next
GetLinks = inputArray
End Function
Disposition du fichier:
Étant donné le grand nombre de demandes qui ont entraîné un blocage, voici la version IE:
'VBE > Tools > References:
'1: Microsoft HTML Object library 2: Microsoft Internet Controls
Public Sub GetSoccerStats()
Dim ie As Object, t As Date
Dim objDoc As New MSHTML.HTMLDocument, text As String
Dim lastRow As Long, dataSheet As Worksheet, inputArray(), i As Long
Const MAX_WAIT_SEC As Long = 10
Set dataSheet = ThisWorkbook.Worksheets("AVG GOAL DATA")
Set ie = CreateObject("InternetExplorer.Application")
With dataSheet
lastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
End With
inputArray = dataSheet.Range("C4:E" & lastRow).Value
inputArray = GetLinks(inputArray)
Dim results(), r As Long, c As Long
ReDim results(1 To UBound(inputArray, 1), 1 To 8)
With ie
.Visible = True
For i = LBound(inputArray, 1) To UBound(inputArray, 1)
r = r + 1
.navigate2 inputArray(i, 4)
While .Busy Or .readyState < 4: DoEvents: Wend
Dim objTable As MSHTML.HTMLTable, objTableRow As MSHTML.HTMLTableRow
t = timer
Do
DoEvents
On Error Resume Next
Set objTable = .document.getElementsByClassName("table-main leaguestats")(0)
On Error GoTo 0
If Timer - t > MAX_WAIT_SEC Then Exit Do
Loop While objTable Is Nothing
If Not objTable Is Nothing Then
c = 1
For Each objTableRow In objTable.Rows
text = objTableRow.Cells(0).innerText
Select Case text
Case "Matches played", "Matches remaining", "Home goals", "Away goals"
results(r, c) = objTableRow.Cells(1).innerText
results(r, c + 1) = objTableRow.Cells(2).innerText
c = c + 2
End Select
Next objTableRow
End If
Set objTable = Nothing
Next
.Quit
End With
dataSheet.Range("F4").Resize(UBound(results, 1), UBound(results, 2)) = results
End Sub