正确构造带文件上传的 multipart/form-data 请求需用 requests.Session() 管理 Cookie,data 传文本字段、files 传文件元组,由 requests 自动设 boundary 和 Content-Type;CSRF Token 需先 GET 提取再即时使用。

怎么构造带文件上传的 multipart/form-data POST 请求
直接用 requests.post(url, data=...) 会失败——它默认发 application/x-www-form-urlencoded,而含文件的表单必须是 multipart/form-data,且边界(boundary)要由 requests 自动管理。
正确做法是把普通字段和文件字段分开传:data 放纯文本字段,files 放文件字段。requests 会自动拼接 boundary、设置正确的 Content-Type 头。
- 普通字段如
username、csrf_token写进data字典(值是字符串) - 文件字段如
avatar必须写进files字典,值为元组:('filename.jpg', open('path.jpg', 'rb'), 'image/jpeg') - 别手动设
Content-Type头,否则 requests 会跳过自动 boundary 生成,导致服务端解析失败 - 文件句柄记得用
with打开,或确保close();requests 不会帮你关
如何处理带 CSRF Token 的表单提交
很多网站在 form 里藏了隐藏字段(如 )——这个值不是固定的,得先 GET 页面,用正则或 BeautifulSoup 提取出来,再塞进 POST 数据里。
漏掉或复用旧 token 是 403 或 422 错误的常见原因,尤其在登录、评论等操作中。
- 用
requests.get(url)获取页面 HTML - 用
re.search(r'name="csrf_token"\s+value="([^"]+)"', html_text)或soup.find('input', {'name': 'csrf_token'})['value']提取 - 提取后立刻用于下一次 POST,不要缓存超过 1 分钟(token 通常有时效)
- 有些站点用
X-CSRFToken请求头传 token,此时要把值从Set-Cookie或响应 body 中提取,再加到headers里
POST 请求里该用 data 还是 json 参数
看目标接口文档或浏览器开发者工具里的「Headers」→「Request Payload」。格式不对,服务端根本收不到字段。
- 表单提交(
Content-Type: application/x-www-form-urlencoded)→ 用data=dict(...),requests 会自动编码成a=1&b=2 - API 接口(
Content-Type: application/json)→ 用json=dict(...),requests 自动序列化 + 设 header - 混用
data和json会导致冲突,requests 会报错或静默忽略其中一个 - 如果必须发 JSON 但服务端不认
application/json头(比如某些老系统),就手动用data=json.dumps(...)+headers={'Content-Type': 'application/json'}
为什么用 Session 而不是反复 new requests
因为 Cookie(尤其是 sessionid、login_token)要自动携带,否则每次 POST 都算未登录状态。单独调 requests.post 不保留 cookie,等于每次都开新隐身窗口。
- 统一用
s = requests.Session(),后续所有s.get()/s.post()共享 cookie - 登录成功后,后续请求不用再传 cookie,Session 自动附带
- 注意有些网站用 JavaScript 动态写 cookie,requests 拿不到——这时得切 selenium 或分析 JS 逻辑模拟生成
- Session 对象本身不自动处理 redirect 后的 cookie 更新,但默认
allow_redirects=True已覆盖大部分场景
实际跑通的关键往往不在 POST 本身,而在前序动作是否拿到最新 token、cookie 是否持续有效、以及 multipart 边界有没有被手动破坏。这些点一错,服务端连日志都可能不记——它根本没解析到字段。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











