目录
前言一
涉及前端基础知识JavaScript、css、HTML
涉及后端基础知识PHP
使用前端框架:Vue.js
使用后端框架:Thinkphp6
前言二
咳咳,真的不太想吐槽。你有没有和我刚进大学一样傻傻的打开百度,搜索”xxx小助手“?
然后下载了一堆不能用的文件,又或者省吃俭用的找班上的大哥来个全包?咳咳,我的口袋空空如也,思来想去还是自己写一个脚本吧。
猜测
因为浏览器与服务器是通过HTTP协议发起HTTP请求进行通信的所以我们可以试着猜想一下平台是如何判断学生是否学习的大致过程:
- 学生选择需要学习的视频开始学习
- 由于看视频这个操作是在浏览器进行的,所以当看完视频后,浏览器会发送请求通知服务器这个视频已经看完了
- 服务器收到浏览器的通知后会进行信息处理,记录学生学习本条视频的日志,然后将处理结果返回给浏览器
- 浏览器得到服务器反馈的结果后,将结果告知学生
思考
我们大概得知了平台对于学习判断的处理过程,那么我们就可以开始分析它的请求了
- 打开浏览器开发者工具
- 查找在正常学习完视频时浏览器发送的HTTP请求
- 仔细分析并记录该请求的API及其所有参数(请求参数和返回参数)
- 分析各项参数的内涵信息,并从其他请求中寻找与其关联的参数
- 通过HTML文本查看器或者API返回数据找出当前视频资源的特殊信息,可能有用的id值等,找到每个任务点之间的id规律
- 通过分析得到所有视频的id,然后利用官方的API进行各项参数填充伪造请求即可
一、官方API分析
1.获取用户信息
返回参数:
- username(用户名:string)[例:137351913010023]
- name(用户名:string)[例:谭某某]
- gender(性别:string)[例:男]
- speciality(专业:string)[例:计算机专业]
- headimgurl(头像url:string)[例:/image?id=375910]
- mobile(手机号码:string)[例:10086]
- email(邮箱:string)
- schoolName(学校名称:string)[例:清华大学]
- schoolId(学校ID:string)[例:51]
2.获取课程所有者信息
返回参数:
- id(所有者id)(即ownerId)
- username(用户名:string)[例:137351913010023]
- phone(手机号码:string)[例:10086]
- email(邮箱:string)
3.获取测试题信息
说明:获取套题信息,用于刷测试题
需要参数:
- id(套题ID:string)
返回参数:
- created(套题创建日期:时间戳)[例:1591588248418]
- lastUpdated(套题最后一次修改日期:时间戳)[例:1632490828042]
- ownerId(套题所有者ID)
- title(套题名称)
- submitEnd(套题截至日期:时间戳)
- number(套题可提交次数)
- score(套题满分)
4.获取parentId
需要参数:
- ownerId(课程所有者id:string)[例:1298995]
- courseId(课程id:string)[例:334568834]
返回参数:parentId(课程父id)
说明:API需要使用parentId参数,这里只需要获取这个参数即可,其他信息并不重要
r.data[0].id
5.学习日志添加接口
说明:限制秒刷间隔30秒,该接口为官方学习日志接口,秒刷原理为直接通过API记录各任务点的学习日志即可学习成功
请求方法:POST
需要参数:
- username(用户ID名:string)[例:137351913010023]
- ownerId(课程所有者ID:string)
- parentId(课程父ID:string)
- action(固定值:0)
- courseId(课程ID:string)
- sectionId(节ID)
- chapterId(章ID)
提供信息:
- code(0=成功 2=重复刷 3=失败)
6.官方套题提交接口
说明:只能用于测试题提交,不包括考试和作业,answer参数必须是json格式
请求方法:POST
需要参数:
- username(用户ID名:string)[例:137351913010023]
- ownerId(课程所有者ID:string)
- paperId(套题ID:string)
- name(用户姓名:string)
- courseId(课程ID:string)
- answers(答案:object)
- classId(固定值:"")
提供信息:
- code(100=失败)
二、脚本API设计及编写
1.脚本用户注册API
设计思路:用于用户注册
JS部分:
- 发送方法:POST
- 发送参数:
- username(用户名)
- password(密码)
- 接收参数:
- data
- code(状态码 1=注册成功 -1=已被注册)
- date(注册日期)
数据库部分: ooc_userinfo
字段名 | 类型 | 注释 |
---|---|---|
id | int | 表内唯一id |
username | varchar | 用户名 |
password | varchar | 密码 |
date | datetime | 注册日期 |
PHP部分:
- 接收方法:POST
- 方法命名:logon
- 需要参数:
- username(用户名)
- password(密码)
- 返回参数:
- data
- code(状态码 1=注册成功 -1=已被注册)
- date(注册日期)
- 涉及数据库:ooc_userinfo
PHP代码:
$username=request()->post("username");
$password=request()->post("password");
$data = array(
'code' => 1,
'date' => null
);
$res = Db::name('ooc_userinfo')->where(['username'=>$username])->select();
if($res->isEmpty()){//如果不存在这个用户名
$data = ['username'=>$username,'password'=>$password,'date'=>date("Y-m-d H:i:s")];
Db::name('ooc_userinfo')->insert($data);
}else//存在这个用户名即已被注册
{
$data['code']=-1;
}
return $data;
2.脚本用户登录API
设计思路:用于登录平台
JS部分:
- 发送方法:POST
- 发送参数:
- username(用户名)
- password(密码)
- 接收参数:
- data
- code(状态码 1=登录成功 -1=未注册 -2=密码错误)
- date(注册日期)
数据库部分: ooc_userinfo
字段名 | 类型 | 注释 |
---|---|---|
id | int | 表内唯一id |
username | varchar | 用户名 |
password | varchar | 密码 |
date | datetime | 注册日期 |
PHP部分:
- 接收方法:POST
- 方法命名:login
- 需要参数:
- username(用户名)
- password(密码)
- 返回参数:
- data
- code(状态码 1=正常登录 -1=未注册)
- date(注册日期)
- 涉及数据库:ooc_userinfo
PHP代码:
$username=request()->post("username");
$password=request()->post("password");
$data = array(
'code' => 1,
'date' => null
);
$res = Db::name('ooc_userinfo')->where(['username'=>$username])->select();
if(!$res->isEmpty()){//如果存在这个用户名
foreach($res as $r){
if($r['password']!=$password){//密码不正确
$data['code']=-2;
}
}
}else//不存在这个用户名即未注册
{
$data['code']=-1;
}
return $data;
3.脚本题库答案查询接口
设计思路:查询题库答案
JS部分:
- 发送方法:POST
- 发送参数:
- testid(套题id)
- 接收参数:
- data
- code(状态码 1=查询成功 -1=没有答案)
- answers(答案)(需要进行json格式化)
- score(可得分数)
- zscore(总分数)
数据库部分: ooc_tk
字段名 | 类型 | 注释 |
---|---|---|
id | int | 表内唯一id |
testid | int | 套题id |
courseid | int | 课程id |
userid | int | 上传者ID |
answers | longtext | 答案 |
zscore | varchar | 套题满分 |
score | varchar | 可得分数 |
date | datetime | 上传时间 |
overdate | datetime | 套题无效时间 |
PHP部分:
- 接收方法:POST
- 方法命名:ooc_selecttk
- 需要参数:
- testid(套题id)
- 返回参数:
- data
- code(状态码 1=查询成功 -1=没有答案)
- answers(答案)
- score(可得分数)
- zscore(总分数)
- 涉及数据库:ooc_tk
PHP代码:
$data = array('code' => 1, 'answers' => null, 'score' => 0, 'zscore' => 0);
$testid = request()->post('testid');
$res = Db::name('ooc_tk')->where(['testid' => $testid])->select();
if (!$res->isEmpty()) {
foreach ($res as $r) {
$data['answers'] = $r['answers'];
$data['score'] = $r['score'];
$data['zscore'] = $r['zscore'];
}
} else {
$data['code'] = -1;
}
return $data;
4.题库答案上传接口
设计思路:将完善的答案和课程套题信息上传到题库保存更新
- 更新答案
- 新增答案
JS部分:
- 发送方法:POST
- 发送参数:
- testid(套题id)
- courseid(课程id)
- answers(答案)
- score(已得分数)
- userid(上传者id)
- zscore(总分数)
- overdate(套题截至日期)
- 接收参数:
- data
- code(状态码 1=更新答案 2=新增答案)
- func(使用的方法)
数据库部分: ooc_tk
字段名 | 类型 | 注释 |
---|---|---|
id | int | 表内唯一id |
testid | int | 套题id |
courseid | int | 课程id |
userid | int | 上传者ID |
answers | longtext | 答案 |
zscore | varchar | 套题满分 |
score | varchar | 可得分数 |
date | datetime | 上传时间 |
overdate | datetime | 套题无效时间 |
PHP部分:
- 接收方法:POST
- 方法命名:ooc_addtk
- 需要参数:
- testid(套题id)
- courseid(课程id)
- answers(答案)
- score(已得分数)
- userid(上传者id)
- zscore(总分数)
- overdate(套题截至日期)
- 返回参数:
- data
- code(状态码 1=更新答案 2=新增答案)
- func(使用的方法)
- 涉及数据库:ooc_tk
PHP代码:
$data = array('code' => 1, 'func' => 'insert');
$testid = request()->post('testid');
$courseid = request()->post('courseid');
$answers = request()->post('answers');
$score = request()->post('score');
$zscore = request()->post('zscore');
$userid = request()->post('userid');
$overdate = request()->post('overdate');
$tk_res = Db::name('ooc_tk')->where(['testid' => $testid])->select();
$data = ['testid' => $testid, 'courseid' => $courseid, 'answers' => $answers, 'zscore' => $zscore, 'score' => $score, 'userid' => $userid, 'overdate' => $overdate, 'date' => date("Y-m-d H:i:s")];
if (!$tk_res->isEmpty()) {
//如果题库里面有该题的答案了
foreach ($tk_res as $r) {
Db::name('ooc_tk')->where(['testid' => $testid])->update(['answers' => $answers, 'score' => $score, 'zscore' => $zscore, 'date' => date("Y-m-d H:i:s")]);
$data['func'] = "update";
}
} else {
Db::name('ooc_tk')->insert($data);
$data['code'] = 2;
}
return $data;
5.题库信息查询
设计思路:用户可以根据课程ID号查询题库中是否存在该课程的相应答案
JS部分:
- 发送方法:POST
- 发送参数:
- courseid(课程id)
- 接收参数:
- data
- code(状态码)
- num(套题数量)
- overdate(过期日期)
数据库部分: ooc_tkinfo
字段名 | 类型 | 注释 |
---|---|---|
id | int | 表内唯一id |
courseid | int | 课程id |
num | int | 套题数量 |
overdate | datetime | 课程结束时间 |
PHP部分:
- 接收方法:POST
- 方法命名:tk_info
- 需要参数:
- courseid(课程id)
- 返回参数:
- data
- code(状态码)
- num(套题数量)
- overdate(过期日期)
- 涉及数据库:ooc_tkinfo
PHP代码:
$courseid=request()->post("courseid");
$data = array(
'code' => 1,
'num' => 0,
'overdate' => null
);
$res = Db::name('ooc_tkinfo')->where(['courseid'=>$courseid])->select();
if(!$res->isEmpty()){
foreach($res as $r){
$data['num']=$r['num'];
$data['overdate']=$r['overdate'];
}
}else
{
$data['code']=0;
}
return $data;
三、脚本设计及编写
1.利用学习日志添加接口编写对应脚本方法
变量说明
coursearr:[{ chapterId//资源的节ID sectionId//资源的章ID }]//保存了所有需要学习的资源的id信息
a() {
var that = this;
$.ajax({
type: "post",
url: '学习日志添加接口',
contentType: 'application/json;charset=utf-8',
data: "{\"username\":\"" + username+ "\",\"ownerId\":" + ownerId + ",\"parentId\":\"" + parentId + "\",\"action\":0,\"courseId\":\"" + courseid + "\",\"sectionId\":\"" + sectionId + "\",\"chapterId\":\"" + chapterId + "\"}",
dataType: "json",
success: function(r) {
if (r.code == 0) {
//成功向服务器添加该资源的学习记录
}
if (r.code == 3) {
//添加学习记录失败
}
if (r.code == 2) {
//已添加学习记录
}
g++;
if (g < coursearr.length) {
setTimeout(function() {
that.a();//递归
},
30000);
} else {
//资源已刷完
}
}
})
}