必须先get页面提取动态csrf令牌再post,使用session管理cookie,按目标框架字段名容错提取,每次提交前重新获取新令牌。

requests抓表单前必须先GET页面获取CSRF令牌
CSRF令牌不是固定值,通常藏在HTML的<input name="csrf_token">、meta标签或响应头里。直接硬编码或跳过这步,POST必然返回403或“Invalid CSRF token”错误。
实操建议:
- 用
requests.get()请求表单页,别跳过; - 用
BeautifulSoup或正则提取name为csrf_token、csrfmiddlewaretoken、_token等常见字段的value; - 注意有些站点把令牌放在
meta中,如<meta name="csrf-token" content="xxx">,需用soup.find("meta", {"name": "csrf-token"})["content"]取; - 极少数站点通过
X-CSRF-Token响应头下发,此时要读response.headers.get("X-CSRF-Token")。
POST时必须同步提交Cookie和CSRF令牌
CSRF验证依赖会话状态,requests.Session()是必须的——它自动管理Set-Cookie,确保后续请求携带正确sessionid和令牌。单独用requests.post()大概率失败。
常见错误现象:
- POST成功但返回登录页(会话丢失);
- 返回
{"error": "CSRF token mismatch"}(令牌没随Cookie一起发); - HTTP 400且响应体含
"The CSRF token is invalid."(令牌过期或未提交)。
示例关键步骤:
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
session = requests.Session()
resp = session.get("https://example.com/login")
# 提取token
soup = BeautifulSoup(resp.text, "html.parser")
token = soup.find("input", {"name": "csrf_token"})["value"]
# POST时data包含token,session自动带Cookie
session.post("https://example.com/login", data={
"username": "u",
"password": "p",
"csrf_token": token
})
不同框架的CSRF字段名差异很大,不能一概而论
Django默认用csrfmiddlewaretoken,Flask-WTF常用csrf_token,Laravel是_token,Spring Security可能叫_csrf。硬写死字段名会导致爬虫在换站后立即失效。
建议做法:
- 先人工查看目标页面源码,确认实际字段名;
- 写提取逻辑时留容错:尝试多个常见名,用
or链式取值; - 加日志打印提取到的
token和字段名,方便调试; - 避免依赖JS渲染——若令牌由AJAX注入,就得换
Playwright或Selenium,requests搞不定。
CSRF令牌有时效性,不能复用太久
很多系统要求令牌在生成后几分钟内使用,或每页刷新都会更新。缓存一个token反复提交,第二次就可能报错。
关键点:
- 每次提交表单前,都应重新GET一次页面并提取新token;
- 不要跨会话复用token(比如A用户取的token给B用户用);
- 如果目标站用“双提交cookie”模式(token同时设在Cookie和form),requests会自动带Cookie,但你仍得从HTML里取form字段值——两者缺一不可。
最易被忽略的是:页面JS可能动态修改input.value,而requests拿到的是原始HTML。这时得看network面板里真实提交的payload,再反推该从哪取值。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










