使用Python实现B站自动答题机器人

文章目录

  • 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地址的唯一性

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/403904.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是OpenTiny?

OpenTiny 是一套企业级的 Web 前端开发解决方案,提供跨端、跨框架的 UI 组件库和低代码引擎,帮助开发者高效构建 Web 应用 。企业运用开发中,可以利用 OpenTiny 的以下核心组件和优势: TinyVue 组件库:一个丰富的组件库…

C/C++实现蓝屏2.0

🚀欢迎互三👉:程序猿方梓燚 💎💎 🚀关注博主,后期持续更新系列文章 🚀如果有错误感谢请大家批评指出,及时修改 🚀感谢大家点赞👍收藏⭐评论✍ 前…

【机器学习-监督学习】逻辑斯谛回归

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科,通过算法和模型让计算机从数据中学习,进行模型训练和优化,做出预测、分类和决策支持。Python成为机器学习的首选语言,…

使用Python制作贪吃蛇小游戏

引言 贪吃蛇游戏是一款经典的电子游戏,玩家通过控制一条不断增长的蛇在格子内移动,并吃掉随机出现的食物来获得分数。随着分数的增加,蛇的身体也会越来越长,游戏的难度也随之提升。在本文中,我们将详细介绍如何使用Py…

基于django的双选宠物托管服务平台/python宠物托管系统

摘 要 伴随着社会以及科学技术的发展,互联网已经渗透在人们的身边,网络慢慢的变成了人们的生活必不可少的一部分,紧接着网络飞速的发展,系统管理这一名词已不陌生,越来越多的双选宠物托管服务等机构都会定制一款属于…

使用 AWS CLI 自动在 Amazon EC2 实例上部署 Apache Web 服务器

“使用 AWS CLI 节省时间” 欢迎来到雲闪世界。今天,我们将利用 AWS CLI 的实际用途来提高效率并自动执行在 Amazon EC2 实例上部署 Apache Web 服务器的步骤。完成“使用 AWS CLI 节省时间”任务后,最后有一个非常有趣的秘密步骤,敬请…

UCOSIII内存管理机制详解

目录 前言 1. 内存管理概述 2. 内存区域(存储区)和内存块 3. 存储区控制块(OS_MEM) 4. 内存管理函数 5. 内存碎片问题 6. 注意事项 7.代码实现 7.1创建内存区域 7.2申请内存 7.3释放内存 前言 UCOSIII(即Mi…

c++----简单了解string

大家好,也是好久没有更新了。今天我想与大家分享的是c中常用的便捷的应该库。哈哈。可能大家对我们c的便捷性已经在前面有很多耳闻了。比如我们前面说的类模板。也是很便捷的。但是我们今天这个更加方便了。但缺点就是太多了。经过多年的迭代更新。这个库函数已经很…

2024.8.15(python管理mysql、Mycat实现读写分离)

一、python管理mysql 1、搭建主mysql [rootmysql57 ~]# tar -xf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz [rootmysql57 ~]# cp -r mysql-5.7.44-linux-glibc2.12-x86_64 /usr/local/mysql [rootmysql57 ~]# rm -rf /etc/my.cnf [rootmysql57 ~]# mkdir /usr/local/mysql…

qt-13 进度条(模态和非模态)

进度条-模态和非模态 progressdlg.hprogressdlg.cppmain.cpp运行图模态非模态 progressdlg.h #ifndef PROGRESSDLG_H #define PROGRESSDLG_H#include <QDialog> #include <QLabel> #include <QLineEdit> #include <QProgressBar> #include <QCombo…

[书生大模型实战营][L0][Task2] Python 开发前置知识

0. 任务&#xff1a;在 InternStudio 环境中实现功能&#xff1a; python 实现 wordcount函数&#xff0c;统计英文字符串单词的使用频率&#xff0c;并返回字典&#xff1b;vscode 远程调试 InternStudio 中的 python 代码 1. wordcount 函数实现 string.punctuation 是一个…

一键切换全球优质Linux 系统软件源及 Docker 源,轻松安装 Docker —— 适配广泛、零门槛、超强功能的开源脚本!

概述 linuxMirrors开源脚本为 GNU/Linux 系统用户提供了强大的工具,帮助用户轻松更换系统软件源并安装 Docker。脚本适配了多种国内外镜像站,经过测试具备良好的下载速度和 IPv6 兼容性,并且还包括了中国大陆教育网镜像站的选项。无需技术背景,文档提供了详尽的操作指引和常…

机器学习(3)-- 一元线性回归

文章目录 线性回归训练模型测试模型线性回归方程测试实用性 总结 线性回归 线性回归算法是一种用于预测一个或多个自变量&#xff08;解释变量&#xff09;与因变量&#xff08;响应变量&#xff09;之间关系的统计方法。这种方法基于线性假设&#xff0c;即因变量是自变量的线…

【网络安全】重置密码token泄露,实现账户接管

未经许可&#xff0c;不得转载。 文章目录 正文 正文 对某站点测试过程中&#xff0c;登录账户触发忘记密码功能点&#xff0c;其接口、请求及响应如下&#xff1a; PUT /api/v1/people/forgot_password 可以看到&#xff0c;重置密码token和密码哈希均在响应中泄露。 删除co…

【C#】虚部与实部

实数是数学中的一个基本概念&#xff0c;它包括了所有的有理数和无理数。实数集合是连续的&#xff0c;可以表示为数轴上的每一个点。 复数是实数的扩展&#xff0c;它允许进行除零以外的所有基本算术运算。复数由两部分组成&#xff1a;实部和虚部。 实部&#xff08;Real P…

【MySQL 07】表的增删查改 (带思维导图)

文章目录 &#x1f308; 一、insert 添加数据⭐ 1. 单行数据 全列插入⭐ 2. 多行数据 指定列插入⭐ 3. 插入否则更新⭐4. 插入否则替换 &#x1f308; 二、select 查询数据⭐ 1. select 列&#x1f319; 1.1 全列查询&#x1f319; 1.2 指定列查询&#x1f319; 1.3 查询字段…

Prettier+Vscode setting提高前端开发效率

文章目录 前言Prettier第一步&#xff1a;下载依赖&#xff08;团队合作&#xff09;或下载插件&#xff08;独立开发&#xff09;第二步&#xff1a;添加.prettierrc.json文件**以下是我使用的****配置规则** 第三步&#xff1a;添加.prettierignore文件**以下是我常用的****配…

OpenCV图像滤波(20)模糊处理函数stackBlur()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 stackBlur() 函数用于对图像进行模糊处理。该函数对图像应用了 stackBlur 技术。stackBlur 可以生成与高斯模糊相似的结果&#xff0c;而且随着模…

C++ 左值引用与右值引用超详解

目录 一 左值与右值 1.左值 2.右值 3.总结 二 左值引用与右值引用 1.左值引用 2.右值引用 3.总结与探究 3.1右值引用可以修改么&#xff1f;取地址么&#xff1f; 3.2左值引用与右值引用转化 左值引用 引用 右值 右值引用 引用 左值 3.3左值引用与右值引用相同之处 3.4左值…

栈与队列 - 逆波兰表达式求值

150. 逆波兰表达式求值 方法一&#xff1a;栈 /*** param {string[]} tokens* return {number}*/ var evalRPN function(tokens) {const stack [];for (const token of tokens) {if (isNaN(Number(token))) { // 非数字const n2 stack.pop(); // 出栈两个数字const n1 s…