在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
答案 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提供的错误处理的一般混乱设计,没有更好的方法。