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

VBA中使用For循环结合XMLHttpRequest出现Error 91错误求助

解决VBA爬虫中Error 91(对象未设置)的问题

看起来你遇到的Error 91是因为**querySelector没有找到匹配的元素,返回了Nothing**,然后你尝试访问它的.innerText属性就触发了错误。结合你的场景,当传入两个HTML标签时第二次迭代报错,大概率是第二个标签在目标页面中不存在,或者你的标签选择器写法有问题。另外你的代码还有几个可以优化的地方,也可能间接导致了这个问题,我来一步步帮你解决:

问题根源分析

  • 未检查querySelector的返回值:如果页面中没有匹配address_array(what_to_check)的元素,.querySelector()会返回Nothing,此时访问.innerText就会抛出Error 91。
  • 重复发送相同URL的请求:在what_to_check循环里,你每次都重新对同一个URL发送GET请求,这不仅浪费资源,还可能导致请求异常。
  • 变量初始化不规范:比如address_count没初始化为0,address_array的索引逻辑可能存在越界风险,html对象在循环内重复创建也没必要。

解决方案与优化后的代码

核心修复点

  1. 先判断元素是否存在再访问属性,避免空对象报错
  2. 同一个URL只请求一次,减少冗余请求
  3. 规范变量初始化,避免索引混乱

下面是修改后的完整代码:

Sub pArse(UserForm4_HiddenList_Text)
    Dim http As New XMLHTTP60
    Dim html As New HTMLDocument ' 移到循环外,避免重复创建对象
    Dim hero_true_Val As Integer
    Dim down_var As Integer
    Dim bill_array_redim As Variant
    Dim address_count As Integer
    Dim targetElement As Object ' 存储找到的DOM元素
    
    ' 初始化变量,避免默认值异常
    hero_true_Val = Application.WorksheetFunction.CountIf(Range("B:B"), True)
    down_var = 1
    address_count = 0
    bill_array_redim = Split(UserForm4_HiddenList_Text, Chr(10))
    
    ' 生成待检查的标签数组(使用1-based索引更贴合Excel习惯)
    ReDim address_array(1 To hero_true_Val)
    For Z = 2 To 6
        If Sheets("resource").Cells(Z, 2).Value <> "False" Then
            address_count = address_count + 1
            address_array(address_count) = Sheets("resource").Cells(Z, 1).Value
        End If
    Next Z
    
    ' 直接操作工作表,避免使用Select提升效率
    With Sheets("Sheet1")
        For url_stack = 0 To UBound(bill_array_redim)
            Dim currentUrl As String
            currentUrl = bill_array_redim(url_stack)
            .Cells(down_var, 1) = currentUrl
            
            ' 仅请求一次当前URL
            With http
                .Open "GET", currentUrl, False
                .send
                ' 等待请求完成
                Do While .readyState <> 4
                    DoEvents
                Loop
                ' 加载HTML内容到文档对象
                html.body.innerHTML = .responseText
            End With
            
            ' 循环解析每个标签
            For what_to_check = 1 To address_count
                Set targetElement = html.querySelector(address_array(what_to_check))
                ' 检查元素是否存在,避免空对象报错
                If Not targetElement Is Nothing Then
                    .Cells(down_var, 2).Value = targetElement.innerText
                Else
                    ' 找不到元素时写入提示,方便排查问题
                    .Cells(down_var, 2).Value = "元素未找到: " & address_array(what_to_check)
                End If
                down_var = down_var + 1
            Next what_to_check
        Next url_stack
    End With
    
    UserForm4.Hide
End Sub

额外建议

  • 验证CSS选择器有效性:确保resource工作表里的标签是合法的CSS选择器(比如h1、.content-class、#main-title这种格式),querySelector不支持XPATH语法。
  • 添加请求错误处理:可以加入On Error Resume Next或On Error GoTo块,捕获网络请求失败的情况(比如URL无效、网络中断)。
  • 避免硬编码行范围:For Z = 2 To 6这种硬编码的范围如果后续有修改会很麻烦,可以改成动态获取有效数据行的逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:45:25