requests传参POST/GET爬取ASPX页面返回默认页怎么办
问题根源
这是ASP.NET WebForm架构站点的典型爬取坑,你提交的请求缺少服务端强制校验的动态表单字段,同时POST传参方式错误,导致服务端直接忽略你传入的筛选条件,返回默认页面内容:
- 这类站点所有表单提交必须携带首次访问页面时动态生成的3个隐藏域参数:
__VIEWSTATE、__VIEWSTATEGENERATOR、__EVENTVALIDATION,缺少任意一个服务端都不会处理表单内容 - 你代码中POST请求把表单参数传给了
params参数,这个参数是用来拼接URL查询字符串的,表单提交的参数应该放在请求体中,传给data参数 - 这类站点依赖会话Cookie校验,直接发起独立的GET、POST请求会因为Cookie不匹配被服务端拦截
修复方案
- 使用
requests.Session()维持会话,自动在多次请求间携带Cookie - 首次GET访问目标页面,从返回的HTML中解析出3个动态隐藏域的值
- 将动态隐藏域参数和你需要的筛选参数合并为完整的表单payload
- 用POST请求提交完整payload,注意参数传给
data参数而非params
可运行代码示例
首先安装依赖:pip install requests beautifulsoup4
import requests from bs4 import BeautifulSoup target_url = "http://164.100.47.193/Loksabha/Legislation/billintroduce.aspx" # 初始化会话,自动维持Cookie session = requests.Session() # 首次访问页面,获取动态校验字段 first_resp = session.get(target_url) soup = BeautifulSoup(first_resp.text, "html.parser") # 提取WebForm强制校验的隐藏字段 viewstate = soup.select_one('input[name="__VIEWSTATE"]')["value"] viewstate_generator = soup.select_one('input[name="__VIEWSTATEGENERATOR"]')["value"] event_validation = soup.select_one('input[name="__EVENTVALIDATION"]')["value"] # 组装完整表单参数 form_data = { # 动态校验字段 "__VIEWSTATE": viewstate, "__VIEWSTATEGENERATOR": viewstate_generator, "__EVENTVALIDATION": event_validation, # 自定义筛选条件 "ctl00$ContentPlaceHolder1$RadioBttnhouse": "both", "ctl00$ContentPlaceHolder1$RadioBttnbilltyp": "Government", "ctl00$ContentPlaceHolder1$ddlMinistry": "EXTERNAL AFFAIRS", "ctl00$ContentPlaceHolder1$ddlCategory": "Ordinary Bill", "ctl00$ContentPlaceHolder1$ddlYear1": "2000", "ctl00$ContentPlaceHolder1$ddlYear2": "2020", "ctl00$ContentPlaceHolder1$btnsbmt": "Submit" } # 提交表单,注意用data参数传表单内容 result_resp = session.post(target_url, data=form_data) print(result_resp.status_code) # result_resp.text即为筛选后包含13条法案数据的页面内容
注意:
__VIEWSTATE和__EVENTVALIDATION的值每次页面渲染都会动态变化,如果需要翻页或者调整筛选条件重新提交,必须从当前返回的页面中重新提取这两个字段的新值,不能复用旧值。
内容的提问来源于stack exchange,提问作者Abhi0908
相关产品推荐
相关产品推荐

