【问题标题】:Retrieve Data from Website with VBA Excel使用 VBA Excel 从网站检索数据
【发布时间】:2017-06-01 18:39:30
【问题描述】:

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

我想从Delphi for PN#13511996 获取描述字段,值应该是“3 Way Gray GT 150 Sealed Female Connector Assembly, Max Current 15 amps”。有人可以帮我检查网站并告诉我如何获取描述吗?

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

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    这是因为您使用来自XMLHTTPGET 请求原始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
    

    希望上面提到的解决方案能解决大家过去和未来的问题,这花了我相当多的时间去弄清楚。

    【讨论】:

    • 非常感谢您的解决方案,非常感谢您对导致问题的深刻解释。
    • 您能帮我获取相关产品吗?我试图找到它的 ID 或 ClassID,但没有一个会给我列表
    • @user7226 有时间我会查的
    • Set desc = aIE.document.getElementsByClassName("ProductDetailsBody")(0).getElementsByTagName("table")(5)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-14
    • 2020-11-16
    相关资源
    最近更新 更多