web-dev-qa-db-fra.com

Raclage des données d'un site web avec vba

J'essaie de récupérer des données du site Web: http://uk.investing.com/rates-bonds/financial-futures via vba, comme le prix en temps réel, c'est-à-dire l'allemand 5 YR Bobl, US 30Y T-Bond, j'ai essayé la requête Web Excel, mais il ne fait qu'effleurer tout le site Web, mais je voudrais ne gratter que le taux. Existe-t-il un moyen de le faire?

12
rockNroll

Il y a plusieurs façons de le faire. C’est une réponse que j’écris en espérant que toutes les bases de l’automatisation d’Internet Explorer seront trouvées lors de la recherche des mots-clés "extraire les données du site Web", mais rappelez-vous que rien ne vaut votre propre recherche codes pré-écrits que vous ne pouvez pas personnaliser).

Notez que ceci est un moyen , que je ne préfère pas en termes de performances (car cela dépend de la vitesse du navigateur), mais il est bon de comprendre la logique qui sous-tend l’automatisation Internet.

1) Si j'ai besoin de naviguer sur le Web, j'ai besoin d'un navigateur! Je crée donc un navigateur Internet Explorer:

Dim appIE As Object
Set appIE = CreateObject("internetexplorer.application")

2) Je demande au navigateur de parcourir la page Web cible. En utilisant la propriété ".Visible", je décide si je veux voir le navigateur faire son travail ou non. Lorsque vous créez le code, il est agréable d’avoir Visible = True, mais lorsque le code fonctionne pour extraire des données, il est agréable de ne pas le voir à chaque fois, donc Visible = False

With appIE
    .Navigate "http://uk.investing.com/rates-bonds/financial-futures"
    .Visible = True
End With

3) La page Web aura besoin de temps pour charger. Donc, je vais attendre en attendant, il est occupé ...

Do While appIE.Busy
    DoEvents
Loop

4) Eh bien, maintenant la page est chargée. Supposons que je veuille gratter le changement de l'US30Y T-Bond: Je vais simplement cliquer sur F12 sur Internet Explorer pour voir le code de la page Web, et donc utiliser le pointeur (en cercle rouge) pour cliquer sur l'élément que je veux gratter pour voir comment puis-je atteindre mon objectif. 

enter image description here

5) Ce que je devrais faire est simple. Tout d'abord, j'obtiendrai par la propriété ID l'élément tr qui contient la valeur:

Set allRowOfData = appIE.document.getElementById("pair_8907")

Ici, je vais obtenir une collection d'éléments td (plus précisément, tr est une rangée de données et les td sont ses cellules. Nous cherchons le huitième, je vais donc écrire:

Dim myValue As String: myValue = allRowOfData.Cells(7).innerHTML

Pourquoi ai-je écrit 7 au lieu de 8? Comme les collections de cellules commencent à 0, l'indice du 8ème élément est 7 (8-1). Analyser brièvement cette ligne de code:

  • .Cells() me fait accéder aux éléments td;
  • innerHTML est la propriété de la cellule contenant la valeur que nous recherchons. 

Une fois que nous avons notre valeur, qui est maintenant stockée dans la variable myValue, nous pouvons simplement fermer le navigateur IE et libérer la mémoire en le définissant sur Nothing:

appIE.Quit
Set appIE = Nothing

Eh bien, maintenant vous avez votre valeur et vous pouvez en faire ce que vous voulez: mettez-la dans une cellule (Range("A1").Value = myValue) ou dans une étiquette d'un formulaire (Me.label1.Text = myValue).

Je voudrais juste vous faire remarquer que ce n'est pas ainsi que StackOverflow fonctionne: vous posez ici des questions sur des problèmes de codage spécifiques, mais vous devez d'abord effectuer votre propre recherche. La raison pour laquelle je réponds à une question qui ne montre pas trop d’efforts de recherche, c’est simplement que je la vois poser plusieurs fois et, au moment où j’ai appris à faire cela, je me souviens que j’aurais aimé avoir une meilleure soutien pour commencer avec. J'espère donc que cette réponse, qui est juste une "entrée d'étude" et n'est pas du tout la solution la meilleure/la plus complète, peut être un support pour le prochain utilisateur ayant le même problème. Parce que j’ai appris à programmer grâce à cette communauté, et j’aime penser que vous et d’autres débutants pourriez utiliser mes contributions pour découvrir le magnifique monde de la programmation. 

Profitez de votre pratique;) 

65
Matteo NNZ

D’autres méthodes ont été mentionnées, alors reconnaissons qu’au moment de la rédaction de ce document, nous sommes au XXIe siècle. Garons le bus local ouverture du navigateur et fly avec un XMLHTTP GET request (XHR GET en abrégé).

Moment Wiki:

XHR est une API sous la forme d'un objet dont les méthodes transfèrent des données entre un navigateur Web et un serveur Web. L'objet est fourni par le Environnement JavaScript du navigateur

C'est une méthode rapide pour récupérer des données qui ne nécessitent pas l'ouverture d'un navigateur. La réponse du serveur peut être lue dans un document HTML et le processus de récupération de la table se poursuit à partir de là.

