#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 Извините, я только что нашел способ проверить это и большое вам спасибо за ваш код!; Я думаю, что я не импортировал справочные модули, когда он не запускался, и не знал, как включить окно отладки