将同一个 Http 从 sub 传递到函数后无法重用

Trouble reusing the same Http after passing it from a sub to a function

我已经使用 xhr 编写了一个脚本来从这个 website 中解析第一个 post 的 link 然后传递 linkhttp 到函数以从其内页获取标题。 重要的是我将 linkhttp 都传递给函数,以便重用我最初使用的相同 http.

我的脚本似乎以正确的方式工作,但我不确定我是否以正确的方式完成了整个事情。我困惑的原因是我在使用 like getHTTP(ByVal Http, ByVal link) As Variant 时得到了结果。当我选择 getHTTP(ByVal Http, ByVal link) As StringgetHTTP(ByVal Http, ByVal link) 时,我什至得到了结果。此外,我没有在函数参数中明确定义 link as StringHttp as XMLHTTP60

我试过(工作完美):

Function getHTTP(ByVal Http, ByVal link) As Variant
    Dim Html As New HTMLDocument, oTitle$
    
    With Http
        .Open "GET", link, False
        .send
        Html.body.innerHTML = .responseText
        oTitle = Html.querySelector("h1[itemprop='name'] > a").innerText
        getHTTP = oTitle
    End With
End Function

Sub GetInfo()
    Const base$ = "https://whosebug.com"
    Const Url$ = "https://whosebug.com/questions/tagged/web-scraping"
    Dim Http As New XMLHTTP60, Html As New HTMLDocument
    Dim firstLink$, postTitle$

    With Http
        .Open "GET", Url, False
        .send
        Html.body.innerHTML = .responseText
        firstLink = base & Replace(Html.querySelector(".summary .question-hyperlink").getAttribute("href"), "about:", "")
        postTitle = getHTTP(Http, firstLink)
        MsgBox postTitle
    End With
End Sub

What is the right way to pass http between sub and function in order to reuse the same http?

像这样的东西可能是合适的:

Sub GetInfo()

    Const base As String = "https://whosebug.com"
    Const url As String = "https://whosebug.com/questions/tagged/web-scraping"
    Dim Html As HTMLDocument
    Dim firstLink As String, postTitle As String

    firstLink = base & Replace(GetPage(url).querySelector(".summary .question-hyperlink") _
                .getAttribute("href"), "about:", "")
    Debug.Print firstLink

    postTitle = GetPage(firstLink).querySelector("h1[itemprop='name'] > a").innerText
    Debug.Print postTitle

End Sub

Function GetPage(url As String) As HTMLDocument
    Dim Html As HTMLDocument
    Static Http As XMLHTTP60

    If Http Is Nothing Then
        Set Http = New XMLHTTP60
        'log in here
    End If

    With Http
        .Open "GET", url, False
        .send
        If .Status = 200 Then
            Set Html = New HTMLDocument
            Html.body.innerHTML = .responseText
        Else
            Debug.Print .Status
            'warn user
        End If
    End With
    Set GetPage = Html
End Function

以上假设 "happy path" 所以可能会受益于一些异常处理...

像下面这样的东西应该可以实现你想要实现的目标:

Function getHTTP(ByVal Http, link) As String
    With Http
        .Open "GET", link, False
        .send
        getHTTP = .responseText
    End With
End Function

Sub GetInfo()
    Const base$ = "https://whosebug.com"
    Const Url$ = "https://whosebug.com/questions/tagged/web-scraping"
    Dim Http As Object, Html As New HTMLDocument
    Dim firstLink$
    
    Set Http = CreateObject("MSXML2.XMLHTTP")

    Html.body.innerHTML = getHTTP(Http, Url)
    firstLink = base & Replace(Html.querySelector(".summary .question-hyperlink").getAttribute("href"), "about:", "")
    
    Html.body.innerHTML = getHTTP(Http, firstLink)
    MsgBox Html.querySelector("h1[itemprop='name'] > a").innerText
End Sub

如果我正确理解了您的问题,并且您需要对函数中的 http 实例进行更改以传递给您的调用子程序,那么传递 http ByRef 就足够了。传递变量 ByRef 会将函数中对 http 实例所做的更改传递给子函数,以便在函数外部使用。所以在函数中对http所做的修改会传递给sub,不会丢失。您将在这两个地方使用相同的 http 对象实例。传递 http ByVal 不会将函数中对 http 所做的更改传递给 sub。如下更改您的函数参数声明。

    Function getHTTP(ByRef Http, ByVal link) As Variant