【问题标题】:How to extract yahoo-finance analyst price targets by VBA?如何通过 VBA 提取 yahoo-finance 分析师价格目标?
【发布时间】:2022-01-16 16:27:13
【问题描述】:

我正在尝试通过 VBA 提取 yahoo-finance 分析师价格目标(例如:分析师数量、高、低、平均、当前)

但我无法通过 .getelementsbyclassname/.getelementbyID 提取其中任何一个。

这是我的代码:

Sub Analysis_import()

Dim website As String

Dim request As Object

Dim response As String

Dim html As New HTMLDocument

Dim price As Variant

website = "https://finance.yahoo.com/quote/AAPL/analysis?p=AAPL"

Set request = CreateObject("MSXML2.XMLHTTP")

request.Open "get", website, False

request.setRequestHeader "If-Modified-since", "Sat, 1 Jan 2000 00:00:00 GMT"

request.send

response = StrConv(request.responseBody, vbUnicode)

html.body.innerHTML = response

price = html.getElementsByClassName("Fz(m) D(ib) Td(inh)").innerText

Debug.Print price

End Sub

有什么问题?非常感谢!

【问题讨论】:

    标签: vba web-scraping yahoo-finance


    【解决方案1】:

    您希望从该站点获取的字段是动态生成的,因此您无法使用HTMLDocument 解析器获取它们。如果您想使用tagidclass 等定位字段,您的选项将是IESelenium

    但是,好消息是原始 json 内容中的某些脚本标记中提供了必填字段。因此,即使您坚持使用xmlhttp 请求,您也可以使用vba json converter 或正则表达式来处理它们。以下脚本基于正则表达式。

    Sub GrabAnalysisInfo()
        Const Url As String = "https://finance.yahoo.com/quote/AAPL/analysis?p=AAPL"
        Dim sResp$, sHigh$, currentPrice$
        Dim analystNum$, sLow$, tMeanprice$
    
        With CreateObject("MSXML2.XMLHTTP")
            .Open "GET", Url, False
            .setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36"
            .send
            sResp = .responseText
        End With
    
        With CreateObject("VBScript.RegExp")
            .Pattern = "numberOfAnalystOpinions[\s\S]+?raw"":(.*?),"
            If .Execute(sResp).count > 0 Then
                analystNum = .Execute(sResp)(0).SubMatches(0)
            End If
    
            .Pattern = "targetMeanPrice[\s\S]+?raw"":(.*?),"
            If .Execute(sResp).count > 0 Then
                tMeanprice = .Execute(sResp)(0).SubMatches(0)
            End If
    
            .Pattern = "targetHighPrice[\s\S]+?raw"":(.*?),"
            If .Execute(sResp).count > 0 Then
                sHigh = .Execute(sResp)(0).SubMatches(0)
            End If
    
            .Pattern = "targetLowPrice[\s\S]+?raw"":(.*?),"
            If .Execute(sResp).count > 0 Then
                sLow = .Execute(sResp)(0).SubMatches(0)
            End If
    
            .Pattern = "currentPrice[\s\S]+?raw"":(.*?),"
            If .Execute(sResp).count > 0 Then
                currentPrice = .Execute(sResp)(0).SubMatches(0)
            End If
        End With
    
        Debug.Print analystNum, tMeanprice, sHigh, sLow, currentPrice
    End Sub
    

    【讨论】:

    • 选择If .Execute(sResp).count > 0 而不是.test 是否有部分原因,因为我想后者会稍微快一些。
    • 嗨@QHarr,我使用了.count 属性,因为我认为它可以帮助脚本避免索引错误,以防缺少任何所需的字段。顺便说一下你推荐的那个我不熟悉。
    • 我认为.test 更快,在这种情况下,您只需要参加第一场比赛。但是,在这种少量访问情况下,速度差异可能可以忽略不计。但是,我没有对此的引用。它是基于在简单地测试存在而不是存在多少次时开销较小的假设。
    • 再次感谢您的帮助。该代码直到今天仍然有效。弹出错误消息“访问被拒绝”。我能做什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-28
    • 2021-10-30
    • 2021-12-20
    相关资源
    最近更新 更多