Excel VBA Error 91问题:HTML元素为空时如何跳过执行
解决Excel VBA爬取词典时Error 91的问题
首先咱们先拆解你代码里的核心问题,这也是Error 91一直触发的原因:
getElementsByClassName方法永远不会返回Nothing——它返回的是一个HTMLCollection集合对象,哪怕没有匹配到元素,集合的Length属性会是0,但对象本身依然存在。所以你用Is Nothing或IsObject做判断完全无效。- 原代码里的
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对象,结束后清空元素集合,防止内存泄漏和旧数据干扰。
- 移除错误的行号修改:把行号递增交给循环本身处理,避免逻辑混乱。
最后给你几个实用小建议:
- 处理3000多行数据时,频繁操作单元格会很慢,建议先把数据存到数组里,最后一次性写入Excel,能大幅提升效率。
- 加上请求延迟和
DoEvents,既避免被网站封禁,又能防止Excel假死。 - 可以给单元格加个“处理状态”列,标记哪些单词请求失败,方便后续排查。
内容的提问来源于stack exchange,提问作者momiji
相关产品推荐
相关产品推荐

