实现思路

1.参数加密

已知我的参数是 page 和 pageSize,此时我想要对着两个参数进行加密,那么我的选型还是比较多的,这里使用常见的md5进行加密处理。

思路

避免加密参数不变,我们引入一个时间戳来混淆爬虫,这样我们就得到了加密的参数了。
代码参考:

import request from '../utils/request';
import CryptoJS from 'crypto-js';
export const searchUserByTags = (tags: any, page: any, pageSize: any) => {
    const timestamp = Date.now().toString();
    const sign = CryptoJS.MD5(page + pageSize + timestamp + "xiaocaidan").toString();
    return request.post("/user/search", {
        tags: tags,
        page: page,
        pageSize: pageSize,
        time: timestamp,
        sign: sign
    });
}

优化,我们可以将tags进行转换,使用hash操作,得到一个新的加密参数,然后进行拼接,得到一个最终效果的参数
如: sign + '|' + time + '|' + hash(tags)

2.代码混淆

得到上方的的加密代码之后我们可以做一个js混淆,让爬虫解析前端代码困难起来。
js混淆工具

混淆前的代码
const timestamp = Date.now().toString();
    const sign = CryptoJS.MD5(page + pageSize + timestamp + "xiaocaidan").toString();
    return request.post("/user/search", {
        tags: tags,
        page: page,
        pageSize: pageSize,
        time: timestamp,
        sign: sign
    });
混淆后的代码
function _0x5670(_0x4239f6, _0x1c06ce) {
        const _0x2507cf = _0x2507(); return _0x5670 = function (_0x567057, _0x3c9f41) { _0x567057 = _0x567057 - 0x1a1; let _0x39c382 = _0x2507cf[_0x567057]; return _0x39c382; }, _0x5670(_0x4239f6, _0x1c06ce);
    }
    const _0x99028a = _0x5670;
    (function (_0x123360, _0xd0bda3) {
        const _0x89478b = _0x5670, _0x5256f6 = _0x123360();
        while (!![]) {
            try {
                const _0x199e10 = parseInt(_0x89478b(0x1a2)) / 0x1 * (-parseInt(_0x89478b(0x1a4)) / 0x2) + parseInt(_0x89478b(0x1a5)) / 0x3 + -parseInt(_0x89478b(0x1ab)) / 0x4 * (parseInt(_0x89478b(0x1af)) / 0x5) + parseInt(_0x89478b(0x1a3)) / 0x6 * (-parseInt(_0x89478b(0x1a9)) / 0x7) + parseInt(_0x89478b(0x1a6)) / 0x8 + parseInt(_0x89478b(0x1a8)) / 0x9 * (parseInt(_0x89478b(0x1a1)) / 0xa) + -parseInt(_0x89478b(0x1ae)) / 0xb; if (_0x199e10 === _0xd0bda3) break; else _0x5256f6['push'](_0x5256f6['shift']());
            } catch (_0x4c629a) { _0x5256f6['push'](_0x5256f6['shift']()); }
        }
    }(_0x2507, 0x9dcd3)); const timestamp = Date['now']()[_0x99028a(0x1ad)](), sign = CryptoJS[_0x99028a(0x1ac)](page + pageSize + timestamp + _0x99028a(0x1a7))[_0x99028a(0x1ad)](); function _0x2507() { const _0x35df2c = ['MD5', 'toString', '1339305ECXPIG', '3365ERShus', '1270gpPtfm', '110645cBxblt', '6RZquIb', '4MjMiyF', '87582bFxmbr', '8275472fserRH', 'xiaocaidan', '70794rMDivZ', '7083769lzcyvp', '/user/search', '364WoWysM']; _0x2507 = function () { return _0x35df2c; }; return _0x2507(); } return request['post'](_0x99028a(0x1aa), { 'tags': tags, 'page': page, 'pageSize': pageSize, 'time': timestamp, 'sign': sign });
接口限流

使用Redisson中的RRateLimiter工具进行操作

工具类:
package com.caidan.HuoBanSystem.utils;

import com.caidan.HuoBanSystem.exception.BaseException;
import jakarta.annotation.Resource;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;


/**
 * @项目名 BIProject
 * @描述 使用redis进行限流操作
 * @作者 wzy
 * @时间 2024/5/28 18:46
 */
//  注册一下bean
//  写成一个工具类 便于后续使用
@Component
public class RedisLimitManager {
    @Resource
    private RedissonClient redissonClient;
    //    定义限流内容
    public void doRateLimit(String key,String message) {
//      设置限流器
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
        // 设置限流器的速率:每秒产生 2 个令牌,允许突发 1 个令牌
        rateLimiter.trySetRate(RateType.OVERALL, 2, 1, RateIntervalUnit.SECONDS);
//      当一个操作来的时候,请求一个令牌
        boolean canOp = rateLimiter.tryAcquire(1);
        if(!canOp){
            throw new BaseException(message);
        }
    }
}

以上就是我针对这个接口的加密方式,也是心血来潮,想要实现一个,毕竟写了这么多爬虫文章了,也应该介绍下反爬了。
如果大家有比较好的策略,可以评论区留言交流一下。