Excel 如何选择web源代码中的第n个实例

Excel 如何选择web源代码中的第n个实例,excel,vba,web-scraping,Excel,Vba,Web Scraping,我正试图通过雅虎财经找到52周的价格区间,以获得一份股票报价表 网址: 我在网上和youtube上搜索过,从那里得到了很多指导。但是,当我运行代码时,它会选择数组的第一个实例,而实际上我需要第六个实例。根据我搜索的字符串——“FiftytyTwoWeekrange”,因为页面似乎也由许多其他标签组成,所以我需要的不是第一个 是否有一种方法可以指定搜索,以不拾取第一个事件,而是拾取第n个事件?谢谢你的帮助。我在YouTube上找到的代码非常有用,但我希望你们能帮我完成这个调整 Sub qTest_

我正试图通过雅虎财经找到52周的价格区间,以获得一份股票报价表

网址:

我在网上和youtube上搜索过,从那里得到了很多指导。但是,当我运行代码时,它会选择数组的第一个实例,而实际上我需要第六个实例。根据我搜索的字符串——“FiftytyTwoWeekrange”,因为页面似乎也由许多其他标签组成,所以我需要的不是第一个

是否有一种方法可以指定搜索,以不拾取第一个事件,而是拾取第n个事件?谢谢你的帮助。我在YouTube上找到的代码非常有用,但我希望你们能帮我完成这个调整

Sub qTest_3()

    Call clear_data

    Dim myrng As Range
    Dim lastrow As Long
    Dim row_count As Long
    Dim ws As Worksheet
    Set ws = Sheets("Main2")

    col_count = 2
    row_count = 2

    'Find last row
    With ws
        lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
    End With

    'set ticker range
    Set myrng = ws.Range(Cells(2, 1), Cells(lastrow, 1))

    'llop through tickers
    For Each ticker In myrng

        'Send web request
        Dim URL2 As String: URL2 = "https://finance.yahoo.com/quote/" & ticker & "?p=" & ticker & ""
        Dim Http2 As New WinHttpRequest

        Http2.Open "GET", URL2, False
        Http2.Send

        Dim s As String
        'Get source code of site
        s = Http2.ResponseText

        Dim metrics As Variant
        '**** Metric fields here
        metrics = Array("fiftyTwoWeekRange")


        'Split string here
        For Each element In metrics

            firstTerm = Chr(34) & element & Chr(34) & ":{" & Chr(34) & "raw" & Chr(34) & ":"
            secondTerm = "," & Chr(34) & "fmt" & Chr(34)

            nextPosition = 1

            On Error GoTo err_hdl

            Do Until nextPosition = 0
                startPos = InStr(nextPosition, s, firstTerm, vbTextCompare)
                stopPos = InStr(startPos, s, secondTerm, vbTextCompare)
                split_string = Mid$(s, startPos + Len(firstTerm), stopPos - startPos - Len(secondTerm))
                nextPosition = InStr(stopPos, s, firstTerm, vbTextCompare)

                Exit Do
            Loop

            On Error GoTo 0

            Dim arr() As String
            arr = Split(split_string, ",")
            metric = arr(0)

            'Output to sheet
            ws.Range(Cells(row_count, col_count), Cells(row_count, col_count)).Value = metric
            col_count = col_count + 1

getData:

        Next element

        Dim symbol As String
        symbol = ticker

        col_count = 2
        row_count = row_count + 1

    Next ticker

    MsgBox ("Done")

    Exit Sub

err_hdl:
    ws.Range(Cells(row_count, col_count), Cells(row_count, col_count)).Value = "N/A"
    Resume getData

End Sub
Sub clear_data()

    Dim ws As Worksheet
    Set ws = Sheets("Main2")
    Dim lastrow, lastcol As Long
    Dim myrng As Range

    With ws
     lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
    End With

    lastcol = ws.Cells(1, Columns.Count).End(xlToLeft).Column

    Set myrng = ws.Range(Cells(2, 2), Cells(lastrow, lastcol))

    myrng.Clear

End Sub

在我看来,这是一种奇怪的解析HTML的方法,而且效率低下

好方法:

如果在范围之后,如果将响应存储在
HTMLDocument
变量中,则可以使用
querySelector
方法
HTMLDocument
。例如,我会研究CSS选择器,作为获取您感兴趣的数据的更好方法

