文章目录
- 1. 写在前面
- 2. 接口分析
- 3. 点选验证分析
- 4. Python程序实现
【🏠作者主页】:吴秋霖
【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与开发工作!
【🌟作者推荐】:对爬虫领域以及JS逆向分析感兴趣的朋友可以关注《爬虫JS逆向实战》《深耕爬虫领域》
未来作者会持续更新所用到、学到、看到的技术知识!包括但不限于:各类验证码突防、爬虫APP与JS逆向分析、RPA自动化、分布式爬虫、Python领域等相关文章
作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!
1. 写在前面
一个新注册的账号一般我们会需要去完成一些基本的任务,比如通过完成答题的方式来进行升级提升权重,而对于答题至少需要完成60道题目的提交才算通过结束!本期我们通过对接口协议的分析来实现一个自动答题机器人,以及在答题的过程中出现点选验证码自动识别验证(8~10道题会要求验证一次)
验证码的话是极验3代三代的一个点选,难度不高!目前有很多种方式来识别验证。如果不想自己训练模型的话可以选择三方的平台
2. 接口分析
首先,我们进入到答题页面,每一道题刷新或者进入下一道题统一走如下接口,如下所示:
{"code":0,"message":"0","ttl":1,"data":{"question":{"id":710,"number":2,"q_height":38.4,"q_coord_y":0,"image":"https://i0.hdslb.com/bfs/member/56093e64936bb5ab040338287adbbfa5.png","from":"","options":[{"number":1,"high":42,"coord_y":38.4,"hash":"12a780b4550d69984494393c9db37faa"},{"number":2,"high":42,"coord_y":80.4,"hash":"a5d259743588549bdb6d98bf4fe50201"}],"type_id":0,"type_name":"","type_image":"","question":{"title":"IX3s9ZxyNPkxiLQracOZ93LB9rR5kXS9chmlm00P9SJ0sCjs2cDCXAaXpFC25xXveXzNqyjBjSCkCKRTqeecRw==","ans":[{"key":"12a780b4550d69984494393c9db37faa","title":"GSjdQikjaZ7uBkdw6H9nmS5NzYhmHZThuPBC4Bh1vY4FIoZ1wIz6xbvwiF0vUmAj"},{"key":"a5d259743588549bdb6d98bf4fe50201","title":"AacVYsQd6gJvrgjs0mwtVijK8weBcJdu2SFrOaTWn615C4iVb/REFsJWJU9rafY7"}]},"decision_ctx":{}}}}
我们对上面生成题的接口响应信息进行一个简单的分析,数据如上所示!因为60道题的类型都是选择题,且只有两个选项,在options字段中就是题选项的信息。外层的number是当前答题的进度(第几题),hash是提交答案接口的字段,如下所示:
可以看到接口check是提交答案的发包接口,其中ans_key字段则是上面说到的hash字段
,在提交答案后,我们需要取判断提交的回答是否正确,在响应JSON的数据中通过is_right字段去检验,如下所示:
{"code":0,"message":"0","ttl":1,"data":{"passed":true,"is_right":true,"ans_right":"a5d259743588549bdb6d98bf4fe50201"}}
3. 点选验证分析
这个自动答题的自动化流程中,难点在于答题过程中出现的点选验证码!这个跟行为无关,就算是手动去答题也是会在几道后出现的。我们现在来分析一下验证码的接口,如下:
上图出现验证码所提交的json_payload那一堆参数(一些环境、IP、设备相关的信息),在提交check答题的时候如果遇到了验证码,接口响应code是41096,然后拿到那一堆参数去请求register接口,拿到验证所需要的关键字段信息,如下所示:
{"code":0,"message":"0","ttl":1,"data":{"type":"geetest","token":"731eeeb787214dd59e6e6ebeebb31d64","geetest":{"challenge":"76cc14453621e982ecc7bfe163cbf841","gt":"ac597a4506fee079629df5d8b66dd4fe"},"biliword":null,"phone":null,"sms":null}}
可以看到validate验证码验证接口所提交的参数,即是上面register接口响应内的。通过调用训练好的验证码识别模型进行点选验证,验证成功通过is_valid来区分,如下所示:
然后拿register接口内给的token字段去提交当前出现验证码的题,即可通过!如下所示:
4. Python程序实现
梳理完整个题答流程后,现在可以开始实现完整的Python答题程序,首先获取Cookie信息,Web端答题的话必须拿到浏览器登录后的完整全参Cookie信息,不然的话buvid参数缺失!如下:
这里需要注意登录的IP保持跟答题的一致!虽然风控强度不是很高,但是测试发现会关小黑屋!拿到Cookie信息直接去请求出题接口,正式开始答题,代码实现如下所示:
url = "https://api.bilibili.com/x/answer/v4/base"
params = {
"platform": "pc",
"image_version": "v",
"re_src": "0",
"web_location": "333.858"
}
try:
response = requests.get(
url,
headers=headers,
cookies=cookies,
proxies=proxies
).json()
if code == 41020:
logger.info('已完成答题!!!')
elif code == 101:
logger.error(f'账号出现异常!!!')
elif code == 0:
question = response.get('data', {}).get('question', {})
question_id = question.get('id', '')
number = question.get('number', '')
logger.info(f'当前答题进度: 第 {number} 题~~')
options = question.get('options', [])
for opts in options:
hashs = opts.get('hash', '')
result = check(headers, cookies, question_id, hashs, proxies)
if result:
logger.info('提交答案成功,进入下一题!')
code目前三种最常见的状态码及含义已在上面程序分支中表示!可以看到作者在拿到options答案选项后采取了遍历的方式去答题,因为平台机制就是答错了可以继续提交其他选项答案,也是能够通过的。且就两个选项(作者测试的话采取的枚举)
这个地方其实可以有更加好的方案!比如我们先去收集一个庞大且完整的题库,让答题更加精准!因为枚举的方式太过于机器人化,也是会有风控的!或者让选择更加的随机化以及对接AI去完成答题都是比较好的一个方案(感兴趣自行去研究尝试)
接下来,继续实现check接口提交答案代码,这部分就需要对接点选验证码的处理了,因为在页面上触发验证码也是在提交选项的时候出现。代码实现如下所示:
url = "https://api.bilibili.com/x/answer/v4/base/check"
data = {
"re_src": 0,
"question_id": question_id,
"ans_key": hashs,
"csrf": cookies['bili_jct']
}
if token:
data['token'] = token
response = requests.post(
url,
headers=headers,
cookies=cookies,
data=data,
proxies=proxies).json()
logger.info(f'提交回答信息: {response}')
code = response.get('code', -1)
if code == 41096:
grisk_id = response.get('data', {}).get('grisk_id', '')
decision_ctx = response.get('data', {}).get('decision_ctx', {})
logger.error(f'出现点选验证码!!!')
token = get_geetest(headers, cookies, grisk_id, decision_ctx, proxies)
if token:
# 过了验证码直接携带Token提交答题验证
check(headers, cookies, question_id, hashs, proxies, token=token)
过完点选验证后,其他基本就没有太多的一个编码工作了!需要注意一下整个自动答题的流程、行为、策略。以防止程序的健壮性以及稳定性(比如说答题的间断性、不要一下把60道全部去完成、IP地址的唯一性)