最近忙于业务开发、交接和游戏,加上碰上了不定时出现的犹豫期和困惑期,荒废学业了一段时间。天冷了,要重新拾起开始下阶段的学习了。之前接触到的一些数据搜索项目,涉及到请求模拟,基于反爬需要使用随机的 User Agent
,于是使用 Redis
实现了一个十分简易的 UA
池。
背景
最近的一个需求,有模拟请求的逻辑,要求每次请求的请求头中的 User Agent
要满足下面几点:
- 每次获取的
User Agent
是随机的。 - 每次获取的
User Agent
(短时间内)不能重复。 - 每次获取的
User Agent
必须带有主流的操作系统信息(可以是Uinux
、Windows
、IOS
和安卓等等)。
这里三点都可以从 UA
数据的来源解决,实际上我们应该关注具体的实现方案。简单分析一下,流程如下:
在设计 UA
池的时候,它的数据结构和环形队列十分类似:
上图中,假设不同颜色的 UA
是完全不同的 UA
,它们通过洗牌算法打散放进去环形队列中,实际上每次取出一个 UA
之后,只需要把游标 cursor
前进或者后退一格即可(甚至可以把游标设置到队列中的任意元素)。最终的实现就是:需要通过中间件实现分布式队列(只是队列,不是消息队列)。
具体实现方案
毫无疑问需要一个分布式数据库类型的中间件才能存放已经准备好的 UA
,第一印象就感觉 Redis
会比较合适。接下来需要选用 Redis
的数据类型,主要考虑几个方面:
UA
支持这几个方面的 Redis
数据类型就是 List
,不过注意 List
本身不能去重,去重的工作可以用代码逻辑实现。然后可以想象客户端获取 UA
的流程大致如下:
结合前面的分析,编码过程有如下几步:
准备好需要导入的 UA
数据,可以从数据源读取,也可以直接文件读取。
- 因为需要导入的
UA
数据集合一般不会太大,考虑先把这个集合的数据随机打散,如果使用Java
开发可以直接使用Collections#shuffle()
洗牌算法,当然也可以自行实现这个数据随机分布的算法, 这一步对于一些被模拟方会严格检验UA
合法性的场景是必须的 。 - 导入
UA
数据到Redis
列表中。 - 编写
RPOP + LPUSH
的Lua
脚本,实现分布式循环队列。
编码和测试示例
引入 Redis
的高级客户端 Lettuce
依赖:
<dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> <version>5.2.1.RELEASE</version> </dependency>
编写 RPOP + LPUSH
的 Lua
脚本, Lua
脚本名字暂称为 L_RPOP_LPUSH.lua
,放在 resources/scripts/lua
目录下:
local key = KEYS[1] local value = redis.call('RPOP', key) redis.call('LPUSH', key, value) return value
这个脚本十分简单,但是已经实现了循环队列的功能。剩下来的测试代码如下:
public class UaPoolTest { private static RedisCommands<String, String> COMMANDS; private static AtomicReference<String> LUA_SHA = new AtomicReference<>(); private static final String KEY = "UA_POOL"; @BeforeClass public static void beforeClass() throws Exception { // 初始化Redis客户端 RedisURI uri = RedisURI.builder().withHost("localhost").withPort(6379).build(); RedisClient redisClient = RedisClient.create(uri); StatefulRedisConnection<String, String> connect = redisClient.connect(); COMMANDS = connect.sync(); // 模拟构建UA池的原始数据,假设有10个UA,分别是UA-0 ... UA-9 List<String> uaList = Lists.newArrayList(); IntStream.range(0, 10).forEach(e -> uaList.add(String.format("UA-%d", e))); // 洗牌 Collections.shuffle(uaList); // 加载Lua脚本 ClassPathResource resource = new ClassPathResource("/scripts/lua/L_RPOP_LPUSH.lua"); String content = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8); String sha = COMMANDS.scriptLoad(content); LUA_SHA.compareAndSet(null, sha); // Redis队列中写入UA数据,数据量多的时候可以考虑分批写入防止长时间阻塞Redis服务 COMMANDS.lpush(KEY, uaList.toArray(new String[0])); } @AfterClass public static void afterClass() throws Exception { COMMANDS.del(KEY); } @Test public void testUaPool() { IntStream.range(1, 21).forEach(e -> { String result = COMMANDS.evalsha(LUA_SHA.get(), ScriptOutputType.VALUE, KEY); System.out.println(String.format("第%d次获取到的UA是:%s", e, result)); }); } }
某次运行结果如下:
第1次获取到的UA是:UA-0
第2次获取到的UA是:UA-8
第3次获取到的UA是:UA-2
第4次获取到的UA是:UA-4
第5次获取到的UA是:UA-7
第6次获取到的UA是:UA-5
第7次获取到的UA是:UA-1
第8次获取到的UA是:UA-3
第9次获取到的UA是:UA-6
第10次获取到的UA是:UA-9
第11次获取到的UA是:UA-0
第12次获取到的UA是:UA-8
第13次获取到的UA是:UA-2
第14次获取到的UA是:UA-4
第15次获取到的UA是:UA-7
第16次获取到的UA是:UA-5
第17次获取到的UA是:UA-1
第18次获取到的UA是:UA-3
第19次获取到的UA是:UA-6
第20次获取到的UA是:UA-9
可见洗牌算法的效果不差,数据相对分散。
小结
其实 UA
池的设计难度并不大,需要注意几个要点:
- 一般主流的移动设备或者桌面设备的系统版本不会太多,所以来源
UA
数据不会太多,最简单的实现可以使用文件存放,一次读取直接写入Redis
中。 - 注意需要随机打散
UA
数据,避免同一个设备系统类型的UA
数据过于密集,这样可以避免触发模拟某些请求时候的风控规则。 - 需要熟悉
Lua
的语法,毕竟Redis
的原子指令一定离不开Lua
脚本。
总结
以上所述是小编给大家介绍的使用Redis实现UA池的方案,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新动态
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]