Dans le code ci-dessous, la table est saisie par son identifiant cr1.

 table

Dans le sous-assistant, WriteTable, nous bouclons les colonnes (balises td), puis les lignes du tableau (balises tr), et finalement, nous parcourons la longueur de chaque ligne de tableau, cellule par cellule. Comme nous ne voulons que des données des colonnes 1 et 8, une instruction Select Case spécifie ce qui est écrit sur la feuille.


Exemple d'affichage de page Web:

 Sample page view


Exemple de sortie de code:

 Code output


VBA:

Option Explicit
Public Sub GetRates()
    Dim sResponse As String, html As New HTMLDocument '<== Tools > References > HTML Object Library
    Dim hTable As HTMLTable
    Application.ScreenUpdating = False
    With CreateObject("MSXML2.XMLHTTP")
        .Open "GET", "https://uk.investing.com/rates-bonds/financial-futures", False
        .setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" 
        .send
        sResponse = StrConv(.responseBody, vbUnicode)
    End With
    sResponse = Mid$(sResponse, InStr(1, sResponse, "<!DOCTYPE "))
    With html
        .body.innerHTML = sResponse
        Set hTable = .getElementById("cr1")
        WriteTable hTable, 1, ThisWorkbook.Worksheets("Sheet1")
    End With
    Application.ScreenUpdating = True
End Sub

Public Sub WriteTable(ByVal hTable As HTMLTable, Optional ByVal startRow As Long = 1, Optional ByVal ws As Worksheet)
    Dim tSection As Object, tRow As Object, tCell As Object, tr As Object, td As Object, r As Long, C As Long, tBody As Object
    r = startRow: If ws Is Nothing Then Set ws = ActiveSheet
    With ws
        Dim headers As Object, header As Object, columnCounter As Long
        Set headers = hTable.getElementsByTagName("th")
        For Each header In headers
            columnCounter = columnCounter + 1
            Select Case columnCounter
            Case 2
                .Cells(startRow, 1) = header.innerText
            Case 8
                .Cells(startRow, 2) = header.innerText
            End Select
        Next header
        startRow = startRow + 1
        Set tBody = hTable.getElementsByTagName("tbody")
        For Each tSection In tBody
            Set tRow = tSection.getElementsByTagName("tr")
            For Each tr In tRow
                r = r + 1
                Set tCell = tr.getElementsByTagName("td")
                C = 1
                For Each td In tCell
                    Select Case C
                    Case 2
                        .Cells(r, 1).Value = td.innerText
                    Case 8
                        .Cells(r, 2).Value = td.innerText
                    End Select
                    C = C + 1
                Next td
            Next tr
        Next tSection
    End With
End Sub
4
QHarr

vous pouvez utiliser l'objet winhttprequest au lieu d'Internet Explorer, car il est conseillé de charger des données à l'exclusion des images n publicité au lieu de télécharger une page Web complète, y compris des images de publicité qui rendent les objets Internet Explorer lourds par rapport à l'objet winhttpRequest. 

1
Nitin k tomar

J'ai modifié quelque chose qui me causait des erreurs et je me suis retrouvé avec cela qui fonctionnait très bien pour extraire les données selon mes besoins

Sub get_data_web()

Dim appIE As Object
Set appIE = CreateObject("internetexplorer.application")

With appIE
    .navigate "https://finance.yahoo.com/quote/NQ%3DF/futures?p=NQ%3DF"
    .Visible = True
End With

Do While appIE.Busy
    DoEvents
Loop

Set allRowofData = appIE.document.getElementsByClassName("Ta(end) BdT Bdc($c-fuji-grey-c) H(36px)")

Dim i As Long
Dim myValue As String

Count = 1

    For Each itm In allRowofData

        For i = 0 To 4

        myValue = itm.Cells(i).innerText
        ActiveSheet.Cells(Count, i + 1).Value = myValue

        Next

        Count = Count + 1

    Next

appIE.Quit
Set appIE = Nothing


End Sub
0
IRENE G

Cette question a été posée bien avant. Mais je pensais que les informations suivantes seraient utiles aux débutants. En fait, vous pouvez facilement obtenir les valeurs du nom de la classe comme ceci.

Sub ExtractLastValue()

Set objIE = CreateObject("InternetExplorer.Application")

objIE.Top = 0
objIE.Left = 0
objIE.Width = 800
objIE.Height = 600

objIE.Visible = True

objIE.Navigate ("https://uk.investing.com/rates-bonds/financial-futures/")

Do
DoEvents
Loop Until objIE.readystate = 4

MsgBox objIE.document.getElementsByClassName("pid-8907-last")(0).innerText

End Sub

Et si vous débutez dans le Web, lisez ce billet.

Web Scraping - Basics

De plus, il existe différentes techniques pour extraire des données de pages Web. Cet article explique quelques-uns d'entre eux avec des exemples.

Web Scraping - Collecte de données depuis une page Web

0
Roshantha De Mel