Option Explicit
Public Sub test()
    Dim html As HTMLDocument
    Set html = New HTMLDocument
    With CreateObject("WINHTTP.WinHTTPRequest.5.1")
        .Open "GET", "https://finance.yahoo.com/quote/AAPL?p=AAPL", False
        .send
        html.body.innerHTML = .responseText
    End With

    Debug.Print html.querySelector("[data-test=FIFTY_TWO_WK_RANGE-value]").innertext
End Sub
这将使用CSS选择器根据元素的属性将其作为目标。
[]
表示属性选择器。它与属性为
data test
的元素匹配,该属性的值为
五十二个WK\u RANGE-value


相关元素:


不太理想的方式:

一个不太理想的方法是使用Split来删除你想要的内容

Debug.Print Split(Split(Split(Http2.ResponseText, "data-test=""FIFTY_TWO_WK_RANGE-value""")(1), "<")(0), ">")(1)
Debug.Print Split(Split(Split)(Split)(Http2.ResponseText,“数据测试=”“TWO\u WK\u RANGE-value”“)(1),“”)

下面是一个更适合您的代码的版本(通常我会将范围放入一个数组中,并以更快的速度循环,但这更接近您的范围):

选项显式
公共子测试()
将html作为HTMLDocument、http作为对象、ticker作为范围
设置html=新的HTMLDocument
设置http=CreateObject(“WINHTTP.WinHTTPRequest.5.1”)
调暗最后一行的长度,myrng的范围
使用此工作簿。工作表(“Main2”)
lastRow=.Cells(.Rows.Count,“A”).End(xlUp).Row
设置myrng=.Range(“A2:A”和lastRow)
每种股票代码(以缅甸元计)
如果不是空的,那么
使用http
.打开“获取”https://finance.yahoo.com/quote/&ticker.Value&&p=“&ticker.Value,False
.发送
html.body.innerHTML=.responseText
以
出错时继续下一步
ticker.Offset(,1)=html.querySelector(“[data test=TWO\u WK\u RANGE-value]”)。innertext

'ticker.Offset(,1)=Split(Split)(Split(Split)(http.ResponseText,“数据测试=”“TWO-WK-RANGE-value”“)(1),“”)“这是一个很好的方式。您好。首先,感谢您抽出时间查看我的查询。我必须说,我对VBA相当陌生,我的努力已经达到了极限。很抱歉,但我还远没有理解您的条款等。也许我需要做更多的学习和研究,以便在提供帮助时我能够理解。我将接受请仔细阅读并尝试了解您的建议。我希望对我的代码进行一个小的添加/修改,以获得我想要的内容。再次感谢。嗨,我非常高兴帮助您理解最上面的版本。我已经给了您一个版本,您可以使用您的代码,就像底部一样。请参阅下面的desira部分有很多课程可以教我思考什么,这只是我的观点,分析HTML的低效方式。我自己刚刚完成了一个Python课程,做了同样的事情。这很有帮助。在我的原始代码中,我将插入额外的行吗?我有一个2500个标签的列表,我需要重新运行代码。t、 它是源代码中的第6个实例,而我的是第1个实例。此拆分(Split(Split)(Split(Http2.ResponseText,“data test=”“五十二个WK\u RANGE-value”“)(1),(1)返回您想要的值。根据需要使用它。
Option Explicit
Public Sub test()
    Dim html As HTMLDocument, http As Object, ticker As Range
    Set html = New HTMLDocument
    Set http = CreateObject("WINHTTP.WinHTTPRequest.5.1")

    Dim lastRow As Long, myrng As Range
    With ThisWorkbook.Worksheets("Main2")

        lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
        Set myrng = .Range("A2:A" & lastRow)

        For Each ticker In myrng
            If Not IsEmpty(ticker) Then
                With http
                    .Open "GET", "https://finance.yahoo.com/quote/" & ticker.Value & "?p=" & ticker.Value, False
                    .send
                    html.body.innerHTML = .responseText
                End With
                On Error Resume Next
                ticker.Offset(, 1) = html.querySelector("[data-test=FIFTY_TWO_WK_RANGE-value]").innertext
               'ticker.Offset(, 1) = Split(Split(Split(http.ResponseText, "data-test=""FIFTY_TWO_WK_RANGE-value""")(1), "<")(0), ">")(1)  ''<<Or this version 
                On Error GoTo 0
            End If
        Next
    End With
End Sub