我试图从网站上抓取数据:http://uk.investing.com/rates-bonds/financial-futures通过vba,就像实时价格一样,即德国5 YR Bobl,美国30Y T-Bond,我尝试过excel网页查询,但它只搜索整个网站,但我只想提高利率,有没有办法做到这一点?
答案 0 :(得分:67)
有几种方法可以做到这一点。这是我写的一个答案,希望在浏览关键词“从网站抓取数据”时可以找到Internet Explorer自动化的所有基础知识,但请记住,没有什么值得作为您自己的研究(如果您不想坚持您无法自定义的预编码。
请注意,这是单向,我不喜欢性能(因为它取决于浏览器速度),但这很好理解互联网自动化的基本原理。< / p>
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的变化: 我要做的就是在Internet Explorer上单击F12以查看网页的代码,因此使用指针(在红色圆圈中)我将点击我想要抓取的元素,看看我如何达到我的目的。
5)我应该做的是直截了当。首先,我将通过ID属性获取包含值<{p>>的tr
元素
Set allRowOfData = appIE.document.getElementById("pair_8907")
在这里,我将获得td
个元素的集合(具体来说,tr
是一行数据,td
是它的单元格。我们正在寻找第8个,所以我会写:
Dim myValue As String: myValue = allRowOfData.Cells(7).innerHTML
为什么我写7而不是8?因为单元格集合从0开始,所以第8个元素的索引是7(8-1)。简要分析这行代码:
.Cells()
让我访问td
元素; innerHTML
是包含我们查找的值的单元格的属性。 一旦我们获得了现在存储在myValue
变量中的值,我们就可以关闭IE浏览器并通过将其设置为Nothing来释放内存:
appIE.Quit
Set appIE = Nothing
好吧,现在你有了自己的价值,你可以用它做任何你想做的事情:把它放进一个单元格(Range("A1").Value = myValue
),或者放到一个表格的标签(Me.label1.Text = myValue
)。
我只想指出,这不是StackOverflow的工作原理:在这里您发布有关特定编码问题的问题,但您应首先进行自己的搜索。我之所以回答一个没有展示太多研究成果的问题,只是因为我看到它多次询问,回到我学习如何做到这一点的时候,我记得我本来希望有一些更好的支持入门。所以我希望这个答案只是一个“学习输入”而不是最好/最完整的解决方案,可以为下一个遇到同样问题的用户提供支持。因为我已经学会了如何编程感谢这个社区,我想你和其他初学者可能会使用我的输入来发现编程的美丽世界。
享受你的练习;)
答案 1 :(得分:5)
提到了其他方法,因此让我们请您承认,在撰写本文时,我们处于21世纪。让我们停放 local bus 浏览器打开的窗口,并通过一个XMLHTTP GET请求(简称XHR GET) fly 。
XHR是对象形式的API,其方法可以传输数据 在Web浏览器和Web服务器之间。该对象由 浏览器的JavaScript环境
这是一种无需打开浏览器即可检索数据的快速方法。可以将服务器响应读取到HTMLDocument中,并从那里继续获取表。
在下面的代码中,表的ID为cr1
。
在帮助子WriteTable
中,我们先循环各列(td
标签),然后再循环表行(tr
标签),最后遍历每个表行的长度,表格单元格。因为我们只想要第1列和第8列中的数据,所以使用Select Case
语句指定要写到工作表的内容。
示例网页视图:
示例代码输出:
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
答案 2 :(得分:1)
您可以使用winhttprequest对象而不是Internet Explorer,因为它可以加载除了图片广告之外的数据,而不是下载包含广告n图片的完整网页,这些图片使得互联网浏览器对象比winhttpRequest对象更重要。
答案 3 :(得分:0)
很久以前就提出过这个问题。但我认为以下信息对新手有用。实际上,您可以轻松地从类名中获取值。
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
如果您不熟悉网页抓取,请阅读此博文。
还有各种从网页中提取数据的技术。本文通过示例解释其中的一些。
答案 4 :(得分:0)
我修改了一些为我弹出错误的东西,并最终得到了这个,以便根据需要提取数据:
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