使用Python Requests模拟网页CSV下载POST请求遇报错问题
尝试用Python的requests库模拟网页https://www.bundesanzeiger.de/pub/en/nlp?2上「Download as CSV」按钮的POST请求,始终返回错误页面而非CSV文件。
按钮对应的HTML代码如下:
<form method="post" action="https://www.bundesanzeiger.de/pub/en/nlp?2-2.-top~csv~form~panel-form" id="idf2"><div id="idf2_hf_0" hidden="" class="hidden-fields"></div> <a class="btn btn-green argus-A98" target="_blank" href="https://www.bundesanzeiger.de/pub/en/nlp?2--top~csv~form~panel-form-csv~resource~link" title="Download as CSV"><span>Download as CSV</span> <i class="fas fa-file-csv"></i></a> </form>
原代码片段:
import requests url = 'https://www.bundesanzeiger.de/pub/en/nlp?2--top~csv~form~panel-form-csv~resource~link' payload = {'id': 'idf2'} r = requests.post(url, json=payload) r.content
已尝试添加User-Agent请求头,问题仍未解决,请问请求中遗漏了什么内容?
你的请求存在几个关键问题,逐一修正即可:
请求目标错误
你误用了<a>标签的href地址发送POST请求,但实际触发CSV下载的是<form>的action地址:https://www.bundesanzeiger.de/pub/en/nlp?2-2.-top~csv~form~panel-form。页面里的<a>只是前端触发表单提交的入口,实际请求需要提交到表单指定的action地址。请求格式与参数缺失
你用json=payload发送JSON格式数据,但表单提交默认是application/x-www-form-urlencoded格式,应该用data=payload参数。另外,表单内的hidden-fields容器(idf2_hf_0)通常包含JSF框架必备的校验参数(比如javax.faces.ViewState),必须先从页面源码中提取这些隐藏字段的键值对,一并加入请求参数。会话状态缺失
这类网站依赖Cookie维持会话,必须先发送GET请求访问目标页面,获取会话Cookie后再发送POST请求,否则服务器会判定为未授权请求。
修正后的示例代码:
import requests from bs4 import BeautifulSoup # 初始化会话,自动维持Cookie session = requests.Session() session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', 'Referer': 'https://www.bundesanzeiger.de/pub/en/nlp?2' }) # 先访问页面获取表单参数与Cookie page_url = 'https://www.bundesanzeiger.de/pub/en/nlp?2' response = session.get(page_url) soup = BeautifulSoup(response.text, 'html.parser') # 提取表单所有隐藏字段数据 form_data = {} form = soup.find('form', id='idf2') hidden_fields = form.find_all('input', type='hidden') for field in hidden_fields: form_data[field.get('name')] = field.get('value') # 发送POST请求到表单的action地址 post_url = form['action'] csv_response = session.post(post_url, data=form_data) # 验证并保存CSV文件 if csv_response.headers.get('Content-Type') == 'text/csv': with open('output.csv', 'wb') as f: f.write(csv_response.content) else: print("请求失败,返回内容:", csv_response.text)
- 额外注意
如果页面存在动态渲染的隐藏参数,上述方案无法获取时,可能需要用selenium工具先完整渲染页面,再提取表单参数。
内容的提问来源于stack exchange,提问作者Luke Bradley

