使用MS Excel VBA从复杂的HTML / JS提取数据

时间:2018-11-14 19:46:28

标签: html excel vba excel-vba web-scraping

简短介绍,我认为自己是没有任何丰富HTML经验的中级VBA编码器。我想使用MS Excel VBA从HTML / JS网页中提取数据。我已经花了几个小时在各个页面上测试我的代码,以及寻找培训材料,各个论坛和问答页面。

我迫切需要您的帮助。 (Office 2013,IE 11.0.96)

目标是获取某个Bloomberg网页的汇率。长期目标是在各种汇率下运行宏,并将每日汇率从系统中导出到每个工作日的excel表中,但我将处理这一部分。

我对

都很满意

(1)当前汇率(span class =“ priceText__1853e8a5”)或

(2)上一个收盘价(节class =“ dataBox opreviousclosingpriceonetradingdayago数值”)或

(3)打开率(部分class =“ dataBox openprice数字”)。

我的问题是我无法获取html代码的比率所在的部分。

Dim IE As Object
Dim div As Object, holdingsClass As Object, botoes As Object
Dim html As HTMLDocument
Set IE = CreateObject("InternetExplorer.Application")
    With IE
        .Visible = False
        .Navigate "https://www.bloomberg.com/quote/EURHKD:CUR"
        Do Until .ReadyState = 4: DoEvents: Loop
    End With

Set html = IE.document
Set div = IE.document.getElementById("leaderboard") 'works just fine, populates the objects
Set holdingsClass = IE.document.getElementsByclass("dataBox opreviousclosingpriceonetradingdayago numeric") 'i am not sure is it a class element at all
Set botoes = IE.document.getElementsByTagName("dataBox openprice numeric") 'i am not sure is it a tag name at all

    Range("a1").Value = div.textContent 'example how i would place it by using .textContent 
    Range("A2").Value = holdingsClass.textContent
    Range("A3").Value = botoes.textContent

非常感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

为什么不使用html进行挖掘,为什么不使用Bloomberg API来请求特定费率呢?

可能会更快,并且将来可以节省很多时间来做同样的事情。

请参阅我的类似项目,在该项目中,我创建了一个宏以从欧洲中央银行提取历史外汇汇率。 https://github.com/dmegaffi/VBA-GET-Requests/blob/master/FX%20-%20GET.xlsm

答案 1 :(得分:0)

如果右键单击您要使用chrome的网页元素,然后选择检查,它将显示该元素的详细信息。您也可以按f12键调出任何页面的HTML。在其他浏览器中也可以使用。

这是您要查找的元素吗? screen shot of mentioned webpage

根据上面的代码,您可以使用IE.document.getElementsByclass(“ priceText__1853e8a5”)引用此元素。 HTML中的元素可以共享类,但不能共享ID,因此,如果价格类classTextText_1853e8a5中存在另一个元素,则它将无法工作,因为它不会选择单个元素。然后,当然,您必须在元素内选择文本,因为此时您只有,并且需要在其中包含文本。 希望这可以帮助。

答案 2 :(得分:0)

要大致解决您的问题,请参见下文。

  

(1)当前汇率(span class =“ priceText__1853e8a5”)

可以将其写为以下内容的CSS查询选择器:

span.priceText__1853e8a5
  

(2)先前关闭(部分class =“ dataBox   opreviousclosesingpriceonetradingdayago数字“)

可以将其写为以下内容的CSS查询选择器:

.dataBox.opreviousclosingpriceonetradingdayago.numeric
  

(3)打开率(部分类=“ dataBox openprice数字”)

可以将其写为以下内容的CSS查询选择器:

.dataBox.openprice.numeric

它们与querySelector的{​​{1}}或querySelectorAll(如果需要多个匹配项,并且比第一个匹配项晚匹配)一起应用。

例如

HTMLDocument

如果更多地使用querySelectorAll

Debug.Print IE.document.querySelector("span.priceText__1853e8a5").innerText

在上面的代码中,将0替换为找到目标元素的相应索引。


查看该页面的实际选择器如下所示,但我认为该网站可能使用的是旧版浏览器(即Internet Explorer)不支持的ecmascript语法,或者正在尝试阻止跨域请求。

IE.document.querySelectorAll("span.priceText__1853e8a5")(0).innerText

使用Selenium Basic和Chrome可以使页面呈现得很好:

Option Explicit

Public Sub GetInfo()
    Dim IE As New InternetExplorer
    With IE
        .Visible = True
        .navigate "https://www.bloomberg.com/quote/EURHKD:CUR"

        While .Busy Or .readyState < 4: DoEvents: Wend
        With .document
            Debug.Print "Current: " & .querySelector(".priceText__1853e8a5").innerText
            Debug.Print "Prev close: " & .querySelector(".value__b93f12ea").innerText
            Debug.Print "Open: " & .querySelector(".value__b93f12ea").innerText
        End With

        .Quit
    End With
End Sub