【问题标题】:Using Excel VBA to scrape HTML使用 Excel VBA 抓取 HTML
【发布时间】:2015-12-04 23:02:40
【问题描述】:

我一直在尝试从网站上抓取和解析一些财务数据,以便可以使用 VBA 将数据添加到 Excel 电子表格中。我找到了几种可能的解决方案,但我似乎无法让它们适合我的参数。我的问题是我只需要表格中的一个变量(平均目标价格)。我一直无法弄清楚我做错了什么。我还将使用类似的 VBA 格式一次检查数百家公司,所以如果有更有效的方法来编写我所拥有的内容,请告诉我。

这是我目前所拥有的:

Sub ImportAnalystEst()

Dim oHtml       As HTMLDocument
Dim oElement    As IHTMLElement

Set oHtml = New HTMLDocument

With CreateObject("WINHTTP.WinHTTPRequest.5.1")
    .Open "GET", "http://www.marketwatch.com/investing/stock/aapl/analystestimates", False
    .send
    oHtml.body.innerHTML = .responseText
End With

Dim wsTarget As Worksheet
Dim i As Integer
i = 1
Set wsTarget = ActiveWorkbook.Worksheets("Sheet1")

For Each oElement In oHtml.getElementsByClassName("snapshot")
  wsTarget.Range("A" & i) = Split(oElement.Children(0).innerText, "<TD>")
  i = i + 1
Next

End Sub

这是我试图从中提取的 HTML。谁能举例说明我如何提取 146.52 的平均目标价?

<div class="analystEstimates">

<div class="block">
    <h2>Snapshot</h2>
</div>
<table class="snapshot">
    <tbody>
        <tr>
            <td class="first">Average Recommendation:</td>
            <td class="recommendation">
                Overweight
            </td>
            <td class="first column2">Average Target Price:</td>
            <td>146.52</td>
        </tr>
        <tr>
            <td class="first">Number of Ratings:</td>
            <td>

【问题讨论】:

  • 为什么不直接查看innerText 并使用正则表达式来获得您想要的值?
  • 如果您可以依赖布局,并且不必搜索“平均目标价格”,那么Split(oHtml.getElementsByClassName("snapshot").item(0).firstchild.firstchild.innerhtml,"TD")(7) 将返回:&gt;146.52&lt;/,然后您可以对其进行清理。

标签: html vba excel web-scraping


【解决方案1】:

我能够通过以下方式解决我的问题:

Sub ImportAnalystEst()
Dim oHtml       As HTMLDocument
Dim oElement    As IHTMLElement

Set oHtml = New HTMLDocument


With CreateObject("WINHTTP.WinHTTPRequest.5.1")
    .Open "GET", "http://www.marketwatch.com/investing/stock/aapl/analystestimates", False
    .send
    oHtml.body.innerHTML = .responseText
End With

Dim wsTarget As Worksheet
Dim i As Integer
i = 1
Set wsTarget = ActiveWorkbook.Worksheets("Sheet1")


For Each oElement In oHtml.getElementsByClassName("snapshot")
  wsTarget.Range("A" & i) = Split(oHtml.getElementsByClassName("snapshot").Item(0).FirstChild.FirstChild.innerHTML, "TD")(7)
  wsTarget.Range("A" & i) = Replace(wsTarget.Range("A" & i), ">", "")
  wsTarget.Range("A" & i) = Replace(wsTarget.Range("A" & i), "</", "")
  i = i + 1
Next


End Sub

【讨论】:

  • 为什么会有For Each ... Next 循环?
  • 我实际上将循环进行一系列迭代。这是我过程的下一步。我现在正在创建和排除故障。我的最终产品实际上将在 A 列中有几百个股票代码,然后将分析师估计值放在 E 列中。因此 GET 函数以及 For Each 函数必须是某种循环。您可能已经注意到上面示例中的“aapl”。那就是将根据 A 列更改的股票代码。您对更正或更有效的结构有什么建议吗?
  • 我会检查您是否可以通过一次调用从 marketwatch 获得多个报价,以获得您感兴趣的参数。我用 Fidelity 来做这件事,但我只是在寻找当前的报价和时间。
【解决方案2】:

使用CSS selector 组合将值定位为表格第二列中第一行表格单元格的位置要容易得多。 CSS 选择器是.snapshot .first.column2 + td,它使用"." 类选择器、" " 后代组合器和"+" 相邻兄弟组合器。

Option Explicit
Public Sub ImportAnalystEst()
    Dim oHtml       As HTMLDocument
    Dim oElement    As IHTMLElement

    Set oHtml = New HTMLDocument

    With CreateObject("WINHTTP.WinHTTPRequest.5.1")
        .Open "GET", "http://www.marketwatch.com/investing/stock/aapl/analystestimates", False
        .send
        oHtml.body.innerHTML = .responseText
    End With
    Debug.Print oHtml.querySelector(".snapshot .first.column2 + td").innertext
End Sub

【讨论】:

    【解决方案3】:

    这会做你想做的。

    Sub Test() Dim IE As Object
    
    Set IE = CreateObject("InternetExplorer.Application")
    With IE
        .Visible = True
        .Navigate "http://www.marketwatch.com/investing/stock/aapl/analystestimates" ' should work for any URL
        Do Until .ReadyState = 4: DoEvents: Loop
    
            x = .document.body.innertext
            y = InStr(1, x, "Average Target Price:")
            Z = Mid(x, y, 6)
    
            Range("A1").Value = Trim(Z)
    
            .Quit
        End With
    End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2021-10-10
      • 2018-03-07
      • 1970-01-01
      • 2018-01-05
      • 1970-01-01
      相关资源
      最近更新 更多