使用VBA从一组<li>标记内的<span>标记获取特定文本的首次出现

时间:2018-12-28 17:09:00

标签: excel vba web-scraping

我有一个webpage的网页抓取内容,该产品的价格优先提供,且卖家的名字更便宜。

我需要让第一位卖家在一组卖家中拥有商品“可用”

卖家列表的显示方式如下

<li class="card js-product-card"
  data-shopid="336"
  data-shop-review-score="4.5"
  data-shop-reviews-count="265">

<div class="shop cf">
  <a title="Supplier1" class="shop-logo js-shop-logo" href="/m/336/Supplier1"></a>
</div>

<div class="description">
    <div class="item js-product" data-product-id="35583015">
      <h3>
        <a title="Τροφοδοτικό (PSU) Thermaltake Smart RGB 700W" </a>
      </h3>
      <p class="availability">
        <span class="availability instock">Not Available</span>
      </p>
    </div>
</div>
<div class="price" >
  <div class="js-blp pre-blp content-placeholder">
    <a title="Δες το στο κατάστημα" rel="nofollow" class="product-link js-product-link content-placeholder" href="/products/show/35289523">63,00€</a>
  </div>

</div>
</li>

<li class="card js-product-card"
  data-shopid="336"
  data-shop-review-score="4.5"
  data-shop-reviews-count="265">

<div class="shop cf">
  <a title="Supplier1" class="shop-logo js-shop-logo" href="/m/336/Supplier1"></a>
</div>

<div class="description">
    <div class="item js-product" data-product-id="35583015">
      <h3>
        <a title="Τροφοδοτικό (PSU) Thermaltake Smart RGB 700W" </a>
      </h3>
      <p class="availability">
        <span class="availability instock">Available</span>
      </p>
    </div>
</div>

<div class="price" >
  <div class="js-blp pre-blp content-placeholder">
    <a title="Δες το στο κατάστημα" rel="nofollow" class="product-link js-product-link content-placeholder" href="/products/show/35289523">68,00€</a>
  </div>
</div>
</li>

<li class="card js-product-card"
  data-shopid="338"
  data-shop-review-score="3"
  data-shop-reviews-count="135">

<div class="shop cf">
  <a title="Supplier3" class="shop-logo js-shop-logo" href="/m/336/Supplier3"></a>
</div>

<div class="description">
    <div class="item js-product" data-product-id="37583015">
      <h3>
        <a title="Τροφοδοτικό (PSU) Thermaltake Smart RGB 700W" </a>
      </h3>
      <p class="availability">
        <span class="availability instock">Available in 1-3 Days</span>
      </p>
    </div>
</div>
<div class="price" >
  <div class="js-blp pre-blp content-placeholder">
    <a title="Δες το στο κατάστημα" rel="nofollow" class="product-link js-product-link content-placeholder" href="/products/show/35289523">69,00€</a>
  </div>
</div>
</li>

我需要获取标签的标题,即卖家的名字 和文本 Available (可用)以及 price

2 个答案:

答案 0 :(得分:1)

我去了那个URL,对我来说是希腊文!抱歉。无法抗拒。但是,即使在Google翻译之后,“ available”一词仍然没有出现在任何地方。

但是,对您的问题的第一个评论是一个合理的答案-基本上要求从头开始编写代码不是该服务旨在解决的问题。

一般来说,Excel可以“网页抓取”,并且可以搜索字符串。如果您从未做过(您没有说过),那么在使用VBA进行编程操作之前,至少要手动执行一次非常重要。

很明显,不仅有说明,而且还有YouTube视频,如果需要入门,请参见如何使用Excel进行网络抓取:https://www.youtube.com/watch?v=YQbe20G0ZSM

但是,如果您是从头开始的话,那么我完全必须使用Excel进行询问。我会提到Perl用于Web客户端的工作,因为它有很多工具和样板代码,整个O'Reilly都在上面写着-并且因为我是老人(tm)。我敢肯定,这些天您可以使用Python进行相同的操作。两者都非常流行于网络抓取; Excel,不是很多。

也就是说,Excel与Perl的共同点是工具太多了,而且不止一种方法。

StackExchange上的此答案表明了如何使用“ Internet Explorer对象”来抓取网页:Webscraping using VBA excel

此人建议使用“ HTMLDocument”对象: Scraping the source code using VBA-Macros

...我想说的是最新技术。而且我相信甚至还有其他代码库可供使用,称为“ MSXML2.ServerXMLHTTP.6.0”。

一旦您选择了一种从网上抓取文本字符串的方法,就必须对其进行搜索。这使我们想到了要了解“正则表达式”还是“ Regexp”技术。他们有学习曲线。如果没有,则Excel具有基本的字符串搜索功能,该功能仍然可以找到所需的字符串,还有更多的VBA代码。

因此,我们将其保留在那里,直到您可以更全面地概述问题为止,这样您就不会要求回答者为您编写所有代码了。

答案 1 :(得分:1)

我将收集所有产品并将其循环,直到找到具有复合类名称availability instock的产品。提取关联的产品ID,然后将其用于定位具有相同ID的元素以收集其他信息。


XMLHTTP请求版本:

Option Explicit
Public Sub GetInfo()
    Dim i As Long, sResponse As String, html As HTMLDocument

    With CreateObject("MSXML2.XMLHTTP")
        .Open "GET", "https://www.skroutz.gr/s/12685474/Thermaltake-Smart-RGB-700W.html", False
        .setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
        .send
        sResponse = .responseText
    End With
    Stop

    Set html = New HTMLDocument
    html.body.innerHTML = sResponse

    Dim products As Object, product As Object
    Set products = html.getElementsByClassName("card js-product-card")
    Dim id As String
    For Each product In products
        If InStr(product.outerHTML, "availability instock") > 0 Then
            id = product.getAttribute("data-product-id")
            'You have the id now to use to select as everything else. Use this later
            Exit For
        End If
    Next
    'other code using product id to target for values
    If id <> vbNullString Then
        On Error Resume Next
        Debug.Print html.querySelector("[data-uservoice-pid='" & id & "']").title
        Debug.Print html.querySelector("[data-product-id='" & id & "'] p.availability").innerText
        Debug.Print html.querySelector("[data-product-id='" & id & "'] .price").innerText
        On Error GoTo 0

    End If
End Sub

浏览器版本:

Option Explicit

Public Sub GetInfo()
    Dim ie As New InternetExplorer, i As Long
    With ie
        .Visible = True
        .Navigate2 "https://www.skroutz.gr/s/12685474/Thermaltake-Smart-RGB-700W.html"

        While .Busy Or .readyState < 4: DoEvents: Wend

        Dim products As Object, product As Object
        Set products = .document.getElementsByClassName("card js-product-card")
        Dim id As String
        For Each product In products
            If product.getElementsByClassName("availability instock").Length > 0 Then
                id = product.getAttribute("data-product-id")
                'You have the id now to use to select as everything else. Use this later
                Exit For
            End If
        Next
        'other code using product id to target for values
        If id <> vbNullString Then
            On Error Resume Next
            Debug.Print .document.querySelector("[data-uservoice-pid='" & id & "']").title
            Debug.Print .document.querySelector("[data-product-id='" & id & "'] p.availability").innerText
            Debug.Print .document.querySelector("[data-product-id='" & id & "'] .price").innerText
            On Error GoTo 0

        End If
        .Quit
    End With
End Sub