【笔记】Python3|爬虫请求 CSRF-Token 时如何获取Token、Token过期、处理 CSRF-Token 需要注意的问题及示例
CSRF-Token 机制是 Web 应用程序中常用的安全机制,它可以防止跨站请求伪造攻击,但会给爬虫造成一定的困扰。本文将介绍在使用 Python3 爬虫时,处理 CSRF-Token 机制需要注意的问题及示例。
文章目录
1 CSRF-Token 机制的原理
在 Web 开发中,每次发送请求时,服务器都会生成一个 CSRF-Token。当用户访问 Web 页面时,该 CSRF-Token 将被嵌入到 Web 表单、请求 URL 或 请求头 中。当用户提交表单或者发送请求时,该 CSRF-Token 将会被服务器验证,以防止跨站请求伪造攻击。
2 爬虫处理 CSRF-Token 机制的问题
由于爬虫不同于浏览器,它无法直接接收服务器生成的 CSRF-Token。因此,在使用爬虫时,我们需要解决如下问题:
- CSRF-Token 在哪生成?
- 如何将 CSRF-Token 嵌入到请求中?
3 CSRF-Token 可能存在的位置
在使用 Python3 爬虫时,针对不同类型的 CSRF-Token 有不同的获取方法。一般来说,CSRF-Token 可能位于 Web 表单、响应头或响应体中。
如果你认为 CSRF-Token 位于请求 URL 或 请求头 中,你需要找到生成 CSRF-Token 的具体请求报文或者网页元素,而不是从这个请求 URL 中直接分离 CSRF-Token。因为 CSRF-Token 会动态更新。具体来说,我们需要先分析网页或者应用程序,找到生成 CSRF-Token 的具体请求报文或者网页元素,然后从中获取 CSRF-Token。
下面,我们将分别介绍这三种情况的获取方法。
3.1 CSRF-Token 位于 Web 表单时
如果 CSRF-Token 位于 Web 表单中,我们可以使用 Beautiful Soup
库或者正则表达式来查找表单元素,然后获取 CSRF-Token。具体代码如下所示:
3.1.1 使用 Beautiful Soup 库
import requests
from bs4 import BeautifulSoup
url = 'http://example.com'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
csrf_token = soup.find('input', {'name': 'csrf_token'}).get('value')
在上面的代码中,我们使用 requests 库来发送 GET 请求,并使用 Beautiful Soup 库来查找 CSRF-Token。
其中 Beautiful Soup
库需要使用pip3安装:
pip3 install BeautifulSoup4
3.1.2 使用正则表达式
import re
import requests
url = 'http://example.com'
response = requests.get(url)
csrf_token = re.findall(r'<input.*?name="csrf_token".*?value="(.*?)".*?>', response.text)[0]
在上面的代码中,我们使用 requests 库来发送 GET 请求,并使用正则表达式来匹配 CSRF-Token。
3.2 CSRF-Token 位于 响应体 时
我们需要首先通过分析 HTML 页面或者 JavaScript 代码,找到生成 CSRF-Token 的具体请求报文。比如,假设生成 CSRF-Token 的请求报文为:
POST /api/csrf_token HTTP/1.1
Host: example.com
Content-Type: application/json
Authorization: Bearer 1234567890
{"user_id": "1234567890"}
我们可以使用 requests 库来发送该请求报文,并从响应体中获取 CSRF-Token。具体代码如下所示:
import requests
url = 'http://example.com/api/csrf_token'
headers = {
'Authorization': 'Bearer 1234567890',
'Content-Type': 'application/json'
}
data = {
'user_id': '1234567890'
}
response = requests.post(url, headers=headers, json=data)
csrf_token = response.json().get('csrf_token')
在上面的代码中,我们使用 requests 库来发送 POST 请求,并使用 response.json() 来解析响应的 JSON 数据,从而获取 CSRF-Token。
需要注意的是,由于 CSRF-Token 会动态更新,因此我们需要在每次请求时重新获取 CSRF-Token。
另外需要注意的是,有些网站在后台生成 CSRF-Token 时可能会根据不同的请求参数生成不同的 Token,这意味着您需要在发送完整的请求(包括所有参数)之后才能获取到完整的 CSRF-Token。如果在获取 CSRF-Token 时发现它不正确或已过期,您可以尝试重新请求页面并获取新的 CSRF-Token。
3.3 CSRF-Token 位于 响应头 时
CSRF-Token 除了可以存在于响应体(Response Body)之外,还可能被隐藏在请求的响应头(Response Header)中。因此,在获取 CSRF-Token 时,您还应该查看完整的响应头,以查看是否有其他的 CSRF-Token。具体代码如下所示:
import requests
url = 'http://example.com/api/csrf_token'
headers = {
'Authorization': 'Bearer 1234567890',
'Content-Type': 'application/json'
}
data = {
'user_id': '1234567890'
}
response = requests.post(url, headers=headers, json=data)
csrf_token = dict(response.headers)['Csrf-Token']
以上就是针对 CSRF-Token 存在的三个位置获取 CSRF-Token 的 两种方法。在实际爬虫过程中,我们需要根据 CSRF-Token 的具体位置来选择相应的方法来获取 CSRF-Token。
3.4 注意事项
Request 请求的构造过程往往只有以下两步:
- 首先,去网站上找一下对应的请求链接。
- 使用 requests.get或requests.post 发起请求就行。
然而,由于 CSRF-Token 往往用于判断同一个会话的合法性,因此有这种机制的时候,需要保证获取 CSRF-Token 的请求和下一个请求处于同一个会话中(会话:Session),所以需要额外使用 requests.Session
,然后将 requests.get
或 requests.post
直接替换成 Session.get
或 Session.post
。
下面是一个简单的示例:
import requests
# 创建一个 Session 对象
session = requests.Session()
# 先请求登录页面获取 csrf_token
login_url = 'http://example.com/login'
login_page = session.get(login_url).text
csrf_token = re.findall('csrf_token=(.*?)&', login_page)[0]
# 使用获取到的 csrf_token 登录
data = {
'username': 'admin',
'password': '123456',
'csrf_token': csrf_token
}
login_result = session.post(login_url, data=data)
# 在同一个 Session 下进行其他操作
data = {
'param1': 'value1',
'param2': 'value2',
'csrf_token': csrf_token
}
result = session.post('http://example.com/other_operation', data=data)
在上面的代码中,我们首先使用 session.get
获取登录页面,然后使用正则表达式获取其中的 csrf_token
,接着使用 session.post
发起登录请求,并在同一个 session
对象下进行其他操作,确保处于同一个会话中,从而绕过 CSRF-Token 的检查。
4 将 CSRF-Token 嵌入到请求中
获取 CSRF-Token 后,我们需要将它嵌入到请求中,以便服务器可以验证请求的合法性。在使用 Python3 爬虫时,需要根据具体的网址判断 CSRF-Token 的嵌入位置,嵌入位置一般在请求头或请求参数中。下面我们将介绍这两种嵌入位置应该如何嵌入。
4.1 CSRF-Token 嵌入请求头
在请求头中嵌入 CSRF-Token 的方法和普通的请求头差不多,只需要在请求头中加入 X-CSRF-Token 或者 X-XSRF-Token 等字段(根据具体网址判断字段名称),并将获取到的 CSRF-Token 作为该字段的值即可。示例代码如下:
import requests
url = 'http://example.com/submit_form'
csrf_token = '1234567890abcdef'
headers = {
'X-CSRF-Token': csrf_token,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
}
data = {
'param1': 'value1',
'param2': 'value2'
}
response = requests.post(url, headers=headers, data=data)
4.2 CSRF-Token 嵌入请求参数
在请求参数中嵌入 CSRF-Token 的方法也很简单,只需要在请求参数中加入名为 csrf_token 的字段,并将获取到的 CSRF-Token 作为该字段的值即可。示例代码如下:
import requests
url = 'http://example.com/submit_form'
csrf_token = '1234567890abcdef'
params = {
'param1': 'value1',
'param2': 'value2',
'csrf_token': csrf_token
}
response = requests.get(url, params=params)
以上代码中,如果是post请求,则需要使用requests.post(url, headers=headers, data=data)
,将 CSRF-Token 嵌入到 data
字段。
需要注意的是,不同的网站可能采用不同的嵌入位置,甚至可能采用多种嵌入方式,需要具体情况具体分析。
5 示例
下面,我们将使用 requests 库来实现一个简单的爬虫,用于获取西北工业大学的招生计划。
首先,我们需要获取西北工业大学网站的 CSRF-Token。具体代码如下所示:
import requests
import json
headers = {} # 请自行去网站上复制补全
get_token_url = "https://zsb.nwpu.edu.cn/f/ajax_get_csrfToken"
Session = requests.Session()
def get_csrf_token():
global data
update_ts()
response = Session.post(get_token_url, headers=headers, data=data)
csrf_token = json.loads(response.text)['data']
return csrf_token
在上面的代码中,我们使用 requests 库来发送 GET 请求,并使用 Beautiful Soup 库来查找 CSRF-Token。
接下来,我们需要将 CSRF-Token 添加到请求头中,并发送请求。具体代码如下所示:
headers["Csrf-Token"] = get_csrf_token()
get_zsjh_url = "https://zsb.nwpu.edu.cn/f/ajax_zsjh"
response = Session.post(get_zsjh_url, headers=headers, data=data)
print(response.text)
在上面的代码中,我们将 CSRF-Token 添加到请求头中,并使用 requests 库发送 POST 请求。由于西北工业大学的招生计划是动态生成的,因此我们需要使用 POST 请求来获取数据。
运行上面的代码后,我们将会得到西北工业大学的招生计划。
需要注意的是,该会话接下来的 CSRF-Token 在这个response 的响应头。因此如果需要继续请求,需要使用这个response的headers去更新 CSRF-Token,代码如下所示:
# update Csrf-Token
headers["Csrf-Token"] = dict(response.headers)['Csrf-Token']
6 总结
在使用 Python3 爬虫时,我们需要了解 CSRF-Token 机制,并正确地处理它,以便服务器可以验证请求的合法性。
具体来说,我们需要通过发送 GET 请求来获取 CSRF-Token,然后将 CSRF-Token 嵌入到请求中,以便服务器可以验证请求的合法性。在 Python3 中,我们可以使用 requests 库和 Beautiful Soup 库来实现这一过程。
【笔记】Python3|爬虫请求 CSRF-Token 时如何获取Token、Token过期、处理 CSRF-Token 需要注意的问题及示例的更多相关文章
- python3爬虫中文乱码之请求头‘Accept-Encoding’:br 的问题
当用python3做爬虫的时候,一些网站为了防爬虫会设置一些检查机制,这时我们就需要添加请求头,伪装成浏览器正常访问. header的内容在浏览器的开发者工具中便可看到,将这些信息添加到我们的爬虫代码 ...
- 请求时token过期自动刷新token
1.在开发过程中,我们都会接触到token,token的作用是什么呢?主要的作用就是为了安全,用户登陆时,服务器会随机生成一个有时效性的token,用户的每一次请求都需要携带上token,证明其请求的 ...
- Python3 自定义请求头消息headers
Python3 自定义请求头消息headers 使用python爬虫爬取数据的时候,经常会遇到一些网站的反爬虫措施,一般就是针对于headers中的User-Agent,如果没有对headers进行设 ...
- 【Python3 爬虫】05_安装Scrapy
Scrapy简介 Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛.框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容 ...
- 【Python3爬虫】我爬取了七万条弹幕,看看RNG和SKT打得怎么样
一.写在前面 直播行业已经火热几年了,几个大平台也有了各自独特的“弹幕文化”,不过现在很多平台直播比赛时的弹幕都基本没法看的,主要是因为网络上的喷子还是挺多的,尤其是在观看比赛的时候,很多弹幕不是喷选 ...
- python3爬虫(4)各种网站视频下载方法
python3爬虫(4)各种网站视频下载方法原创H-KING 最后发布于2019-01-09 11:06:23 阅读数 13608 收藏展开理论上来讲只要是网上(浏览器)能看到图片,音频,视频,都能够 ...
- Python3爬虫:(一)爬取拉勾网公司列表
人生苦短,我用Python 爬取原因:了解一下Python工程师在北上广等大中城市的薪资水平与入职前要求. Python3基础知识 requests,pyquery,openpyxl库的使用 爬取前的 ...
- Python爬虫笔记(一):爬虫基本入门
最近在做一个项目,这个项目需要使用网络爬虫从特定网站上爬取数据,于是乎,我打算写一个爬虫系列的文章,与大家分享如何编写一个爬虫.这是这个项目的第一篇文章,这次就简单介绍一下Python爬虫,后面根据项 ...
- Python3爬虫系列:理论+实验+爬取妹子图实战
Github: https://github.com/wangy8961/python3-concurrency-pics-02 ,欢迎star 爬虫系列: (1) 理论 Python3爬虫系列01 ...
- golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍
golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍 go语言爬虫框架:gocolly/colly,goquery,colly,chrom ...
随机推荐
- Idea无法下载插件或下载插件报错
Plugin Python was not installed: Cannot download 'https://plugins.jetbrains. file -> settings -& ...
- DeepSeek智能编程
技术背景 DeepSeek开源之后,让大家意识到了即时是在自己硬件性能一般的本地环境,也能够部署和使用大语言模型,真正实现了大模型的"私有化".而私有化大模型之后,自然是考虑生产力 ...
- 从龟速乘到 $Miller-Rabin$ 算法(数论算法总结)
发现自己竟然菜到不太会龟速乘,所以把 \(Miller-Rabin\) 算法所需要用到的算法全学了一遍-- 龟速乘 龟速乘是一种 \(O(\log n)\) 的乘法计算方法. 考虑有时普通乘法取模会爆 ...
- 5. 想在代码中验证sql的正确性?
1. 简介 我们在平时的开发中可能会遇到需要验证一下sql是否正确,也就是需要check一下sql. 判断sql是否正确一般包含一下几点: 1. sql中使用的列是否存在 2. sql语法是否正确 3 ...
- pagehelper分页查询的一个坑,明明下一页没有数据了却还是返回了数据
pagehelper分页查询的一个坑,明明下一页没有数据了却还是返回了数据 解决:关闭这该死的合理化,如下配置: pagehelper:# helperDialect: mysql reasonabl ...
- 【Spring Boot】我的第一个Spring Boot练习
背景 Spring 在 Java 生态的企业级开发项目中极其常用,通常我们为项目引入一项新技术时,不得不考虑如何将新技术与 Spring 整合在一起. 我们知道,预研一项新技术,我们基于 MVP(最简 ...
- Oracle - [03] 存储过程
一.什么是存储过程 存储过程是一种数据库对象,是一种存储在数据库中的可执行程序,是一些经过编写.编译而存在数据库中的SQL语句集. 二.创建存储过程的语法 create or replace proc ...
- postgresql使用for循环
开发过程中经常需要制造一些测试数据,sqlserver等数据库都有循环执行语句的方式,postgresql也可以使用for循环插入数据 do $$ begin for tt in 1..99 loop ...
- Refit 原理解析:从初识到实践
在现代的分布式系统和微服务架构中,HTTP API 调用是不可或缺的一部分.为了简化 HTTP 请求的构建和解析,我们可以使用 Refit 这个强大的库.Refit 通过将 HTTP API 抽象为接 ...
- python基础-函数(lambda表达式、函数作参数、内置函数、推导式)和pip
函数进阶 今日概要: 函数名就是一个变量(扩展) 匿名函数(lambda表达式) 重点内置函数--python内置函数 推导式(一行代码生成数据) 1. 函数名就是变量 def func(): pas ...