如果没有"就可以执行我的代码。接下来的错误恢复"

时间:2017-05-21 13:13:09

标签: vba selenium web-scraping

在VBA中编写一个爬虫与selenium结合来解析网页上不同产品的价格,我在执行时遇到问题。当它发现某些价格没有时,它会中断。使用"接下来的错误恢复"我可以得到完整的结果。但是,我希望执行我的代码而不使用"错误恢复下一步"。如果它不是硒,我可以使用Length属性来摆脱它。但是,硒并不支持这一点。希望我能在这里有任何解决方法。

Sub Redmart_scraping()
Dim driver As New ChromeDriver
Dim posts As Object, post As Object

With driver
    .get "https://redmart.com/bakery"
    Set posts = .FindElementsByCss("li.productPreview")
End With

On Error Resume Next

For Each post In posts
    i = i + 1
    Cells(i, 1) = post.FindElementByCss("span[class^=ProductPrice__price]").Text
Next post
End Sub

5 个答案:

答案 0 :(得分:1)

您可以按如下方式提取价格:

Sub Redmart_scraping()
Dim driver As New ChromeDriver
Dim posts As Object
Dim i As Long

With driver
    .get "https://redmart.com/bakery"
End With

Columns("A:A").NumberFormat = "[$$-409]#,##0.00"

For Each posts In driver.FindElementsByClass("productPreview")
    i = i + 1
    'Cells(i, 2) = posts.Text
    For Each Item In Split(posts.Text, vbLf)
        If InStr(1, Item, "$", vbTextCompare) > 0 Then
            If InStr(2, Item, "$", vbTextCompare) > 0 Then
                Cells(i, 1) = Mid(Item, 2, InStr(2, Item, "$", vbTextCompare) - 2)
            Else
                Cells(i, 1) = Right(Item, Len(Item) - 1)
            End If

       End If
    Next
Next
End Sub

请注意,posts.Text包含一个项目所需的所有信息。因此,除了价格,您还可以提取项目名称,折扣,客户评级,重量,折扣前的价格以及保证的新鲜日期。取消注释'Cells(i, 2) = posts.Text并亲眼看看。

我将剩下的有趣工作留给你。祝你好运!

答案 1 :(得分:1)

看起来,从查看已接受的答案来看,您的脚本在促销价格上失败,使用2个属性选择器和OR组合来设置原始帖子变量。这样就没有空值要处理了。 (迟来的答案-在寻找资源时碰到了这个问题!)。

Option Explicit
Public Sub Redmart_scraping()
    Dim driver As New ChromeDriver
    Dim posts As Object, post As Object, i As Long

    With driver
        .get "https://redmart.com/bakery"
        Do
        Set posts = .FindElementsByCss("li.productPreview span[class^=ProductPrice__price],span[class^=ProductPrice__promo_price]")
        Loop While posts.Count = 0
    End With

    For Each post In posts
        i = i + 1
        Cells(i, 1) = post.Text
    Next post
End Sub

答案 2 :(得分:1)

根据文档,这是 Florent B。 的建议,以避免任何索引错误并使代码一直运行到最后。

Sub ScrapePrice()
    Dim driver As New ChromeDriver, post As Object

    With driver
        .get "https://redmart.com/bakery"
        For Each post In .FindElementsByCss("li.productPreview")
            If Not post.FindElementByCss("span[class^='ProductPrice__price']", Raise:=False, timeout:=0) Is Nothing Then
                R = R + 1: Cells(R, 1) = post.FindElementByCss("span[class^='ProductPrice__price']").Text
            End If
        Next post
    End With
End Sub

答案 3 :(得分:0)

Sub Testing()
    Dim driver As New WebDriver
    Dim posts As Object, post As Object
    dim this as string, that as string

    Set driver = New WebDriver
    driver.Start "Phantomjs", "https://redmart.com"
    driver.get "/bakery"
    Set posts = driver.FindElementsByXPath("//div[@class='productDescriptionAndPrice']")
    On Error Resume Next
    For Each post In posts
        i = i + 1
        If Isnull(post.FindElementByXPath(".//h4/a").Text) = True Then
            this = ""
        Else
            this = post.FindElementByXPath(".//h4/a").Text
        End if
        Cells(i, 1) = this

        if IsNull(post.FindElementByXPath(".//span[@class='ProductPrice__price___3BmxE']").Text) = True then
            that = ""
        else
            that = post.FindElementByXPath(".//span[@class='ProductPrice__price___3BmxE']").Text
        end if
        Cells(i, 2) = that
    Next post
End Sub

古老的“空指针”令人讨厌。检查空值很重要。有很多更好的方法可以做到这一点,但你明白了(双关语)

答案 4 :(得分:0)

On Error Resume Next只是跳过任何运行时错误 - 你一般都不想应用它。

如果您无法首先阻止这些错误发生(例如,通过测试null),则应仅针对实际可以<的代码部分激活On Error Resume Next / em>创建这些错误并在On Error Goto 0之后立即停用它。

在这些On Error块的内部,您还可以使用Err对象显式测试发生了哪些错误(因此将被忽略)。通过这种方式,您可以重新提出您不期望的所有错误,并且只会忽略您期望的错误。 注意:必须在On Error块之外完成引发错误,但保留该块将重置Err对象。因此,在离开On Error块后,您必须将所有必要的错误信息保存在另一个变量(或变量)中以访问它。

我担心VBA提供的错误处理的一般混乱设计,没有更好的方法。