20. 一秒一个Token甩到前台,吓死在座的各位爬虫工程师
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
本篇博客是爬虫训练场中的基础反爬案例核心实现通过动态 token 验证限制爬虫
学习过程重点是反爬思维学习
文章目录
基础结构搭建
本案例依旧采用学校列表数据实现核心要修改的文件未 school/index.py
然后在 templates/school
目录下拷贝 ajax_list.html
进行后续修改。
index.py
文件首先编写视图函数用于页面首次加载。
@s.route('ajax_list2')
def ajax_list2():
page = 1 # 初始化第一页数据
pagination = pagination_object(page)
return render_template('school/ajax_list2.html', pagination=pagination)
此时基础结构已经搭建完毕下面重点是前台JS代码生成 Cookie 部分逻辑。
当然正式阅读本文前需要梳理一下逻辑。
- 我们在前端通过JS生成两个 cookie 值分别是
timestamp
、token
timestamp
通过 JS 获取时间戳token
将timestamp
进行md5
加密timestamp
和token
都要发送到 Python Flask 端- Python 端校验
token
值和使用md5
之后timestamp
是否一致相同返回数据不相同返回 403。
前端 JS 生成 Cookie
JavaScript 可以使用 document.cookie
属性来设置、获取和删除 cookie。
设置 cookie 的语法如下
document.cookie = "name=value; expires=date; path=path; domain=domain; secure";
name=value
这是 cookie 的名称和值。名称和值之间用等号分隔。expires=date
这是 cookie 的过期日期。如果省略这个参数那么这个 cookie 将在浏览器关闭时过期。path=path
这是 cookie 可用的路径。如果省略这个参数那么这个 cookie 在整个站点内都可用。domain=domain
这是 cookie 可用的域。如果省略这个参数那么这个 cookie 在整个站点内都可用。secure
这是一个布尔值表示这个 cookie 只能通过 HTTPS 协议传输。
下面是一个示例设置一个名为 username
的 cookie值为 Ca
过期日期为 7 天之后
var expires = new Date();
expires.setTime(expires.getTime() + (7 * 24 * 60 * 60 * 1000));
document.cookie = "username=Ca; expires=" + expires.toUTCString() + "; path=/";
你还可以使用 encodeURIComponen
t 函数来对 cookie 的值进行编码以便在存储时保留特殊字符
var value = "梦想橡皮擦";
document.cookie = "username=" + encodeURIComponent(value) + "; expires=" + expires.toUTCString() + "; path=/";
要获取 cookie 的值可以使用 getCookie 函数
function getCookie(name) {
let value = "; " + document.cookie;
let parts = value.split("; " + name + "=");
if (parts.length == 2) {
return decodeURIComponent(parts.pop().split(";").shift());
}
}
上述函数使用 ;
作为分隔符将 document.cookie
分割成一个数组。然后使用 split()
函数将每个 cookie 的名称和值分割开来。最后使用 decodeURIComponent()
函数将值解码并返回。
删除 cookie可以将其过期日期设置为过去的某个日期
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
获取时间戳
基于这些内容我们在 ajax_list2.html
文件中建立一个创建 cookie 的函数。
// js 设置 cookie 值
function setCookie(key,value,day){
var cookie=key+'='+encodeURIComponent(value);
if(day>0){
var date=new Date();
date.setDate(date.getDate()+day);
cookie+=';expires='+date;
}
document.cookie=cookie;
}
然后开始写入 cookie首先获取时间戳在 JavaScript 中可以使用 Date.now()
方法来获取当前时间戳。
var timestamp = Date.now();
你也可以使用 performance.now()
方法来获取更高精度的时间戳。这个方法返回从页面加载开始的毫秒数。
var timestamp = performance.now();
如果你想将时间戳转换为标准日期格式可以使用 new Date()
方法。
var date = new Date(timestamp);
这样就可以使用 date 对象的各种方法如 getFullYear
、getMonth
等来访问年份、月份、日期等信息。
使用 CryptoJS 库来实现 MD5 哈希生成 token
在 JavaScript 中可以使用 CryptoJS 库来实现 MD5 哈希。
首先需要在 HTML 中引入 CryptoJS 库
<script src="https://cdn.jsdelivr.net/npm/crypto-js@4.0.0/crypto-js.min.js"></script>
然后可以使用 CryptoJS.MD5()
方法来计算 MD5 哈希值。
var message = "Hello, XiangPiCa!";
var hash = CryptoJS.MD5(message);
这样就可以得到一个 CryptoJS 对象可以使用它的各种方法如 toString
、toHex
等来访问哈希值。
var hashString = hash.toString();
var hashHex = hash.toHex();
接下来就可以生成 token 值将上述内容应用到爬虫训练场案例中示例代码如下
// 每次间隔10秒设置 Cookie 值
setInterval(function(){
// 获取当前时间戳
var timestamp = Date.now();
// 设置时间戳
setCookie("timestamp",timestamp,1);
//加密 token由时间戳加密
var token = CryptoJS.MD5(timestamp.toString());
setCookie("token",token,1);
},10*1000);
代码还使用了 setInterval()
定时器函数每间隔 10 秒写入 Cookie 值。
两个值都写入完毕就可以在前台编写数据发送代码发送过程要求携带 timestamp
和 token
。
function get_data(page){
// 获取存储的 cookie 值
timestamp = getCookie("timestamp");
token = getCookie("token");
$.ajax({
type: "get",
url: "/ss/api_token",
data: {
page: page,
timestamp:timestamp,
token:token
},
success: function(response) {
// ajax 请求成功
render_data(response);
// 修改分页数据
$('.prev').attr('page',response["prev_page"]);
$('.next').attr('page',response["next_page"]) ;
console.log("AJAX request succeeded!");
},
error: function(error) {
console.log("AJAX request failed: " + error);
}
});
}
然后就是后台接口解析参数代码的编写了
Python Flask 解析参数
在 school/index.py
文件中添加如下代码。
@s.route('api_token')
def token_list_school():
page = int(request.args.get("page", 1))
token = request.args.get("token", None)
timestamp = request.args.get("timestamp", None)
if token is None or timestamp is None:
return "请求出错", 403
# 加密 timestamp与 token 比较
hash = hashlib.md5()
hash.update(timestamp.encode())
p_token = hash.hexdigest()
print(p_token)
if token != p_token:
return "请求出错", 403
pagination = pagination_object(page)
return jsonify(pagination)
其中重点要说明是的 python 生成 md5 值部分。
首先需要导入 hashlib 模块
import hashlib
然后可以使用 hashlib.md5()
函数创建一个 MD5 哈希对象。
hash.update(b"Hello, XiangPiCa!")
接下来可以使用 update()
方法将数据传入哈希对象。
hash.update("Hello, XiangPiCa!".encode())
最后可以使用 hexdigest()
方法计算哈希值。
hashValue = hash.hexdigest()
本案例到此结束已更新到 爬虫训练场 欢迎大家访问学习。
项目同步到代码仓库 https://gitcode.net/hihell/spider_playground
📢📢📢📢📢📢
💗 你正在阅读 【梦想橡皮擦】 的博客
👍 阅读完毕可以点点小手赞一下
🌻 发现错误直接评论区中指正吧
📆 橡皮擦的第 818 篇原创博客
从订购之日起案例 5 年内保证更新