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

VBA获取谷歌搜索首条URL时出现Run Time Error '91'错误如何解决

问题根因
  • 核心原因是谷歌搜索结果页的DOM结构近期发生了调整,原有定位元素id="rso"要么已被移除、要么结构层级变化,导致doc.getElementById("rso")返回Nothing,后续调用方法直接触发91错误
  • 次要原因:MSXML2.XMLHTTP请求无浏览器头标识,极容易被谷歌反爬机制拦截,返回人机验证页面而非正常搜索结果,同样不存在rso元素
  • 原有代码未做非空校验,只要元素获取失败就直接抛出错误
修复后的可用代码

使用前先在VBA编辑器的「工具-引用」里勾选Microsoft HTML Object Library和Microsoft XML, v6.0:

Sub GetGoogleFirstLink()
    Dim doc As HTMLDocument
    Set doc = New HTMLDocument
    
    Dim lastrow As Long
    Dim ecoll As Object
    Dim link As Object
    Dim t As Date
    Dim reqObj As MSXML2.XMLHTTP60
    Dim searchUrl As String
    
    lastrow = Range("A" & Rows.Count).End(xlUp).Row
    t = Now()
    
    Set reqObj = New MSXML2.XMLHTTP60
        
    For i = 2 To lastrow
        ' 对关键词做URL编码,避免特殊字符导致请求异常
        searchUrl = "https://www.google.co.in/search?q=" & WorksheetFunction.EncodeURL(Cells(i, 1).Value) & "&rnd=" & WorksheetFunction.RandBetween(1, 10000)
        
        reqObj.Open "GET", searchUrl, False
        ' 添加浏览器UA头,降低被反爬拦截的概率
        reqObj.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
        reqObj.send
        
        doc.body.innerHTML = reqObj.responseText
        
        ' 先校验rso元素是否存在,不存在直接跳过避免报错
        Set ecoll = doc.getElementById("rso")
        If Not ecoll Is Nothing Then
            ' 适配谷歌最新DOM结构,定位搜索结果第一条的有效跳转链接
            Set link = ecoll.querySelector("div[jsname] a")
            If Not link Is Nothing Then
                ' 清理谷歌跳转前缀,提取真实目标URL并解码
                Cells(i, 2) = Split(link.href, "&url=")(1)
                Cells(i, 2) = Split(Cells(i, 2), "&ved=")(0)
                Cells(i, 2) = WorksheetFunction.DecodeURL(Cells(i, 2))
            Else
                Cells(i, 2) = "未找到匹配链接"
            End If
        Else
            Cells(i, 2) = "请求被拦截/无搜索结果"
        End If
        ' 加1秒延迟,避免请求过快被封IP
        Application.Wait Now() + TimeValue("00:00:01")
    Next
    
    Set doc = Nothing
    Set reqObj = Nothing
    
    Debug.Print "done" & "Time taken : " & Format(Now() - t, "hh:mm:ss")
    MsgBox "耗时 - " & Format(Now() - t, "hh:mm:ss")
End Sub
可选替代方案
  • 方案1:使用谷歌官方自定义搜索API,申请免费密钥后调用接口,完全不存在反爬和DOM结构变动问题,返回结构化JSON可直接提取第一条链接,免费额度为每天100次查询,足够个人日常使用
  • 方案2:换用Selenium模拟真实浏览器操作,完全模拟真人搜索行为,反爬抗性更强,适合查询量较大的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:06:02