爬取cbi.ir页面表格返回空内容的Python爬虫代码修改求助
问题原因
- 硬编码动态参数:你代码里写死的
__VIEWSTATE、Cookie值都是服务器临时生成的,有效期极短,复制后很快失效,提交失效参数服务器不会返回对应年份的渲染结果 - 缺失必填校验字段:ASP.NET WebForm框架默认会校验
__EVENTVALIDATION字段,你手动组装的参数里漏掉了这个字段,服务器会直接判定请求非法,返回默认页面而非目标数据 - 请求逻辑错误:这类表单交互必须先发起GET请求获取初始页面,从当前会话的页面中实时提取所有动态表单参数,再组装POST请求提交,不能跳过初始请求直接硬编码参数提交
- 错误写死Content-Length:requests会自动根据提交的表单数据计算正确的Content-Length值,你手动写死的固定长度和实际提交的数据长度不匹配,会导致服务器解析请求失败
- 会话不连续:你没有维持请求会话,单独复制的TSPD反爬Cookie和请求上下文不绑定,会被网站反爬规则拦截
修改后代码
import requests from bs4 import BeautifulSoup url = "https://www.cbi.ir/PolicyRates/policyrates_fa.aspx" target_year = "1400" # 初始化会话,自动维护Cookie session = requests.Session() # 配置请求头,去掉硬编码的Content-Length和手动Cookie,补充真实UA和Referer session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'fa-IR,fa;q=0.9,en-US;q=0.8,en;q=0.7', 'Referer': url, 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1' }) # 第一步:GET请求获取初始页面,提取动态生成的表单隐藏字段 init_resp = session.get(url, verify=False) init_resp.encoding = 'utf-8' init_soup = BeautifulSoup(init_resp.text, 'html.parser') # 自动提取所有隐藏表单字段,避免遗漏__EVENTVALIDATION等必填参数 form_data = {} for hidden_input in init_soup.find_all('input', type='hidden'): input_name = hidden_input.get('name') input_value = hidden_input.get('value', '') if input_name: form_data[input_name] = input_value # 补充下拉框触发的POST参数 form_data['__EVENTTARGET'] = 'ctl00$ucBody$ucContent$ctl00$ddlYear' form_data['__EVENTARGUMENT'] = '' form_data['ctl00$ucBody$ucContent$ctl00$ddlYear'] = target_year # 第二步:提交POST请求,获取选中年份的页面数据 resp = session.post(url, data=form_data, verify=False) resp.encoding = 'utf-8' soup = BeautifulSoup(resp.text, 'html.parser') # 解析目标内容 table = soup.find("table", attrs={"class":"table table-hover table-responsive table-condensed table-bordered table-striped"}) div = soup.find("div", attrs={"id":"ctl00_ucBody_ucContent_ctl00_divRates"}) print(resp.status_code) print("目标div是否找到:", div is not None) print("目标表格是否找到:", table is not None) # 提取表格内容 if table: for row in table.find_all('tr'): cells = [cell.get_text(strip=True) for cell in row.find_all(['th', 'td'])] print(cells)
关键说明
- 用
requests.Session()维持完整会话,自动处理Cookie的生成、传递和更新,不需要手动复制Cookie值 - 自动遍历提取页面中所有type为hidden的input字段,避免遗漏任何框架要求的动态校验参数,不需要手动硬编码
__VIEWSTATE、__VIEWSTATEGENERATOR、__EVENTVALIDATION这类动态值 - 补充了真实浏览器的User-Agent和Referer请求头,模拟正常用户的访问行为,降低被反爬拦截的概率
- 移除了手动写死的Content-Length头,交由requests自动计算匹配,避免参数长度不匹配的问题
- 指定了响应编码为utf-8,避免波斯语内容乱码
- 如果需要切换查询年份,只需要修改
target_year变量的值即可,不需要改动其他参数逻辑
内容的提问来源于stack exchange,提问作者yasharov
相关产品推荐
相关产品推荐

