Я пытаюсь очистить данные с веб-сайта: http://uk.investing.com/rates-bonds/financial-futures через vba, например, в режиме реального времени, т.е. Немецкий 5 YR Bobl, US 30Y T-Bond, я попробовал excel веб-запрос, но он только царапины всего сайта, но я хотел бы очистить скорость только, есть ли способ сделать это?
Скремблирование данных с веб-сайта с помощью vba
Ответ 1
Есть несколько способов сделать это. Это ответ, который я пишу, надеясь, что все основы автоматизации Internet Explorer будут найдены при просмотре ключевых слов "скремблирование данных с веб-сайта", но помните, что ничто не стоит как ваше собственное исследование (если вы не хотите придерживаться предварительно написанные коды, которые вы не можете настроить).
Обратите внимание, что это один из способов, который я не предпочитаю с точки зрения производительности (поскольку это зависит от скорости браузера), но это хорошо, чтобы понять логику автоматизации Интернета.
1) Если мне нужно просматривать веб-страницы, мне нужен браузер! Поэтому я создаю браузер Internet Explorer:
Dim appIE As Object
Set appIE = CreateObject("internetexplorer.application")
2) Я прошу браузер просмотреть целевую веб-страницу. Благодаря использованию свойства ".Visible", я решаю, хочу ли я видеть, как браузер выполняет свою работу или нет. При создании кода приятно иметь Visible = True
, но когда код работает для очистки данных, приятно не видеть его каждый раз, поэтому Visible = False
.
With appIE
.Navigate "http://uk.investing.com/rates-bonds/financial-futures"
.Visible = True
End With
3) На веб-страницу потребуется некоторое время для загрузки. Итак, я буду ждать, пока он занят...
Do While appIE.Busy
DoEvents
Loop
4) Ну, теперь страница загружена. Скажем, что я хочу очистить изменение US30Y T-Bond: то, что я сделаю, это просто щелкнуть F12 в Internet Explorer, чтобы увидеть код веб-страницы, и, следовательно, используя указатель (в красном круге), я нажму на элемент, который Я хочу очистить, чтобы понять, как я могу достичь своей цели.
5) То, что я должен сделать, прямолинейно. Прежде всего, я получу по свойству ID элемент tr
который содержит значение:
Set allRowOfData = appIE.document.getElementById("pair_8907")
Здесь я получу коллекцию элементов td
(в частности, tr
- это строка данных, а td
- ее ячейки. Мы ищем восьмое место, поэтому напишу:
Dim myValue As String: myValue = allRowOfData.Cells(7).innerHTML
Почему я написал 7 вместо 8? Поскольку коллекции ячеек начинаются с 0, поэтому индекс восьмого элемента равен 7 (8-1). Вкратце анализируя эту строку кода:
-
.Cells()
позволяет мне получить доступ к элементамtd
; -
innerHTML
- это свойство ячейки, в которой находится значение, которое мы ищем.
Как только у нас есть наше значение, которое теперь сохраняется в переменной myValue
, мы можем просто закрыть браузер IE и освободить память, установив его в Nothing:
appIE.Quit
Set appIE = Nothing
Итак, теперь у вас есть ваша ценность, и вы можете делать с ней все, что хотите: поместите ее в ячейку (Range("A1").Value = myValue
) или в метку формы (Me.label1.Text = myValue
).
Я просто хотел бы указать вам, что это не так, как работает StackOverflow: здесь вы публикуете вопросы о конкретных проблемах с кодированием, но сначала вы должны сделать свой собственный поиск. Причина, по которой я отвечаю на вопрос, который не показывает слишком много исследований, - это то, что я вижу его несколько раз, и, когда я узнал, как это сделать, я помню, что мне было бы лучше поддержка для начала работы. Поэтому я надеюсь, что этот ответ, который является всего лишь "вкладом в исследование" и вовсе не лучшим/самым полным решением, может быть поддержкой для следующего пользователя, имеющего такую же проблему. Потому что я научился программировать благодаря этому сообществу, и мне нравится думать, что вы и другие новички могли бы использовать мой вклад, чтобы открыть прекрасный мир программирования.
Наслаждайтесь своей практикой;)
Ответ 2
Были упомянуты и другие методы, поэтому позвольте нам признать, что на момент написания статьи мы находимся в 21 веке. Позвольте парковать браузер, открывающий локальную шину, и выполняйте запрос XMLHTTP GET (для краткости XHR GET).
XHR - это API в форме объекта, методы которого передают данные между веб-браузером и веб-сервером. Объект предоставлен среда JavaScript браузера
Это быстрый метод для получения данных, который не требует открытия браузера. Ответ сервера может быть прочитан в HTMLDocument, и оттуда процесс захвата таблицы продолжается.
В приведенном ниже коде таблица захватывается своим идентификатором cr1
.
В вспомогательной подпрограмме WriteTable
мы зацикливаем столбцы (теги td
), а затем строки таблицы (теги tr
) и, наконец, пересекаем длину каждой строки таблицы, ячейка таблицы по ячейке таблицы. Поскольку нам нужны только данные из столбцов 1 и 8, используется оператор Select Case
, который указывает, что записывается на лист.
Пример просмотра веб-страницы:
Пример вывода кода:
VBA:
Option Explicit
Public Sub GetRates()
Dim html As HTMLDocument, hTable As HTMLTable '<== Tools > References > Microsoft HTML Object Library
Set html = New HTMLDocument
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" 'to deal with potential caching
.send
html.body.innerHTML = .responseText
End With
Application.ScreenUpdating = False
Set hTable = html.getElementById("cr1")
WriteTable hTable, 1, ThisWorkbook.Worksheets("Sheet1")
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
Ответ 3
вы можете использовать объект winhttprequest вместо интернет-исследователя, так как он хорош для загрузки данных, за исключением изображений n рекламы, а не для загрузки полной веб-страницы, включая рекламу n изображений, которые делают объект Internet Explorer сложным по сравнению с объектом winhttpRequest.
Ответ 4
Этот вопрос задал задолго до этого. Но я думал, что следующая информация будет полезна для новичков. На самом деле вы можете легко получить значения из имени класса, как это.
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
И если вы новичок в веб-соскабливании, прочитайте это сообщение в блоге.
А также есть различные методы для извлечения данных с веб-страниц. Эта статья объясняет несколько из них примерами.
Ответ 5
Я изменил некоторые вещи, которые выставляли ошибку для меня, и в конечном итоге это отлично работало, чтобы извлечь данные по мере необходимости:
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