【问题标题】:InnerText returns empty for a specific span classInnerText 为特定的跨度类返回空
【发布时间】:2020-02-13 12:12:22
【问题描述】:

我正在尝试从this 网站检索常规 (126,37 欧元) 和减价 (101,10 欧元) 价格信息。

简化的 HTML 代码如下所示:

<div class="vw-productFeatures ">
  <ul class="feature-list -price-container">
    <li class="feature -price">
      <span class="value">126,37</span>
    </li>
  </ul>
  <ul class="feature-list vw-productVoucher">
    <li class="voucher-information">Mit Code
      <span class="voucher-reduced-price">101,10</span>
    </li>
  </ul>
</div>

所以,我基本上是一步一步来的(div类->ul类->li类->span类),最后得到innerText。

我可以得到正常的价格,但是,spanclass.innerText 的降价返回空。

这是我正在使用的代码:

Function getHTMLelemFromCol(HTMLColIn As MSHTML.IHTMLElementCollection, tagNameIn As String, classNameIn As String) As MSHTML.IHTMLElement
    Dim HTMLitem As MSHTML.IHTMLElement

    For Each HTMLitem In HTMLColIn
        If (HTMLitem.tagName = tagNameIn) Then
            If (HTMLitem.className = classNameIn) Then
                Set getHTMLelemFromCol = HTMLitem
                Exit For
            End If
        End If
    Next HTMLitem
End Function
Function getPrice(webSite As String, divClass As String, ulClass As String, liClass As String, spanClass As String) As String
    Dim XMLPage As New msxml2.XMLHTTP60
    Dim HTMLDoc As New MSHTML.HTMLDocument
    Dim HTMLitem As MSHTML.IHTMLElement
    Dim HTMLObjCol As MSHTML.IHTMLElementCollection

    XMLPage.Open "GET", webSite, False
    XMLPage.send
    HTMLDoc.body.innerHTML = XMLPage.responseText

    Set HTMLObjCol = HTMLDoc.getElementsByClassName(divClass)
    Set HTMLitem = getHTMLelemFromCol(HTMLObjCol, "DIV", divClass)          ' Find the div class we are interested in first
    Set HTMLitem = getHTMLelemFromCol(HTMLitem.Children, "UL", ulClass)     ' Find the ul class we are interested in
    Set HTMLitem = getHTMLelemFromCol(HTMLitem.Children, "LI", liClass)     ' Find the li class we are interested in
    Set HTMLitem = getHTMLelemFromCol(HTMLitem.Children, "SPAN", spanClass) ' Find the span class we are interested in

    getPrice = HTMLitem.innerText
End Function
Sub Run()
    Dim webSite As String, divClass As String, ulClass As String, liClass As String, spanClass As String, regularPrice As String, reducedPrice As String

    webSite = "https://www.rakuten.de/produkt/msi-b450-tomahawk-max-atx-mainboard-4x-ddr4-max-64gb-1x-dvi-d-1x-hdmi-14-1x-usb-c-31-2843843890"
    divClass = "vw-productFeatures "

    ' Get the regular price
    ulClass = "feature-list -price-container"
    liClass = "feature -price"
    spanClass = "value"
    regularPrice = getPrice(webSite, divClass, ulClass, liClass, spanClass)

    ' Get the reduced price
    ulClass = "feature-list vw-productVoucher -hide"
    liClass = "voucher-information"
    spanClass = "voucher-reduced-price"
    reducedPrice = getPrice(webSite, divClass, ulClass, liClass, spanClass)

    Debug.Print "Regular price: " & regularPrice
    Debug.Print "Reduced price: " & reducedPrice
End Sub

我得到的输出:

Regular price: 126,37
Reduced price: 

调试器显示它能够找到正确的跨度类,但它没有任何具有价格信息的属性(包括innerText)。

如何获取降价信息?

【问题讨论】:

  • 我不是这方面的专家,但我认为没有理由将 -hide 包含在您的 ulClass 变量中。似乎这会导致它不匹配任何东西。
  • 实际上,当我“检查”时,ul class 似乎是feature-list vw-productVoucher。但是,那时没有比赛。当我查看页面源时,搜索feature-list vw-productVoucher,我可以看到它是feature-list vw-productVoucher -hide

标签: excel vba web-scraping


【解决方案1】:

有时当页面的大部分内容依赖于 API 调用时,使用浏览器自动化会更容易。

从性能的角度来看,这并不理想,但可以更快地投入使用,并且可以在紧要关头工作。另一种方法是监控您和服务器之间的网络流量,看看您是否可以模拟网络请求以降低价格。这会更快,但可能需要一些时间来弄清楚它是如何工作的。

每种方法都需要权衡取舍。下面是一些 Internet Explorer 自动化代码,它可以帮助我检索我相信您所追求的数据。

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub GetReducedPrice()
    Dim text As String

    With CreateObject("internetexplorer.application")
        .navigate "https://www.rakuten.de/produkt/msi-b450-tomahawk-max-atx-mainboard-4x-ddr4-max-64gb-1x-dvi-d-1x-hdmi-14-1x-usb-c-31-2843843890"
         Do While .Busy And .readyState <> 4: DoEvents: Loop
         Sleep 1000 ' wait a little bit too
         text = .document.querySelector(".voucher-reduced-price").innerText
        .Quit
    End With

    Debug.Print "the reduced price is: " & text
End Sub

结果是:

the reduced price is: 101,10

【讨论】:

    【解决方案2】:

    没有-hide类降价:

    ulClass = "feature-list vw-productVoucher"
    

    您可以使用简单的选择器通过querySelector (example) 获取两个价格,而不是使用具有不必要迭代的复杂方法。

    regularPrice = HTMLDoc.querySelector(".-price .value").innerText
    reducedPrice = HTMLDoc.querySelector(".voucher-reduced-price").innerText
    

    更新: Vaucher 在这里是https://tags.tiqcdn.com/utag/rakuten/main/prod/utag.js,是根据product_shop_id 和日期计算得出的。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-26
    • 1970-01-01
    • 2018-03-30
    相关资源
    最近更新 更多