【问题标题】:How to handle errors efficiently to prevent misleading results?如何有效地处理错误以防止误导结果?
【发布时间】:2018-05-16 00:48:16
【问题描述】:

我在 vba 中编写了一些代码,以针对某些网站中的某些名称查找某些身份。如果一切都按正确的顺序,代码运行良好,我的意思是如果链接有效,名称与a 标签匹配,最后正则表达式可以找到身份。如果这三个中的任何一个或所有三个都是错误搜索,则脚本将引发错误。我已经在下面的脚本中指定了错误发生的位置。

我希望各位专家为我提供有关如何处理错误并让我的脚本继续运行直到所有链接都用尽的任何解决方案。

由于我对 VBA 了解不多,所以我尝试使用 On error resume next 跳过错误。但是,当我查看结果时,结果却是一团糟。我正在粘贴一个粗略的示例,当我使用 On error resume next 时得到的结果。

Sub Identity_Finder()

    Dim http As New XMLHTTP60, html As New HTMLDocument
    Dim post As Object, link As Variant, refined_links As String
    Dim rxp As New RegExp, identity As Object

    For Each link In [{"http://spltech.in/","http://www.unifrostindia.com/","http://www.unitfrostindia.com/","http://www.greenplanet.in/"}]
        With http
            .Open "GET", link, False
            .send                    '''throws here the first error if the link is invalid
            html.body.innerHTML = .responseText
        End With

        For Each post In html.getElementsByTagName("a")
            If InStr(post.innerText, "certain_name") > 0 Then refined_links = post.href: Exit For
        Next post

        With http
            .Open "GET", refined_links, False
            .send                          ''throws another error here if no such link is found
        End With

        With rxp
            .Pattern = "some_regex"
            .Global = True
            Set identity = .Execute(http.responseText) 
        End With

        r = r + 1: Cells(r, 1) = link
        Cells(r, 2) = identity(0)    ''''throws another error here if no such identity is noticed

    Next link
End Sub

使用On error resume next 我得到了什么:

John executive
Mac lawyer
lulu lawyer
Robin lawyer 
Cathy student

预期输出:

John executive
Mac lawyer
lulu 
Robin  
Cathy student

当我使用On error resume next 时,空字段(未找到时)将被以前的值填充。我怎样才能绕过这个误导性的结果?提前致谢。

【问题讨论】:

  • 你有没有把代码一步一步地运行起来,看看逻辑在哪里?如果您通过按F8 开始您的代码,然后再次按以转到代码的下一行等等......这对于调试逻辑问题非常有用:)
  • 是的,我调试了几次,如果链接不是无效的,我找不到任何问题,名称与a 标签匹配,并且正则表达式找到了我在帖子中已经描述的身份。但是,当这三个中的任何一个与搜索不匹配并且我已经在脚本中标记了发生错误的位置时,我会收到错误消息。谢谢。

标签: vba excel error-handling web-scraping


【解决方案1】:

在VBA中error trap最有效的方法是

1) 在通过定制功能或内置编码概念或两者结合运行之前实际测试输入/结果。

2) 如果绝对需要,请使用 VBA 内置错误处理

示例 1

例如。您可以使用自定义函数包装此语句以测试 URL 是否有效。

With http
    .Open "GET", link, False
    .send                    '''throws here the first error if the link is invalid
    html.body.innerHTML = .responseText
End With

If ValidURL Then 

    With http
        .Open "GET", link, False
        .send     
         html.body.innerHTML = .responseText
    End With

End If

其中 ValidURL 是一个定义为的函数:

Function ValidURL(URL as String) as Boolean

     Dim result as Boolean
    'I don't know how you would specify a valid link in your specific case
    'but that code goes here
    'a dummy example follows
     result = Left(URL,7) = "http://"
     ValidURL = result 'True or False

End Function

示例 2

我在此声明中假设:

    With http
        .Open "GET", refined_links, False
        .send                          ''throws another error here if no such link is found
    End With

当没有找到这样的链接时,会产生一个特定的错误号(代码)。发现该号码并使用此代码绕过。

With http
    .Open "GET", refined_links, False
    On Error Resume Next
    .Send
    On Error GoTo 0
End With

If err.Number <> 9999 'replace with correct number

    'continue with regex test

End If

把它们放在一起

最后将所有这些放在一起,您可以像这样构建,最少使用 On Error Resume Next 并且没有 GoTo 语句。

For Each link In [{"http://spltech.in/","http://www.unifrostindia.com/","http://www.unitfrostindia.com/","http://www.greenplanet.in/"}]

    If ValidURL(link) Then 

        With http
            .Open "GET", link, False
            .send     
             html.body.innerHTML = .responseText
        End With

        For Each post In html.getElementsByTagName("a")
            If InStr(post.innerText, "certain_name") > 0 Then refined_links = post.href: Exit For
        Next post

        With http
            .Open "GET", refined_links, False
            On Error Resume Next
            .Send
            On Error GoTo 0
        End With

        If err.Number <> 9999 'replace with correct number

            With rxp
                .Pattern = "some_regex"
                .Global = True
                Set identity = .Execute(http.responseText) 
            End With

            'i will leave it to you on how to account for no pattern match
            r = r + 1: Cells(r, 1) = link
            Cells(r, 2) = identity(0)    ''''throws another error here if no such identity is noticed

        End If

    End If

Next link

【讨论】:

  • 如果在调用 .Send 之前无法确定链接是否有效,则可以像示例 2 中一样进行错误捕获。
  • 你的代码看起来非常漂亮。我检查完后会回复你的。非常感谢您的时间和精力@Scott Holtzman。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-29
  • 1970-01-01
  • 2012-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多