使用VBA Excel从网站检索数据

时间:2017-06-01 18:39:30

标签: vba excel-vba excel

我理解已经回答了类似的问题,但我不确定我是否无法理解如何从其他人的答案中找到解决方案,或者我需要获取信息的网站很复杂。所以,请帮助我。

我想从Delphi for PN#13511996获取描述字段,值应为“3 Way Grey GT 150密封母连接器组件,最大电流15安培”。有人可以帮我检查网站,让我知道如何获取说明吗?

Sub GetData()
 'Added Microsoft HTML Object library to reff
 'Added Microsoft XML, v6.0 to reff
    Dim xhr As MSXML2.XMLHTTP60
    Dim doc As MSHTML.HTMLDocument
    Dim desc As String
    Set xhr = New MSXML2.XMLHTTP60
    With xhr
        .Open "GET", "http://ecat.delphi.com/feature?search=13511996", False
        .send
        If .ReadyState = 4 And .Status = 200 Then
            Set doc = New MSHTML.HTMLDocument
            doc.body.innerHTML = .responseText
        End If
    End With
    With doc
        desc = .getElementsByClassName("ProductDetail.Description").Item(0).innerText
    End With

    Debug.Print desc

End Sub

1 个答案:

答案 0 :(得分:0)

这是因为您使用GET中的XMLHTTP来请求原始HTML。如果您尝试Debug.Print doc.body.innerHTML,您会看到该表尚未生成,并且您要查找的文本根本不存在。

为了能够运行项目" 13511996"的查询,您需要一个真正的浏览器。只有这样,您才能生成表并获取DOM文档对象。请尝试以下代码:

Sub GetData()
    Dim aIE As InternetExplorer
    Dim desc As IHTMLElement
    Set aIE = New InternetExplorer
    With aIE
        .navigate "http://ecat.delphi.com/feature?search=13511996"
        .Visible = True '----> set it to false if you dont want to see the browser
    End With

    Do While (aIE.Busy Or aIE.ReadyState <> READYSTATE_COMPLETE)
        DoEvents
    Loop

    Set desc = aIE.document.getElementsByClassName("DetailAttributes")(0)

    'Debug.Print desc.innerText '---> prints the whole table data

    Debug.Print Split(desc.innerText, vbLf)(3) '----> prints the forth data in table

    Set aIE = Nothing
    Set desc = Nothing
End Sub

此外,如果您计划自动执行此代码以在多个查询的循环中运行,您可能希望使用:

Set desc = Nothing

For i = 1 To 100
    On Error Resume Next
    Set desc = aIE.document.getElementsByClassName("DetailAttributes")(0)
    If Err.Number = 91 Then
        GoTo Skip
    End If
    Exit For
Skip:
Application.Wait (Now() + TimeValue("00:00:001"))
Next i

而不是:

Set desc = aIE.document.getElementsByClassName("DetailAttributes")(0)

这是因为有时网页在完全生成其内容之前就已准备就绪。这会导致代码退出do loop并继续执行设置desc对象的下一个语句。您在设置时不会收到错误,因为代码将使用以前的DOM文档对象,并将输出您之前查询的结果,这是一个错误。没有任何错误,你的代码将循环运行直到结束,你手中将有一个完全扭曲的输出,这是浪费时间。

要解决此问题,您应事先将对象设置为nothing,并捕获错误并等待页面加载到for loop

最后但同样重要的是,如果构建您正在解析的网页的人知道他们正在做什么,他们可能会保护它免受来自同一来源的多个查询(很可能来自多个来源),这可能会导致他们的服务器崩溃,如果他们不这样做。此保护将在有限的时间内作为有限数量的查询反映给您。换句话说,例如在5分钟内发出100次请求后,网页将不会响应某段时间(例如2分钟)。

要解决此问题,您应限制请求数并等待所需时间。假设您使用i变量递增循环。然后你需要在循环结束时插入它:

If i Mod 100 = 0 Then
    Application.Wait (Now() + TimeValue("00:02:00"))
End If

我希望上面提到的解决方案可以解决每个人过去和未来的问题,这需要我花费相当多的时间来解决。