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

VBA调用GetElementById等方法抓取网页数据结果不稳定如何解决

VBA数据抓取异常问题修复

核心故障原因

  • 缺少HTTP请求校验逻辑:代码未判断请求返回状态码,也未校验响应内容完整性,网络波动、请求被网站拒绝时会拿到残缺/错误的页面内容,直接解析就会出现数据错位、缺失的问题
  • 未做反爬规避:连续30次无间隔的高频请求会触发目标网站的反爬机制,返回验证码、限流提示页而非正常数据页,导致解析结果时对时错
  • 表格结构适配错误:目标网站的单条数据拆分在2个<tr>标签中,且表头包含跨行、空白行,直接逐行写入Excel会导致数据错位,偶尔匹配正确仅为巧合
  • 请求协议不匹配:原代码使用HTTP协议请求,目标站已升级为HTTPS,跳转过程可能导致响应内容异常

修复后代码

Sub Gettab()
    Dim html As HTMLDocument
    Dim table As MSHTML.HTMLTable
    Dim sh As Worksheet
    Dim td As Object, tr As Object, r As Long, c As Long, i As Integer, retryCnt As Integer
    Dim dataRowFlag As Boolean, tempRow() As String
    
    ' 先判断工作表是否存在,避免重复创建报错
    Application.DisplayAlerts = False
    On Error Resume Next
    ThisWorkbook.Sheets("webtab").Delete
    On Error GoTo 0
    Application.DisplayAlerts = True
    Sheets.Add.Name = "webtab"
    Set sh = ThisWorkbook.Worksheets("webtab")
    
    r = 1
    dataRowFlag = False
    
    For i = 1 To 30
        retryCnt = 0
        ' 重试机制:最多重试3次
retry:
        URL = "https://www.cophieu68.vn/atbottom.php?currentPage=" & CStr(i) & "&&d=24&type=lo&lang=en"
        Set html = New HTMLDocument
        
        With CreateObject("MSXML2.XMLHTTP")
            .Open "GET", URL, False
            .SetRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
            .send
            ' 状态码校验,仅200正常返回时解析
            If .Status = 200 Then
                html.body.innerHTML = .responseText
                ' 校验是否拿到正常数据表格
                If html.getElementById("fred") Is Nothing Then
                    If retryCnt < 3 Then
                        retryCnt = retryCnt + 1
                        Application.Wait Now + TimeValue("00:00:02") ' 失败后等2秒重试
                        GoTo retry
                    Else
                        MsgBox "第" & i & "页连续3次请求失败,已跳过"
                        GoTo nextPage
                    End If
                End If
            Else
                If retryCnt < 3 Then
                    retryCnt = retryCnt + 1
                    Application.Wait Now + TimeValue("00:00:02")
                    GoTo retry
                Else
                    MsgBox "第" & i & "页连续3次请求失败,已跳过"
                    GoTo nextPage
                End If
            End If
        End With
        
        Set table = html.getElementById("fred")
        ReDim tempRow(1 To table.Rows(0).Cells.Length * 2) ' 初始化临时数组,存储拆分的两行数据
        
        For Each tr In table.getElementsByTagName("tr")
            ' 过滤无内容的空白行
            If tr.Cells.Length > 0 And Trim(tr.Cells(0).innerText) <> "" Then
                ' 处理表头:单独写第一页的表头即可,后续页面跳过表头
                If i = 1 And r <= 3 Then
                    c = 1
                    For Each td In tr.getElementsByTagName("td")
                        sh.Cells(r, c) = td.innerText
                        c = c + 1
                    Next
                    r = r + 1
                Else
                    ' 合并拆分的两行数据为一行
                    If Not dataRowFlag Then
                        ' 第一行数据存入临时数组
                        c = 1
                        For Each td In tr.getElementsByTagName("td")
                            tempRow(c) = td.innerText
                            c = c + 1
                        Next
                        dataRowFlag = True
                    Else
                        ' 第二行数据追加到临时数组,写入Excel
                        For Each td In tr.getElementsByTagName("td")
                            tempRow(c) = td.innerText
                            c = c + 1
                        Next
                        ' 写入整行数据
                        For c = 1 To UBound(tempRow)
                            If tempRow(c) <> "" Then
                                sh.Cells(r, c) = tempRow(c)
                            End If
                        Next
                        Erase tempRow
                        dataRowFlag = False
                        r = r + 1
                    End If
                End If
            End If
        Next
        
nextPage:
        ' 每次请求完间隔1秒,避免触发反爬
        Application.Wait Now + TimeValue("00:00:01")
        Set table = Nothing
        Set html = Nothing
        Set tr = Nothing
        Set td = Nothing
    Next
End Sub

运行前请确认已在VBA编辑器的「工具-引用」中勾选「Microsoft HTML Object Library」,否则会报类型定义错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 00:12:03