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

更新POST请求回调参数以获取网站后续分页数据

解决DevExpress分页回调的参数更新问题

这个网站用的是DevExpress的ASP.NET控件,分页通过Callback回调实现,不是普通表单提交,你之前的问题有两个核心错误:

  • 解析第二页响应时误用了第一页的r.content,应该用r2.content
  • 没有从回调响应里提取更新后的控件状态参数,一直复用第一页的旧参数,导致后续请求都返回第二页

具体解决步骤

  1. 正确解析回调响应
    DevExpress的Callback响应不是完整HTML,是包含脚本的片段,里面会更新控件状态。你需要从响应中提取以下更新后的参数:

    • __VIEWSTATE、__VIEWSTATEGENERATOR、__EVENTVALIDATION:仍在隐藏输入框中,但要从当前请求的响应里获取
    • vwfpbquerytitle$CallbackState:这个会在响应的<script>里通过setCallbackState方法更新,需要用正则提取
  2. 循环更新参数请求分页
    每请求完一页,就用当前响应更新所有表单参数,再生成对应页码的__CALLBACKPARAM,然后发起下一次POST请求。

修正后的代码示例

import requests
from bs4 import BeautifulSoup
import re

with requests.session() as s:
    # 第一页请求,初始化会话和参数
    r = s.get('https://apps.fpb.org.za/erms/fpbquerytitle.aspx?filmtitle=&Submit1=Search')
    soup = BeautifulSoup(r.content, 'html.parser')
    
    # 初始化表单参数
    form_data = {
        '__EVENTTARGET': '',
        '__EVENTARGUMENT': '',   
        '__VIEWSTATE': soup.find('input', id='__VIEWSTATE')['value'],
        '__VIEWSTATEGENERATOR': soup.find('input', id='__VIEWSTATEGENERATOR')['value'],
        '__EVENTVALIDATION': soup.find('input', id='__EVENTVALIDATION')['value'],
        'vwfpbquerytitle_DXKVInput': soup.find('input', id='vwfpbquerytitle_DXKVInput')['value'],
        'vwfpbquerytitle$CallbackState': soup.find('input', id='vwfpbquerytitle_CallbackState')['value'],
        'vwfpbquerytitle$DXSelInput': soup.find('input', id='vwfpbquerytitle_DXSelInput')['value'],
        'vwfpbquerytitle_DXHFPWS': soup.find('input', id='vwfpbquerytitle_DXHFPWS')['value'],
        'popupControlWS': soup.find('input', id='popupControlWS')['value'],     
        'DXScript': '1_155,1_87,1_147,1_97,1_123,1_106,1_113,1_84,1_139,1_137,1_98,1_135',
        '__CALLBACKID': 'vwfpbquerytitle',
    }
    
    # 请求第2到第5页(可按需修改页码范围)
    for page_number in range(2, 6):
        # 生成当前页的__CALLBACKPARAM
        form_data['__CALLBACKPARAM'] = f"c0:KV|777;{form_data['vwfpbquerytitle_DXKVInput']};GB|20;12|PAGERONCLICK3|PN{page_number - 1};"
        
        # 发送POST请求
        r_page = s.post('https://apps.fpb.org.za/erms/fpbquerytitle.aspx?filmtitle=&Submit1=Search', data=form_data)
        page_soup = BeautifulSoup(r_page.content, 'html.parser')
        
        # 更新VIEWSTATE等核心参数
        form_data['__VIEWSTATE'] = page_soup.find('input', id='__VIEWSTATE')['value']
        form_data['__VIEWSTATEGENERATOR'] = page_soup.find('input', id='__VIEWSTATEGENERATOR')['value']
        form_data['__EVENTVALIDATION'] = page_soup.find('input', id='__EVENTVALIDATION')['value']
        
        # 提取更新后的CallbackState(正则匹配脚本中的状态值)
        callback_state_match = re.search(r"vwfpbquerytitle\.setCallbackState\('([^']+)'\)", r_page.text)
        if callback_state_match:
            form_data['vwfpbquerytitle$CallbackState'] = callback_state_match.group(1)
        
        # 处理当前页数据(示例:提取表格行内容)
        print(f"===== 第{page_number}页数据 =====")
        rows = page_soup.select('.dxgvDataRow')
        for row in rows:
            print(row.get_text(strip=True, separator='|'))

关键说明

  • 正则提取CallbackState是核心:DevExpress在回调响应里会用脚本更新这个状态,必须替换成新值,否则服务器会判定请求无效,返回重复内容。
  • 所有状态参数(VIEWSTATE、EVENTVALIDATION、CallbackState)都要每次请求后更新,不能复用旧值。
  • __CALLBACKPARAM里的PN{page_number-1}是页码标识,你之前找到的规则是对的,只要和当前页码对应即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:53:11