news 2026/4/23 18:57:22

Python爬虫实战:用Requests库搞定那些烦人的CSRF Token(附完整代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python爬虫实战:用Requests库搞定那些烦人的CSRF Token(附完整代码)

Python爬虫实战:破解CSRF Token的五大高阶技巧

当你用Python爬虫抓取需要登录的网站时,是不是经常遇到这种场景——明明在浏览器里能正常操作的页面,换成代码请求就总是返回403错误?打开开发者工具一看,发现每个表单提交都带着一个叫csrf_token的神秘字符串。这就是现代网站最常用的安全防护机制之一,今天我们就来彻底解决这个难题。

1. CSRF Token的运行机制与爬虫困境

CSRF(Cross-Site Request Forgery)防护的本质是让服务器能区分"真实用户操作"和"恶意伪造请求"。典型流程是这样的:

  1. 用户首次访问网站时,服务器会在响应中埋入一个随机生成的Token
  2. 这个Token可能出现在:
    • 表单的隐藏字段(如<input type="hidden" name="csrf_token" value="abc123">
    • HTTP响应头(如X-CSRF-Token: xyz789
    • 响应的JSON数据中(常见于前后端分离架构)
  3. 当用户提交表单时,必须原样带回这个Token
  4. 服务器比对Token,不一致则拒绝请求

对于爬虫开发者来说,最大的挑战在于:

# 典型错误示例 - 直接发送请求会失败 import requests response = requests.post('https://example.com/submit', data={'name': 'test'}) print(response.status_code) # 通常返回403

2. 精准定位Token的四大来源

2.1 HTML表单中的隐藏字段

最常见的情况,Token藏在表单的隐藏输入框里。我们可以用BeautifulSoup精准提取:

from bs4 import BeautifulSoup import requests session = requests.Session() login_page = session.get('https://example.com/login') soup = BeautifulSoup(login_page.text, 'html.parser') # 方法1:通过name属性定位 token = soup.find('input', {'name': 'csrf_token'}).get('value') # 方法2:通过CSS选择器定位 token = soup.select_one('input[name="csrfmiddlewaretoken"]')['value']

注意:有些网站会动态生成input的name属性,比如csrf_token_5a7b3,这时需要观察HTML规律或用正则匹配

2.2 响应头中的Token

某些RESTful API会在响应头返回Token:

profile_response = session.get('https://api.example.com/user/profile') token = profile_response.headers.get('X-CSRF-Token') # 后续请求需要带上这个Token headers = { 'X-CSRF-Token': token, 'Content-Type': 'application/json' } session.post('https://api.example.com/update', headers=headers, json=data)

2.3 异步接口返回的Token

现代前端框架经常通过AJAX获取Token:

# 先模拟获取Token的API请求 token_response = session.get('https://example.com/api/csrf_token') token = token_response.json()['token'] # 然后带着这个Token提交表单 form_data = { 'username': 'admin', 'password': 'secure123', '_token': token } session.post('https://example.com/login', data=form_data)

2.4 JavaScript动态生成的Token

最棘手的情况是Token由前端JS计算生成。这时需要:

  1. 用Selenium等工具实际渲染页面
  2. 从内存中提取Token
  3. 或者逆向分析生成算法
from selenium import webdriver driver = webdriver.Chrome() driver.get('https://example.com/login') token = driver.execute_script('return window.csrfToken;') # 或者从cookie中获取 token = driver.get_cookie('csrf_token')['value']

3. Session会话的进阶管理技巧

单纯获取Token还不够,关键在于维持会话状态。Requests库的Session对象会自动处理Cookie,但有些细节需要注意:

session = requests.Session() # 关键配置项 session.headers.update({ 'User-Agent': 'Mozilla/5.0', 'Accept-Language': 'en-US,en;q=0.9' }) # 超时设置(单位:秒) session.request = functools.partial(session.request, timeout=10) # 自动重试机制 adapter = requests.adapters.HTTPAdapter( max_retries=3, pool_connections=100, pool_maxsize=100 ) session.mount('http://', adapter) session.mount('https://', adapter)

处理Token过期的正确姿势:

def safe_request(url, method='GET', **kwargs): for _ in range(3): # 最多重试3次 try: response = session.request(method, url, **kwargs) if response.status_code == 403: refresh_token() # 重新获取Token continue return response except requests.exceptions.RequestException: time.sleep(1) raise Exception("Request failed after retries") def refresh_token(): new_token = session.get('https://example.com/new_token').json()['token'] session.headers['X-CSRF-Token'] = new_token

4. 反爬虫对抗策略解析

网站可能会用这些手段增加CSRF防护强度:

  1. Token绑定用户会话:不同用户获取的Token不同

    • 解决方案:确保先登录再获取Token
  2. Token时效性:5-10分钟自动失效

    • 解决方案:每次请求前检查Token有效期
  3. 二次验证:需要先访问特定页面才能获取有效Token

    • 解决方案:模拟完整用户流程
  4. 加密Token:Base64编码或JWT格式

    • 解决方案:可能需要解密或解析
# 处理JWT格式Token的示例 import jwt token = get_raw_token() decoded = jwt.decode(token, options={"verify_signature": False}) print(decoded) # 查看Token包含的信息

5. 实战:知乎网站登录案例分析

让我们用知乎的登录流程演示完整解决方案:

import re import requests from bs4 import BeautifulSoup session = requests.Session() session.headers = { 'User-Agent': 'Mozilla/5.0', 'Host': 'www.zhihu.com' } # 第一步:获取登录页面提取_xsrf login_page = session.get('https://www.zhihu.com/signin') match = re.search(r'name="_xsrf" value="([^"]+)"', login_page.text) _xsrf = match.group(1) if match else '' # 第二步:获取验证码(如果需要) captcha_url = 'https://www.zhihu.com/api/v3/oauth/captcha?lang=en' captcha = session.get(captcha_url).json() if captcha.get('show_captcha'): # 这里需要处理图形验证码 pass # 第三步:提交登录(带_xsrf) login_api = 'https://www.zhihu.com/api/v3/oauth/sign_in' form_data = { '_xsrf': _xsrf, 'username': 'your_email', 'password': 'your_password', 'captcha': captcha.get('img_base64', '') } response = session.post(login_api, data=form_data) print(response.json())

常见问题排查表:

现象可能原因解决方案
403错误Token缺失或过期检查获取Token的流程
400错误Token格式错误确认是否需要进行URL编码
重复跳登录会话丢失确保使用同一个Session对象
验证码触发请求频率过高添加随机延迟,模拟人工操作

最后分享一个真实项目中的经验:某电商网站的Token竟然藏在页面某个<script>标签的JSON数据里,花了两天才发现这个隐藏位置。所以当常规方法失效时,不妨试试:

# 暴力搜索整个页面的Token模式 def find_hidden_token(html): patterns = [ r'csrfToken:\s*["\']([^"\']+)["\']', r'window\.csrf\s*=\s*["\']([^"\']+)["\']', r'&csrf_token=([^&]+)' ] for pattern in patterns: match = re.search(pattern, html) if match: return match.group(1) return None
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 18:50:27

FineBI核心功能实战解析:从数据建模到仪表板设计

1. 数据准备&#xff1a;从原始数据到分析模型 第一次接触FineBI时&#xff0c;最让我头疼的就是数据准备环节。记得当时接手一个零售商的销售分析项目&#xff0c;手里有来自ERP、CRM和Excel的十几张表格&#xff0c;数据格式乱七八糟。FineBI的数据准备功能简直是我的救命稻草…

作者头像 李华
网站建设 2026/4/23 18:48:31

你的 Tree Shaking 可能是“假的”?

你以为你用了 ES Module&#xff0c;就自动开启 Tree Shaking 了&#xff1f; 很遗憾&#xff0c;大多数情况下——并没有真正生效。很多项目打包后&#xff1a; 明明没用的代码还在bundle 体积异常膨胀优化了半天效果不明显 问题很可能出在一个你没注意的地方&#xff1a; pac…

作者头像 李华
网站建设 2026/4/23 18:48:04

DHT11、DHT22、AM2302怎么选?一篇讲透温湿度传感器选型与实战避坑

DHT11、DHT22、AM2302温湿度传感器选型指南&#xff1a;从参数对比到实战避坑 在智能家居和物联网项目中&#xff0c;温湿度传感器的选择往往决定了整个系统的数据可靠性和成本结构。面对市场上主流的DHT11、DHT22和AM2302这三款传感器&#xff0c;很多开发者都会陷入选择困境—…

作者头像 李华