实现思路
1.参数加密
已知我的参数是 page 和 pageSize,此时我想要对着两个参数进行加密,那么我的选型还是比较多的,这里使用常见的md5进行加密处理。
思路
避免加密参数不变,我们引入一个时间戳来混淆爬虫,这样我们就得到了加密的参数了。
代码参考:
java
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混淆工具
混淆前的代码
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
});
混淆后的代码
js
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
工具进行操作
工具类:
java
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);
}
}
}
以上就是我针对这个接口的加密方式,也是心血来潮,想要实现一个,毕竟写了这么多爬虫文章了,也应该介绍下反爬了。
如果大家有比较好的策略,可以评论区留言交流一下。