Данные VBA-reactid для финансовых показателей Yahoo Finance

#excel #vba #web-scraping #yahoo-finance #queryselector

#excel #vba #очистка веб-страниц #yahoo-финансы #выбор запросов

Вопрос:

Я погуглил data-reactid и, похоже, в большинстве случаев он не будет работать с VBA.

Но я все еще думаю, что, возможно, есть возможность получить ответ. Я хочу получить цифры в «Общем денежном потоке от операционной деятельности«

https://finance .yahoo.com/quote/BABA/cash-flow?p=BABA

 Sub YFinance()

    Dim XMLReq As New MSXML2.XMLHTTP60
    Dim HTMLDoc As New MSHTML.HTMLDocument
    Dim i As Integer
    Dim strUrl As String



    XMLReq.Open "GET", "https://finance.yahoo.com/quote/BABA/cash-flow?p=BABA", False
    XMLReq.send

    If XMLReq.Status <> 200 Then
        MsgBox "Error!"
        Exit Sub
    End If

    HTMLDoc.body.innerHTML = XMLReq.responseText

    Set XMLReq = Nothing

    MsgBox HTMLDoc.getElementsById("Bdbw(0px)! H(36px)")(0).innerText






End Sub
  

Ответ №1:

getElementById возвращает один узел, чтобы вы не индексировали в нем, как вы делаете. Не существует метода, getElementsById поэтому он должен завершиться ошибкой.

Вы могли бы использовать класс и экранировать специальные символы и индекс в возвращаемой коллекции

 MsgBox HTMLDoc.querySelectorAll(".Bdbw(0px)!")(1).innerText
  

Или передайте составной класс в getElementsByClassName :

 MsgBox HTMLDoc.getElementsByClassName("Bdbw(0px)! H(36px)")(1).innerText
  

Атрибут (не id) data-reactid может отличаться в зависимости от страницы и выходных данных (как это происходит в этом случае — идентификатор равен 113 для строки в выходных данных. В этом случае может быть безопаснее использовать индексы таблиц и строк

 MsgBox HTMLDoc.getElementsByTagName("table")(2).getElementsByTagName("tr")(9).innerText
  

Если вы хотите, чтобы столбец за столбцом для этой строки:

 Dim td As Object, tds As Object
Set tds = HTMLDoc.getElementsByTagName("table")(2).getElementsByTagName("tr")(9).getElementsByTagName("td")
For Each td In tds
    Debug.Print td.innerText
Next
  

Или

 Dim td As Object, tds As Object
Set tds = HTMLDoc.getElementsByClassName("Bdbw(0px)! H(36px)")(1).getElementsByTagName("td")
For Each td In tds
    Debug.Print td.innerText
Next
  

Как я уже сказал, data-reactid может изменяться, но если вы хотите знать, как применить для этого селектор атрибутов, см.:

 MsgBox HTMLDoc.querySelector("tr[data-reactid='113']").innerText
  

Комментарии:

1. Большое вам спасибо за помощь! Как абсолютный новичок, я подумал, что для извлечения этих чисел определенно нужны сложные инструменты. Не могли бы вы рассказать мне, как вы получили порядковый номер тега <table> и <tr>? Вы просто посчитали это или есть какой-нибудь инструмент для этого?

2. Большое спасибо за добавленный код и пояснения! Ваш ответ мне очень помог, хотя я думаю, что мне следует изучить его более глубоко, чтобы понять новые концепции и термины 🙂

Ответ №2:

Для надежности вы можете попробовать следующее. Как только for loop получит требуемый узел, он извлечет желаемый контент и завершит цикл.

 Sub FetchFinanceInfo()
    Dim XMLReq As New XMLHTTP60, HTMLDoc As New HTMLDocument
    Dim post As Object, Iamp;

    XMLReq.Open "GET", "https://finance.yahoo.com/quote/BABA/cash-flow?p=BABA", False
    XMLReq.send
    HTMLDoc.body.innerHTML = XMLReq.responseText

    For Each post In HTMLDoc.getElementsByTagName("span")
        If InStr(post.innerText, "From Operating Activities") > 0 Then
            With post.ParentNode.ParentNode.getElementsByTagName("td")
                For I = 1 To .Length - 1
                    Debug.Print .Item(I).innerText
                Next I
            End With
            Exit For
        End If
    Next post
End Sub
  

Комментарии:

1. 👀 parentnode.родительский узел

2. Я действительно ценю ваш ответ за правильный цикл в качестве решения 🙂 Я буду усердно это изучать :))

3. Код работает так, как и должно быть. Я только что протестировал прямо сейчас @BangolPhoenix.

4. @SIM Извините, я только что нашел способ проверить это и большое вам спасибо за ваш код!; Я думаю, что я не импортировал справочные модули, когда он не запускался, и не знал, как включить окно отладки