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

XMLHTTPRequest请求pb.nalog.ru始终返回404页面未找到问题

问题原因分析

  1. Fragment(哈希值)的作用: URL中的#及其后续内容是客户端片段标识符,不会被发送到服务器。浏览器加载search.html后,由页面内的JavaScript解析片段参数并发起实际的搜索API请求。
  2. XMLHTTP的错误处理: 你的代码中把片段直接拼接到URL中,XMLHTTP60错误地将#编码为%23,导致服务器收到的路径是/search.html%23t=...,这是一个不存在的资源,因此返回404。
  3. 动态内容加载: 即使你正确获取了search.html页面,搜索结果也是通过JavaScript动态加载的,XMLHTTP不会执行页面脚本,因此无法直接从返回的HTML中获取结果元素。

解决方案

步骤1:定位实际搜索API端点

使用浏览器开发者工具(Network标签)观察点击“Искать”后的网络请求,会发现页面发起了一个API调用(通常是XHR/Fetch请求),示例格式:
https://pb.nalog.ru/api/v3/search?query=9714055795&mode=all&_=1730356470622
其中:

  • query对应你输入的组织ID
  • mode=all对应片段中的mode=search-all
  • _是UTC毫秒级时间戳(和你生成的t值一致)

步骤2:修改VBA代码直接调用API

以下是修正后的代码,包含必要的请求头以模拟浏览器请求,并直接调用搜索API:

Option Explicit

Private Type SYSTEMTIME
    wYear As Integer
    wMonth As Integer
    wDayOfWeek As Integer
    wDay As Integer
    wHour As Integer
    wMinute As Integer
    wSecond As Integer
    wMilliseconds As Integer
End Type

Private Declare PtrSafe Sub GetSystemTime Lib "kernel32" (lpSystemTime As SYSTEMTIME)

Function CurrentTimeMillis() As Double
    ' 返回UTC时间戳(毫秒级,与Date.getTime()一致)
    Dim st As SYSTEMTIME
    GetSystemTime st
    Dim t_Start As Date, t_Now As Date
    t_Start = DateSerial(1970, 1, 1)
    t_Now = DateSerial(st.wYear, st.wMonth, st.wDay) + TimeSerial(st.wHour, st.wMinute, st.wSecond)
    CurrentTimeMillis = DateDiff("s", t_Start, t_Now) * 1000 + st.wMilliseconds
End Function

Public Sub FetchSearchResults()
    Dim http As New XMLHTTP60
    Dim responseText As String
    Dim curr As Double
    Dim orgId As String
    
    orgId = "9714055795" ' 替换为目标组织ID
    curr = CurrentTimeMillis()
    
    With http
        .Open "GET", "https://pb.nalog.ru/api/v3/search?query=" & orgId & "&mode=all&_=" & curr, False
        ' 添加浏览器请求头,避免被服务器拦截
        .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"
        .setRequestHeader "Referer", "https://pb.nalog.ru/"
        .setRequestHeader "Accept", "application/json, text/javascript, */*; q=0.01"
        
        .send
        
        ' 检查请求状态
        If .Status = 200 Then
            responseText = .responseText
            Debug.Print "API响应内容:" & vbCrLf & responseText
            
            ' 根据API返回格式处理结果:
            ' 1. 如果是JSON:需要使用VBA-JSON库解析(需自行导入)
            ' 2. 如果是HTML片段:加载到HTMLDocument提取元素
            Dim html As New HTMLDocument
            html.body.innerHTML = responseText
            Dim statusElements As IHTMLElementCollection
            Set statusElements = html.getElementsByClassName("pb-subject-status pb-subject-status--active")
            
            If statusElements.Length > 0 Then
                Debug.Print "找到状态元素:" & statusElements(0).innerText
            Else
                Debug.Print "未找到目标元素"
            End If
        Else
            Debug.Print "请求失败,状态码:" & .Status & ",响应:" & .responseText
        End If
    End With
End Sub

步骤3:处理API响应

  • 如果API返回JSON:需要导入VBA-JSON库来解析响应,提取所需数据。
  • 如果API返回HTML片段:直接加载到HTMLDocument中,即可通过getElementsByClassName等方法获取目标元素。

关键注意事项

  • 请求头模拟: 很多网站会拦截没有浏览器标识的请求,因此必须添加User-Agent、Referer等头信息。
  • API端点验证: 请通过浏览器开发者工具确认实际的API路径,不同网站版本可能会有变化。
  • 时间戳一致性: 确保时间戳是UTC毫秒级,与页面JavaScript使用的Date.getTime()保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 19:04:57