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 部分逻辑。

当然正式阅读本文前需要梳理一下逻辑。

  1. 我们在前端通过JS生成两个 cookie 值分别是 timestamptoken
  2. timestamp 通过 JS 获取时间戳tokentimestamp 进行 md5 加密
  3. timestamptoken 都要发送到 Python Flask 端
  4. 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=/";

你还可以使用 encodeURIComponent 函数来对 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 对象的各种方法如 getFullYeargetMonth 等来访问年份、月份、日期等信息。

使用 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 对象可以使用它的各种方法如 toStringtoHex 等来访问哈希值。

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 值。

两个值都写入完毕就可以在前台编写数据发送代码发送过程要求携带 timestamptoken

    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 年内保证更新

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

“20. 一秒一个Token甩到前台,吓死在座的各位爬虫工程师” 的相关文章