更新POST请求回调参数以获取网站后续分页数据
解决DevExpress分页回调的参数更新问题
这个网站用的是DevExpress的ASP.NET控件,分页通过Callback回调实现,不是普通表单提交,你之前的问题有两个核心错误:
- 解析第二页响应时误用了第一页的
r.content,应该用r2.content - 没有从回调响应里提取更新后的控件状态参数,一直复用第一页的旧参数,导致后续请求都返回第二页
具体解决步骤
正确解析回调响应
DevExpress的Callback响应不是完整HTML,是包含脚本的片段,里面会更新控件状态。你需要从响应中提取以下更新后的参数:__VIEWSTATE、__VIEWSTATEGENERATOR、__EVENTVALIDATION:仍在隐藏输入框中,但要从当前请求的响应里获取vwfpbquerytitle$CallbackState:这个会在响应的<script>里通过setCallbackState方法更新,需要用正则提取
循环更新参数请求分页
每请求完一页,就用当前响应更新所有表单参数,再生成对应页码的__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
相关产品推荐
相关产品推荐

