动手写自动挂机刷课脚本
失踪人口又回来了,🤣🤣
受疫情影响,所有的课程都是以网课形式存在,后又要自己选一个通识网课,这无疑让本就悲惨的认识雪上加霜,于是,我研究了一下智慧树的部分api接口,编写了一个较简单的挂机脚本。此篇文章以做记录。
附上shi'p视频播放界面的api请求列表
api request
其中
-
getLoginUserInfo
为get请求,- 附带参数 dateFormate: 时间戳,
-
返回的数据中包含登录者的姓名和一个
uuid
, 这个uuid 比较重要后面的几个请求都需要以它作为参数传递 -
videolist
为post请求, -
携带参数 recruitAndCourseId: 这个可以从地址栏中获取,目测是对课程号处理过后得到的值,uuid:上面提到过的uuid ,dateFormate:时间戳,
-
返回数据为播放列表的信息 包含视频id 课程id 课程名称等等,本次用到的是其中的
name
lessonId
id
内容。处理过滤后存储在一个map中 -
loadVideoPointerInfo
为post请求 -
携带参数 lessonId: 当前播放内容的小节课程id 非总的课程id ,lessonVideoId: 播放的视频id (* 此字段非必带,仅播放的小节课程处于小课程时才需要用以区分 例如当2.3作为单独一小节时 不需要此字段,若2.3 有子课程时,2.3.1 2.3.2....均需要该字段 )uuid: 第一个api中的,dateFormate*: 时间戳
-
返回数据 返回此视频所有的答题时间点,即多少分多少秒会出现答题
-
lessonPopupExam
为post请求- 携带参数 lessonId: 同上 lessonVideoId: 同上 time: 答题的时间点 可由上一个api返回数据中获取 uuid: 同上 dateFormate:同上
- 返回数据 该数据返回问题及答案 选项列表中有个result字段 该字段为1则说明该选项时答案之一。
基于以上四个api在对页面的标签进行选择,通过jquery对页面进行操作 模拟出用户的点击操作,api请求我没有过多的进行分析和使用,因为这个数据是直接发送回服务端,请求太多容易出纰漏,被发现出端倪,所以脚本中的网络请求则能省就省。
于是有了如下的第一个版本
代码质量有点低,各位就当看个乐吧,望各位轻点喷。
关于如何使用的问题 那可就简单了 把你写好的代码编译成js 然后复制到网页开发者工具的控制台中,回车运行即可~~~
run ..............................
declare let $;
let courseId: string;
let lessonVideoId: number;
let needVideoId: boolean;
let uid = null;
let map = new Map();
let runTime = 0;
let autoAnswerTimes = 0;
// @ts-ignore
class Time {
private _hour: number;
private _minute: number;
private _second: number;
constructor(time: string) {
this._hour = parseInt(time.split(`:`)[0]);
this._minute = parseInt(time.split(`:`)[1]);
this._second = parseInt(time.split(`:`)[2]);
}
set hour(value: number) {
this._hour = value;
}
set minute(value: number) {
this._minute = value;
}
set second(value: number) {
this._second = value;
}
tosec() {
return this._hour * 3600 + this._minute * 60 + this._second;
}
}
class Course {
name: string;
lessonId: number;
lessonVideoId: number;
isSmallLesson: boolean;
constructor(name: string, lessonId: number, lessonVideoId: number, isSmallLesson: boolean) {
this.name = name;
this.lessonId = lessonId;
this.lessonVideoId = lessonVideoId ? lessonVideoId : null;
this.isSmallLesson = isSmallLesson;
}
}
let isPlaying: boolean = true;
let needAnswer: boolean = false;
let currentTime: Time;
let totalTime: Time;
let currentPlayIndex = -1;
getUuid();
setInterval(function () {
console.clear();
getCurrentCourseId();
updateRecTime();
checkNeedAnswer();
preporeInfo();
if (needAnswer) {
answerT();
}
if (currentTime.tosec() === totalTime.tosec()) {
// 点击播放下一节
clickNextNode();
getCourseId();
} else {
if (!isPlaying) {
clickScreenTocontinue();
}
}
record(8);
}, 8000);
function record(space: number) {
runTime += space;
console.log(`已使用:${runTime}秒\n已答题:${autoAnswerTimes}次`)
}
function getCourseId() {
// 获取courseId
$.ajax({
type: "POST",
url: "https://studyservice.zhihuishu.com/learning/videolist",
data: {
recruitAndCourseId: GetQueryString('recruitAndCourseId'),
uuid: uid,
dateFormate: Date.parse(Date())
},
contentType: "application/x-www-form-urlencoded",
xhrFields: {
withCredentials: true
},
success: function (data1) {
// 获取学习进度
data1.data.videoChapterDtos.forEach(item => {
item.videoLessons.forEach(item2 => {
if (item2.ishaveChildrenLesson) {
item2.videoSmallLessons.forEach(item3 => {
map.set(item3.id, new Course(item3.name, item3.lessonId, item3.id, true))
})
} else {
map.set(item2.id, new Course(item2.name, item2.id, item2.id, false))
}
})
});
}
})
}
function getCurrentCourseId() {
let text = $(".list .current_play").text();
map.forEach(value => {
if (text.indexOf(value.name) != -1) {
courseId = value.lessonId;
lessonVideoId = value.lessonVideoId;
needVideoId = value.isSmallLesson;
return;
}
});
// console.log(`courseId=${courseId}`)
}
function getUuid() {
$.ajax({
type: "GET",
url: "https://onlineservice.zhihuishu.com/login/getLoginUserInfo",
xhrFields: {
withCredentials: true
},
success: function (data) {
if (data.result == null || data.result.uuid == null) {
return
}
uid = data.result.uuid;
getCourseId();
}
});
}
let lastTimePlaying = new Time("00:00:00");
/**
* 记录播放时间和总时间
*/
function updateRecTime() {
currentTime = new Time($(".currentTime").text());
if (lastTimePlaying) {
isPlaying = lastTimePlaying.tosec() != currentTime.tosec();
console.log(isPlaying ? "播放中" : "暂停中");
}
totalTime = new Time($(".duration").text());
// console.log(`lastTimePlaying : ${lastTimePlaying.tosec()} \ncurrentTime: ${currentTime.tosec()} \ntotalTime: ${totalTime.tosec()}`);
lastTimePlaying = currentTime;
}
let array;
function preporeInfo() {
let list = $(".list .clearfix, .video").toArray();
array = Array();
list.forEach((item, index) => {
if (!$(item).hasClass('video')) {
// 删除title
return;
}
array.push(item);
});
array.forEach((item, index) => {
if ($(item).hasClass('current_play')) {
currentPlayIndex = index;
}
});
}
/**
* 点击播放下一节
*/
function clickNextNode() {
// 当前正在播放的item
preporeInfo();
$(array[currentPlayIndex + 1]).click();
clickScreenTocontinue();
}
/**
* 检查是否需要做题
*/
function checkNeedAnswer() {
$(".el-dialog__header h4").toArray().forEach(item => {
//console.log($(item).text());
if ($(item).text() === "弹题测验") {
needAnswer = true;
}
});
}
/**
* 答题
* 答案在api中
*/
function answerT() {
let dataTime: string = null;
let request: {
lessonId: string,
uuid: string,
dateFormate: number,
lessonVideoId?: number;
} = {
lessonId: courseId,
uuid: uid,
dateFormate: Date.parse(Date()),
};
if (needVideoId) {
request.lessonVideoId = lessonVideoId;
}
// 获取暂停时间片
$.ajax({
type: "POST",
url: "https://studyservice.zhihuishu.com/popupAnswer/loadVideoPointerInfo",
data: request,
contentType: "application/x-www-form-urlencoded",
xhrFields: {
withCredentials: true
},
success: function (data) {
dataTime = data.data.questionPoint[0].timers;
if (dataTime == null) {
console.log("获取答题时间点失败");
return
}
let req: {
lessonId: string
time: string
uuid: string,
dateFormate: number,
lessonVideoId?: number
} = {
lessonId: courseId,
time: dataTime,
uuid: uid,
dateFormate: Date.parse(Date()),
};
if (needVideoId) {
req.lessonVideoId = lessonVideoId;
}
// 获取答案
$.ajax({
type: "POST",
url: "https://studyservice.zhihuishu.com/popupAnswer/lessonPopupExam",
data: req,
contentType: "application/x-www-form-urlencoded",
xhrFields: {
withCredentials: true
},
success: function (data) {
// 题目选项
let answers = Array();
let t = data.data.lessonTestQuestionUseInterfaceDtos[0].testQuestion.questionOptions;
let ans = "";
t.forEach((item, index) => {
if (item.result === "1") {
ans += (item.content + "\t");
answers.push(index);
}
});
console.log("答案:" + ans);
clickAnswer(answers);
}
})
}
});
}
// 点击选项
function clickAnswer(answers) {
let liArray = $(".el-dialog .el-dialog__body .topic-list .topic-item").toArray();
answers.forEach((item) => {
// 点击选项
if (!$($(liArray[item])[0].lastChild).hasClass('active')) {
$(liArray[item]).click()
}
});
// 点击关闭
$(".el-dialog .el-dialog__footer .btn").toArray().forEach(item => {
if ($(item)[0].className === "btn") {
$(item).click()
}
});
autoAnswerTimes++;
needAnswer = false;
// 点击播放
clickScreenTocontinue();
}
// 点击播放
function clickScreenTocontinue() {
$(".videoArea").click();
}
function GetQueryString(name) {
let query = window.location.href.substr(window.location.href.indexOf('?') + 1);
let vars = query.split("&");
for (let i = 0; i < vars.length; i++) {
let pair = vars[i].split("=");
if (pair[0] == name) {
return pair[1];
}
}
return;
}
网友评论