20. 一秒一个Token甩到前台,吓死在座的各位爬虫工程师
Posted 梦想橡皮擦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20. 一秒一个Token甩到前台,吓死在座的各位爬虫工程师相关的知识,希望对你有一定的参考价值。
本篇博客是爬虫训练场中的基础反爬案例,核心实现通过动态 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 年内保证更新
以上是关于20. 一秒一个Token甩到前台,吓死在座的各位爬虫工程师的主要内容,如果未能解决你的问题,请参考以下文章