Не удается выполнить мой код без "при повторном запуске"

Написание искателя в VBA в сочетании с селеном для анализа цены различных продуктов с веб-страницы, я получаю проблему после ее выполнения. Он ломается, когда он обнаруживает, что определенные цены не равны. Используя "on error resume next", я могу получить полные результаты. Однако я хочу выполнить свой код без использования "on error resume next". Если бы не селен, я мог бы использовать свойство 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

Ответ 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 и убедитесь сами.

Я оставляю вам всю интересную работу. Удачи!

Ответ 2

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

Возрастная ошибка "нулевого указателя". Важное значение имеет проверка нулей. Там есть лучший способ сделать это, но вы получите точку (каламбур)

Ответ 3

On Error Resume Next просто пропускает любые ошибки во время выполнения - вы правы, не желая применять это вообще.

Если вы не можете предотвратить эти ошибки в первую очередь (например, путем тестирования для null), вы должны активировать On Error Resume Next только для той части кода, которая действительно может создавать эти ошибки и деактивировать ее сразу после с On Error Goto 0.

Внутри этих блоков On Error вы также можете явно проверить, какая ошибка произошла (и, следовательно, будет проигнорирована), используя объект Err. Таким образом, вы можете повторно собрать все ошибки, которых не ожидали, и игнорировать только те, которые вы ожидали. Опасайтесь: повышение ошибки должно выполняться за пределами блока On Error, но оставление блока будет reset объекта Err. Поэтому вам нужно будет сохранить всю необходимую информацию об ошибке в другой переменной (или переменным) для ее доступа после выхода из блока On Error.

Я боюсь, что с общим запутанным дизайном обработки ошибок, предоставляемым VBA, нет лучшего способа.