You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Excel VBA Error 91问题:HTML元素为空时如何跳过执行

解决Excel VBA爬取词典时Error 91的问题

首先咱们先拆解你代码里的核心问题,这也是Error 91一直触发的原因:

  1. getElementsByClassName方法永远不会返回Nothing——它返回的是一个HTMLCollection集合对象,哪怕没有匹配到元素,集合的Length属性会是0,但对象本身依然存在。所以你用Is Nothing或IsObject做判断完全无效。
  2. 原代码里的i = i + 1逻辑完全错误:循环本身会在Next i时自动递增行号,手动加i会直接跳过大量行,而且你把判断逻辑搞反了(应该是元素不存在时跳过赋值,不是跳行)。

下面是修改后的完整代码,每部分都标注了改进点:

Sub CrawlGermanDictionary()
    Dim XMLReq As New MSXML2.XMLHTTP60
    Dim HTMLDoc As New MSHTML.HTMLDocument
    Dim i As Integer
    Dim strURL As String
    ' 提前声明元素集合变量,让代码更清晰
    Dim posElements As MSHTML.IHTMLElementCollection
    Dim meaningElements As MSHTML.IHTMLElementCollection
    Dim exampleGerElements As MSHTML.IHTMLElementCollection
    Dim exampleEngElements As MSHTML.IHTMLElementCollection
    
    ' 循环处理每行单词
    For i = 2 To 3493
        ' 拼接请求URL,加上.Value确保取到单元格文本
        strURL = "https://dictionary.cambridge.org/dictionary/german-english/" & Range("A" & i).Value
        
        ' 重置XML请求对象,避免旧请求数据残留
        Set XMLReq = New MSXML2.XMLHTTP60
        XMLReq.Open "GET", strURL, False
        XMLReq.send
        
        ' 先检查请求是否成功
        If XMLReq.Status <> 200 Then
            MsgBox "请求单词「" & Range("A" & i).Value & "」失败,状态码:" & XMLReq.Status
            ' 直接跳转到循环末尾,处理下一个单词
            GoTo NextWord
        End If
        
        HTMLDoc.body.innerHTML = XMLReq.responseText
        
        ' --- 处理词性 ---
        Set posElements = HTMLDoc.getElementsByClassName("pos dpos")
        ' 通过Length判断是否有匹配元素
        If posElements.Length > 0 Then
            Range("B" & i).Value = posElements(0).innerText
        Else
            ' 没有找到则清空单元格(可选操作)
            Range("B" & i).Value = ""
        End If
        
        ' --- 处理释义 ---
        Set meaningElements = HTMLDoc.getElementsByClassName("ddef_h")
        If meaningElements.Length > 0 Then
            Range("C" & i).Value = meaningElements(0).innerText
        Else
            Range("C" & i).Value = ""
        End If
        
        ' --- 处理德语例句 ---
        Set exampleGerElements = HTMLDoc.getElementsByClassName("eg deg")
        If exampleGerElements.Length > 0 Then
            Range("D" & i).Value = exampleGerElements(0).innerText
        Else
            Range("D" & i).Value = ""
        End If
        
        ' --- 处理英语译文 ---
        Set exampleEngElements = HTMLDoc.getElementsByClassName("trans dtrans hdb")
        If exampleEngElements.Length > 0 Then
            Range("E" & i).Value = exampleEngElements(0).innerText
        Else
            Range("E" & i).Value = ""
        End If
        
NextWord:
        ' 清理对象,避免内存泄漏
        Set posElements = Nothing
        Set meaningElements = Nothing
        Set exampleGerElements = Nothing
        Set exampleEngElements = Nothing
        Set XMLReq = Nothing
        ' 可选:加延迟防止被网站封禁,每次请求后等1秒
        ' Application.Wait Now + TimeValue("00:00:01")
        ' 可选:让Excel响应界面操作,避免假死
        ' DoEvents
    Next i
    
    MsgBox "单词爬取完成!"
End Sub

关键改进说明:

  • 正确的元素存在性判断:用HTMLCollection.Length > 0来检查是否有匹配元素,这是判断getElementsByClassName结果有效的标准方式。
  • 请求失败的优雅处理:请求出错时给出具体单词的提示,并用GoTo直接跳过当前单词,不中断整个爬取流程。
  • 对象生命周期管理:每次循环重置XML对象,结束后清空元素集合,防止内存泄漏和旧数据干扰。
  • 移除错误的行号修改:把行号递增交给循环本身处理,避免逻辑混乱。

最后给你几个实用小建议:

  1. 处理3000多行数据时,频繁操作单元格会很慢,建议先把数据存到数组里,最后一次性写入Excel,能大幅提升效率。
  2. 加上请求延迟和DoEvents,既避免被网站封禁,又能防止Excel假死。
  3. 可以给单元格加个“处理状态”列,标记哪些单词请求失败,方便后续排查。

内容的提问来源于stack exchange,提问作者momiji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 07:47:45