2017-08-25 1 views
1

Malheureusement, je ne connais pas vraiment les "composants" du code HTML (tags, classes, ids, etc.) et comment ils diffèrent les uns des autres. J'essaie de faire exécuter une liste de liens à un programme, de cliquer sur chacun d'entre eux, puis de trouver un lien de téléchargement sur la page «cliquée». Mon exemple d'URL est "https://c64g.com/games/" et j'ai réussi à parcourir la liste des liens et à laisser VBA ouvrir chaque lien. Cependant, je ne peux pas laisser VBA identifier combien de fichiers sont sur la page à télécharger car je ne peux pas récupérer ces "éléments" du HTML.VBA - Comment parcourir la liste des liens de téléchargement (webscraping)

Exemple (sélection de la page pour "1942"):

<h1 class="c64u px16">Free C64 Game Download</h1> 
<form action="/games/download/get/12" method="post"> 
    <button class="btn-link" type="submit">Download 1942.Elite.+2-BAM.zip (31K)</button> 
</form> 
<form action="/games/download/get/13" method="post"> 
    <button class="btn-link" type="submit">Download 1942.Elite.+7hpd-REM.zip (38K)</button> 
</form> 
<form action="/games/download/get/14" method="post"> 
    <button class="btn-link" type="submit">Download 1942.Elite.CFO.zip (27K)</button> 
</form> 
<form action="/games/download/get/15" method="post"> 
    <button class="btn-link" type="submit">Download 1942_v1.Capcom.+2-MHI.zip (25K)</button> 
</form> 
<form action="/games/download/get/16" method="post"> 
    <button class="btn-link" type="submit">Download 1942_v2.Capcom.+2p-MHI.zip (37K)</button> 
</form> 
<script type="text/javascript"><!-- 

code VBA:

Sub useClassnames() 

Dim ie As Object 
Dim internetlink As Object 
Dim internetinnerlink As Object 

Set ie = CreateObject("InternetExplorer.Application") 

ie.Visible = True 
ie.navigate ("https://c64g.com/games/") 

Do While ie.readyState <> READYSTATE_COMPLETE 
    Application.StatusBar = "Loading Web page..." 
    DoEvents 
Loop 


Set internetlink = ie.document.getElementsByTagName("a") 
i = 0 

For Each internetinnerlink In internetlink 
'for testing purposes I want only to open the page for "1942", later all links will be run through 
    If internetinnerlink.innerText = "1942" Then 
     internetinnerlink.Click 
     Exit For 
    End If 
    i = i + 1 
Next internetinnerlink 

Dim alldownloads As Object 
'I have tried any kind of name ("btn-group", "button class", btn-link") and element fetch code (by Id, by name, by tagname, by classname) 
Set alldownloads = internetlink(i).getElementsByClassName("btn-group") 
MsgBox "alldownloads.Length: " & alldownloads.Length 

'ie.Quit 

End Sub 

Toute aide est vraiment apprécié, en particulier pour expliquer pourquoi je ne peux pas saisir tout le texte de la page (par exemple en tant que chaîne de caractères) et que VBA travaille dessus jusqu'à ce qu'il trouve le mot "btn-link". Bien sûr, je dois obtenir chaque lien en tant qu '«élément» ou «élément» (ne sachant pas quel format de données utiliser alors que la chaîne ne serait pas la réponse). Merci d'expliquer comment le faire correctement.

Répondre

0

Je ne sais pas pourquoi référez-vous à l'internetlink (i) que c'est un tableau de l'élément précédent contenant les éléments avec un nom de tag "a" dans la page précédente, vous devez utiliser l'objet IE qui a été chargé avec la nouvelle page contenant le lien de téléchargement, obtenez les liens du corps html, puis faites ce que vous voulez avec eux.

Dans cet exemple, je vais vous montrer comment télécharger un seul fichier de la page que vous avez demandée.

Il suffit de lire le commentaire dans ce code.

Le lien de téléchargement sont supérieur l'élément de bouton dans l'action de la forme, de sorte que nous prenons chaque classe BTN-lien et avec leurs parents, nous obtenons l'action de forme (le lien pour télécharger le fichier)

Parce que pour télécharger le zip nous devons faire une demande POST, nous devons utiliser l'objet SHDocVw.InternetExplorer Navigate Method pour poster quelque chose qui n'est pas pertinent, donc j'ai créé une chaîne de test convertie en byte pour l'afficher dans la requête, après avoir navigué dans une fenêtre pour télécharger le l'article devrait apparaître dans IE.

Faites un essai.

Sub useClassnames() 

Dim ie As Object 
Dim internetlink As Object 
Dim internetinnerlink As Object 

Set ie = CreateObject("InternetExplorer.Application") 

ie.Visible = True 
ie.navigate ("https://c64g.com/games/") 

Do While ie.readyState <> READYSTATE_COMPLETE 
    Application.StatusBar = "Loading Web page..." 
    DoEvents 
Loop 


Set internetlink = ie.document.getElementsByTagName("a") 
i = 0 

For Each internetinnerlink In internetlink 
    If internetinnerlink.innerText = "1942" Then 
     internetinnerlink.Click 
     Exit For 
    End If 
    i = i + 1 
Next internetinnerlink 


Do While ie.readyState <> READYSTATE_COMPLETE 
    Application.StatusBar = "Loading Web page..." 
    DoEvents 
Loop 

Set alldownloads = ie.document.getElementsByClassName("btn-link") 
MsgBox "alldownloads.Length: " & alldownloads.Length 
'example with 1 link, you should create an array of them then cycle it, i commented the for each out, you could decomment and use itm to get every btn-link 
'For Each itm In alldownloads 
    Set tst = alldownloads(0).parentelement 'parent of the button where the form post data is, with the link to the download 
    link = tst.Action 'taking the download link 
'Next itm 


'Now i create and example data to post, we cannot use POST Method in InternetExplorer.Application without posting anything. 
FormData = "test" 
Dim bFormData() As Byte 
ReDim bFormData(Len(FormData) - 1) 
bFormData = StrConv(FormData, vbFromUnicode) 

'Posting the request to the previous link, now a window with the attempt to download the file should open in IE. 
ie.navigate link, Empty, Empty, bFormData 

ie.Quit 

End Sub