脚本①(油猴Tampermonkey插件)

// ==UserScript==
// @name         熊猫超星网课助手
// @namespace    xiongmao
// @version      9.0.1
// @description  自动挂机看尔雅MOOC,支持视频、音频、文档、图书自动完成,章节测验自动答题提交,支持自动切换任务点、挂机阅读时长、自动登录等,解除各类功能限制,开放自定义参数
// @author       xiongmao
// @match        *://*.chaoxing.com/*
// @match        *://*.edu.cn/*
// @connect      api.xmlm8.com
// @run-at       document-end
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @grant        GM_setClipboard
// @license      MIT
// ==/UserScript==

// 设置修改后,需要刷新或重新打开网课页面才会生效
var setting = {
    // 8E3 == 8000,科学记数法,表示毫秒数
    time: 8E3 // 默认响应速度为8秒,不建议小于5秒
    ,token: \'\' // 捐助用户可以使用定制功能,更精准的匹配答案,此处填写捐助后获取的识别码
    ,review: 0 // 复习模式,完整挂机视频(音频)时长,支持挂机任务点已完成的视频和音频,默认关闭
    ,queue: 1 // 队列模式,开启后任务点逐一完成,关闭则单页面所有任务点同时进行,默认开启

    // 1代表开启,0代表关闭
    ,video: 1 // 视频支持后台、切换窗口不暂停,支持多视频,默认开启
    ,work: 0 // 自动答题功能(章节测验),作业需要手动开启查询,高准确率,默认开启
    ,audio: 1 // 音频自动播放,与视频功能共享vol和rate参数,默认开启
    ,book: 1 // 图书阅读任务点,非课程阅读任务点,默认开启
    ,docs: 1 // 文档阅读任务点,PPT类任务点自动完成阅读任务,默认开启
    // 本区域参数,上方为任务点功能,下方为独立功能
    ,jump: 1 // 自动切换任务点、章节、课程(需要配置course参数),默认开启
    ,read: \'0\' // 挂机课程阅读时间,单位是分钟,\'65\'代表挂机65分钟,请手动打开阅读页面,默认\'0\'分钟
    ,face: 0 // 解除面部识别(不支持二维码类面部采集),此功能仅为临时解除,默认关闭
    ,total: 0 // 显示课程进度的统计数据,在学习进度页面的上方展示,默认关闭

    // 仅开启video(audio)时,修改此处才会生效
    ,line: \'公网1\' // 视频播放的默认资源线路,此功能适用于系统默认线路无资源,默认\'公网1\'
    ,http: \'标清\' // 视频播放的默认清晰度,无效参数则使用系统默认清晰度,默认\'标清\'
    // 本区域参数,上方为video功能独享,下方为audio功能共享
    ,vol: \'0\' // 默认音量的百分数,设定范围:[0,100],\'0\'为静音,默认\'0\'
    ,rate: \'3\' // 视频播放默认倍率,参数范围0∪[0.0625,16],\'0\'为秒过,默认\'1\'倍

    // 仅开启work时,修改此处才会生效
    ,auto: 0 // 答题完成后自动提交,默认关闭 改为1开启
    ,none: 0 // 无匹配答案时执行默认操作,关闭后若题目无匹配答案则会暂时保存已作答的题目,默认开启
    ,scale: 0 // 富文本编辑器高度自动拉伸,用于文本类题目,答题框根据内容自动调整大小,默认关闭

    // 仅开启jump时,修改此处才会生效
    ,course: 0 // 当前课程完成后自动切换课程,仅支持按照根目录课程顺序切换,默认开启
    ,lock: 1 // 跳过未开放(图标是锁)的章节,即闯关模式或定时发放的任务点,默认开启

    // 自动登录功能配置区
    ,school: \'账号为手机号可以不修改此参数\' // 学校/单位/机构码,要求完整有效可查询,例如\'清华大学\'
    ,username: \'\' // 学号/工号/借书证号(邮箱/手机号/账号),例如\'2018010101\',默认\'\'
    ,password: \'\' // 密码,例如\'123456\',默认\'\'
},
_self = unsafeWindow,
url = location.pathname,
top = _self;

if (url != \'/studyApp/studying\' && top != _self.top) document.domain = location.host.replace(/.+?\./, \'\');

try {
    while (top != _self.top) {
        top = top.parent.document ? top.parent : _self.top;
        if (top.location.pathname == \'/mycourse/studentstudy\') break;
    }
} catch (err) {
    // console.log(err);
    top = _self;
}

var $ = _self.jQuery || top.jQuery,
parent = _self == top ? self : _self.parent,
Ext = _self.Ext || parent.Ext || {},
UE = _self.UE,
vjs = _self.videojs;

String.prototype.toCDB = function() {
    return this.replace(/\s/g, \'\').replace(/[\uff01-\uff5e]/g, function(str) {
        return String.fromCharCode(str.charCodeAt(0) - 65248);
    }).replace(/[“”]/g, \'"\').replace(/[‘’]/g, "\'").replace(/。/g, \'.\');
};

setting.normal = \'\'; // \':visible\'
// setting.time += Math.ceil(setting.time * Math.random()) - setting.time / 2;
setting.job = [\':not(*)\'];

setting.video && setting.job.push(\'iframe[src*="/video/index.html"]\');
setting.work && setting.job.push(\'iframe[src*="/work/index.html"]\');
setting.audio && setting.job.push(\'iframe[src*="/audio/index.html"]\');
setting.book && setting.job.push(\'iframe[src*="/innerbook/index.html"]\');
setting.docs && setting.job.push(\'iframe[src*="/ppt/index.html"]\', \'iframe[src*="/pdf/index.html"]\');

setting.tip = !setting.queue || top != _self && jobSort($ || Ext.query);

if (url == \'/mycourse/studentstudy\') {
    _self.checkMobileBrowerLearn = $.noop;
    var classId = location.search.match(/cla[zs]{2}id=(\d+)/i)[1] || 0,
    courseId = _self.courseId || location.search.match(/courseId=(\d+)/i)[1] || 0;
    setting.lock || $(\'#coursetree\').on(\'click\', \'[onclick*=void], [href*=void]\', function() {
        _self.getTeacherAjax(courseId, classId, $(this).parent().attr(\'id\').slice(3));
    });
} else if (url == \'/ananas/modules/video/index.html\' && setting.video) {
    if (setting.review) _self.greenligth = Ext.emptyFn;
    checkPlayer(_self.supportH5Video());
} else if (url == \'/work/doHomeWorkNew\' || url == \'/api/work\' || url == \'/work/addStudentWorkNewWeb\') {
    if (!UE) {
        var len = ($ || Ext.query || Array)(\'font:contains(未登录)\', document).length;
        setTimeout(len == 1 ? top.location.reload : parent.greenligth, setting.time);
    } else if (setting.work) {
        setTimeout(relieveLimit, 0);
        beforeFind();
    }
} else if (url == \'/ananas/modules/audio/index.html\' && setting.audio) {
    if (setting.review) _self.greenligth = Ext.emptyFn;
    _self.videojs = hookAudio;
    hookAudio.xhr = vjs.xhr;
} else if (url == \'/ananas/modules/innerbook/index.html\' && setting.book && setting.tip) {
    setTimeout(function() {
        _self.setting ? _self.top.onchangepage(_self.getFrameAttr(\'end\')) : _self.greenligth();
    }, setting.time);
} else if (url.match(/^\/ananas\/modules\/(ppt|pdf)\/index\.html$/) && setting.docs && setting.tip) {
    setTimeout(function() {
        _self.setting ? _self.finishJob() : _self.greenligth();
    }, setting.time);
    frameElement.setAttribute(\'download\', 1);
} else if (url == \'/knowledge/cards\') {
    $ && checkToNext();
} else if (url.match(/^\/(course|zt)\/\d+\.html$/)) {
    setTimeout(function() {
        +setting.read && _self.sendLogs && $(\'.course_section:eq(0) .chapterText\').click();
    }, setting.time);
} else if (url == \'/ztnodedetailcontroller/visitnodedetail\') {
    setting.read *= 60 / $(\'.course_section\').length;
    setting.read && _self.sendLogs && autoRead();
} else if (url == \'/mycourse/studentcourse\') {
    var gv = location.search.match(/d=\d+&/g);
    setting.total && $(\'<a>\', {
        href: \'/moocAnalysis/chapterStatisticByUser?classI\' + gv[1] + \'courseI\' + gv[0] + \'userId=\' + _self.getCookie(\'_uid\') + \'&ut=s\',
        target: \'_blank\',
        title: \'点击查看章节统计\',
        style: \'margin: 0 25px;\',
        html: \'本课程共\' + $(\'.icon\').length + \'节,剩余\' + $(\'em:not(.openlock)\').length + \'节未完成\'
    }).appendTo(\'.zt_logo\').parent().width(\'auto\');
} else if (url.match(/^\/visit\/(courses|interaction)$/)) {
    setting.face && $(\'.zmodel\').on(\'click\', \'[onclick^=openFaceTip]\', DisplayURL);
} else if (location.host.match(/^passport2/)) {
    setting.username && getSchoolId();
} else if (location.hostname == \'i.mooc.chaoxing.com\') {
    _self.layui.use(\'layer\', function() {
        this.layer.open({content: \'拖动进度条、倍速播放、秒过会导致不良记录!题库在慢慢补充,搜不到的题目系统会在次日进行自动补充\', title: \'超星网课助手提示\', btn: \'我已知悉\', offset: \'t\', closeBtn: 0});
    });
} else if (url == \'/widget/pcvote/goStudentVotePage\') {
    $(\':checked\').click();
    $(\'.StudentTimu\').each(function(index) {
        var ans = _self.questionlist[index].answer;
        $(\':radio, :checkbox\', this).each(function(num) {
            ans[num].isanswer && this.click();
        });
        $(\':text\', this).val(function(num) {
            return $(ans[num].content).text().trim();
        });
    });
} else if (url == \'/work/selectWorkQuestionYiPiYue\') {
    submitAnswer(getIframe().parent(), $.extend(true, [], parent._data));
}

function getIframe(tip, win, job) {
    if (!$) return Ext.get(frameElement || []).parent().child(\'.ans-job-icon\') || Ext.get([]);
    do {
        win = win ? win.parent : _self;
        job = $(win.frameElement).prevAll(\'.ans-job-icon\');
    } while (!job.length && win.parent.frameElement);
    return tip ? win : job;
}

function jobSort($) {
    var fn = $.fn ? [getIframe(1), \'length\'] : [self, \'dom\'],
    sel = setting.job.join(\', :not(.ans-job-finished) > .ans-job-icon\' + setting.normal + \' ~ \');
    if ($(sel, fn[0].parent.document)[0] == fn[0].frameElement) return true;
    if (!getIframe()[fn[1]] || getIframe().parent().is(\'.ans-job-finished\')) return null;
    setInterval(function() {
        $(sel, fn[0].parent.document)[0] == fn[0].frameElement && fn[0].location.reload();
    }, setting.time);
}

function checkPlayer(tip) {
    _self.videojs = hookVideo;
    hookVideo.xhr = vjs.xhr;
    Ext.isSogou = Ext.isIos = Ext.isAndroid = false;
    var data = Ext.decode(_self.config(\'data\')) || {};
    delete data.danmaku;
    data.doublespeed = 1;
    frameElement.setAttribute(\'data\', Ext.encode(data));
    if (tip) return;
    _self.supportH5Video = function() {return true;};
    alert(\'此浏览器不支持html5播放器,请更换浏览器\');
}

function hookVideo() {
    _self.alert = console.log;
    var config = arguments[1],
    line = Ext.Array.filter(Ext.Array.map(config.playlines, function(value, index) {
        return value.label == setting.line && index;
    }), function(value) {
        return Ext.isNumber(value);
    })[0] || 0,
    http = Ext.Array.filter(config.sources, function(value) {
        return value.label == setting.http;
    })[0];
    config.playlines.unshift(config.playlines[line]);
    config.playlines.splice(line + 1, 1);
    config.plugins.videoJsResolutionSwitcher.default = http ? http.res : 360;
    config.plugins.studyControl.enableSwitchWindow = 1;
    config.plugins.timelineObjects.url = \'/richvideo/initdatawithviewer?\';
    config.plugins.seekBarControl.enableFastForward = 1;
    if (!setting.queue) delete config.plugins.studyControl;
    // config.preload = setting.tip ? \'auto\' : \'none\';
    var player = vjs.apply(this, arguments),
    a = \'<a href="https://d0.ananas.chaoxing.com/download/\' + _self.config(\'objectid\') + \'" target="_blank">\',
    img = \'<img src="https://d0.ananas.chaoxing.com/download/e363b256c0e9bc5bd8266bf99dd6d6bb" style="margin: 6px 0 0 6px;">\';
    player.volume(Math.round(setting.vol) / 100 || 0);
    Ext.get(player.controlBar.addChild(\'Button\').el_).setHTML(a + img + \'</a>\').dom.title = \'下载视频\';
    player.on(\'loadstart\', function() {
        setting.tip && this.play().catch(Ext.emptyFn);
        this.playbackRate(setting.rate > 16 || setting.rate < 0.0625 ? 1 : setting.rate);
    });
    player.one([\'loadedmetadata\', \'firstplay\'], function() {
        setting.two = setting.rate === \'0\' && setting.two < 1;
        setting.two && config.plugins.seekBarControl.sendLog(this.children_[0], \'ended\', Math.floor(this.cache_.duration));
    });
    player.on(\'ended\', function() {
        Ext.fly(frameElement).parent().addCls(\'ans-job-finished\');
    });
    return player;
}

function hookAudio() {
    _self.alert = console.log;
    var config = arguments[1];
    config.plugins.studyControl.enableSwitchWindow = 1;
    config.plugins.seekBarControl.enableFastForward = 1;
    if (!setting.queue) delete config.plugins.studyControl;
    var player = vjs.apply(this, arguments),
    a = \'<a href="https://d0.ananas.chaoxing.com/download/\' + _self.config(\'objectid\') + \'" target="_blank">\',
    img = \'<img src="https://d0.ananas.chaoxing.com/download/e363b256c0e9bc5bd8266bf99dd6d6bb" style="margin: 6px 0 0 6px;">\';
    player.volume(Math.round(setting.vol) / 100 || 0);
    player.playbackRate(setting.rate > 16 || setting.rate < 0.0625 ? 1 : setting.rate);
    Ext.get(player.controlBar.addChild(\'Button\').el_).setHTML(a + img + \'</a>\').dom.title = \'下载音频\';
    player.on(\'loadeddata\', function() {
        setting.tip && this.play().catch(Ext.emptyFn);
    });
    player.one(\'firstplay\', function() {
        setting.rate === \'0\' && config.plugins.seekBarControl.sendLog(this.children_[0], \'ended\', Math.floor(this.cache_.duration));
    });
    player.on(\'ended\', function() {
        Ext.fly(frameElement).parent().addCls(\'ans-job-finished\');
    });
    return player;
}

function relieveLimit() {
    if (setting.scale) _self.UEDITOR_CONFIG.scaleEnabled = false;
    $.each(UE.instants, function() {
        var key = this.key;
        this.ready(function() {
            this.destroy();
            UE.getEditor(key);
        });
    });
}

function beforeFind() {
    setting.regl = parent.greenligth || $.noop;
    if ($.type(parent._data) == \'array\') return setting.regl();
    setting.div = $(
        \'<div style="border: 2px dashed rgb(0, 85, 68); width: 330px; position: fixed; top: 0; right: 0; z-index: 99999; background-color: rgba(70, 196, 38, 0.6); overflow-x: auto;">\' +
            \'<span style="font-size: medium;"></span>\' +
            \'<div style="font-size: medium;">正在搜索答案...</div>\' +
            \'<button style="margin-right: 10px;">暂停答题</button>\' +
            \'<button style="margin-right: 10px;">\' + (setting.auto ? \'取消本次自动提交\' : \'开启本次自动提交\') + \'</button>\' +
            \'<button style="margin-right: 10px;">重新查询</button>\' +
            \'<button>折叠面板</button>\' +
            \'<div style="max-height: 300px; overflow-y: auto;">\' +
                \'<table border="1" style="font-size: 12px;">\' +
                    \'<thead>\' +
                        \'<tr>\' +
                            \'<th style="width: 25px; min-width: 25px;">题号</th>\' +
                            \'<th style="width: 60%; min-width: 130px;">题目(点击可复制)</th>\' +
                            \'<th style="min-width: 130px;">答案(点击可复制)</th>\' +
                        \'</tr>\' +
                    \'</thead>\' +
                    \'<tfoot style="display: none;">\' +
                        \'<tr>\' +
                            \'<th colspan="3">答案提示框 已折叠</th>\' +
                        \'</tr>\' +
                    \'</tfoot>\' +
                    \'<tbody>\' +
                        \'<tr>\' +
                            \'<td colspan="3" style="display: none;"></td>\' +
                        \'</tr>\' +
                    \'</tbody>\' +
                \'</table>\' +
            \'</div>\' +
        \'</div>\'
    ).appendTo(\'body\').on(\'click\', \'button, td\', function() {
        var len = $(this).prevAll(\'button\').length;
        if (this.nodeName == \'TD\') {
            $(this).prev().length && GM_setClipboard($(this).text());
        } else if (!$(this).siblings().length) {
            $(this).parent().text(\'正在搜索答案...\');
            setting.num++;
        } else if (len === 0) {
            if (setting.loop) {
                clearInterval(setting.loop);
                delete setting.loop;
                len = [\'已暂停搜索\', \'继续答题\'];
            } else {
                setting.loop = setInterval(findAnswer, setting.time);
                len = [\'正在搜索答案...\', \'暂停答题\'];
            }
            setting.div.children(\'div:eq(0)\').html(function() {
                return $(this).data(\'html\') || len[0];
            }).removeData(\'html\');
            $(this).html(len[1]);
        } else if (len == 1) {
            setting.auto = !setting.auto;
            $(this).html(setting.auto ? \'取消本次自动提交\' : \'开启本次自动提交\');
        } else if (len == 2) {
            parent.location.reload();
        } else if (len == 3) {
            setting.div.find(\'tbody, tfoot\').toggle();
        }
    }).find(\'table, td, th\').css(\'border\', \'1px solid\').end();
    setting.lose = setting.num = 0;
    setting.data = parent._data = [];
    setting.over = \'<button style="margin-right: 10px;">跳过此题</button>\';
    setting.curs = $(\'script:contains(courseName)\', top.document).text().match(/courseName:\\'(.+?)\\'|$/)[1] || $(\'h1\').text().trim() || \'无\';
    setting.loop = setInterval(findAnswer, setting.time);
    var tip = ({undefined: \'任务点排队中\', null: \'等待切换中\'})[setting.tip];
    tip && setting.div.children(\'div:eq(0)\').data(\'html\', tip).siblings(\'button:eq(0)\').click();
}

function findAnswer() {
    if (setting.num >= $(\'.TiMu\').length) {
        var arr = setting.lose ? [\'共有 <font color="red">\' + setting.lose + \'</font> 道题目待完善(已深色标注)\', saveThis] : [\'答题已完成\', submitThis];
        setting.div.children(\'div:eq(0)\').data(\'html\', arr[0]).siblings(\'button:eq(0)\').hide().click();
        return setTimeout(arr[1], setting.time);
    }
    var $TiMu = $(\'.TiMu\').eq(setting.num),
    question = filterImg($TiMu.find(\'.Zy_TItle:eq(0) .clearfix\')).replace(/^【.*?】\s*/, \'\').replace(/\s*(\d+\.\d+分)$/, \'\').replace(/[(]\s*[)]。$/,\'\').replace(/(\s*)。$/,\'\').replace(/[(]\s*[)]$/,\'\').replace(/(\s*)$/,\'\'),
    type = $TiMu.find(\'input[name^=answertype]:eq(0)\').val() || \'-1\';


    //setting.div.children(\'div:eq(0)\').text(encodeURIComponent(question)+\'正在搜索答案...\');


    GM_xmlhttpRequest({
        method: \'GET\',
        url: \'http://api.xmlm8.com/tp/tk.php?t=\'+ encodeURIComponent(question),
        headers: {
            \'Content-type\': \'application/x-www-form-urlencoded\'
        },
        timeout: setting.time,
        onload: function(xhr) {
            if (!setting.loop) {
            } else if (xhr.status == 200) {
                var obj = $.parseJSON(xhr.responseText) || {};
                if (obj.code == 1) {
                    setting.div.children(\'div:eq(0)\').text(\'正在搜索答案...\');
                    var td = \'<td style="border: 1px solid;\',
                    answer = String(obj.answer).replace(/&/g, \'&amp;\').replace(/<(?!img)/g, \'&lt;\');
                    obj.answer = /^http/.test(answer) ? \'<img src="\' + obj.answer + \'">\' : obj.answer;
                    $(
                        \'<tr>\' +
                            td + \' text-align: center;">\' + $TiMu.find(\'.Zy_TItle:eq(0) i\').text().trim() + \'</td>\' +
                            td + \'" title="点击可复制">\' + (question.match(\'<img\') ? question : question.replace(/&/g, \'&amp;\').replace(/</g, \'&lt\')) + \'</td>\' +
                            td + \'" title="点击可复制">\' + (/^http/.test(answer) ? obj.answer : \'\') + answer + \'</td>\' +
                        \'</tr>\'
                    ).appendTo(setting.div.find(\'tbody\')).css(\'background-color\', fillAnswer($TiMu.find(\'ul:eq(0)\').find(\'li\'), obj, type) ? \'\' : \'rgba(0, 150, 136, 0.6)\');
                    setting.data[setting.num++] = {
                        code: obj.code > 0 ? 1 : 0,
                        question: question,
                        option: obj.answer,
                        type: Number(type)
                    };
                } else {
                    setting.div.children(\'div:eq(0)\').html(setting.over + obj.answer || setting.over + \'服务器繁忙,正在重试...\');
                }
                setting.div.children(\'span\').html(obj.msg || \'\');
            } else if (xhr.status == 403) {
                var html = xhr.responseText.indexOf(\'{\') ? \'请求过于频繁,建议稍后再试\' : $.parseJSON(xhr.responseText).data;
                setting.div.children(\'div:eq(0)\').data(\'html\', html).siblings(\'button:eq(0)\').click();
            } else {
                setting.div.children(\'div:eq(0)\').html(setting.over + \'服务器异常,正在重试...\');
            }
        },
        ontimeout: function() {
            setting.loop && setting.div.children(\'div:eq(0)\').html(setting.over + \'服务器超时,正在重试...\');
        }
    });
}

function fillAnswer($li, obj, type) {
    var $input = $li.find(\':radio, :checkbox\'),
    str = String(obj.answer).toCDB() || new Date().toString(),
    data = str.split(/#|\x01|\|/),
    opt = obj.opt || str,
    state = setting.lose;
    // $li.find(\':radio:checked\').prop(\'checked\', false);
    obj.code > 0 && $input.each(function(index) {
        if (this.value == \'true\') {
            data.join().match(/(^|,)(正确|是|对|√|T|ri)(,|$)/) && this.click();
        } else if (this.value == \'false\') {
            data.join().match(/(^|,)(错误|否|错|×|F|wr)(,|$)/) && this.click();
        } else {
            var tip = filterImg($li.eq(index).find(\'.after\')).toCDB() || new Date().toString();
            Boolean($.inArray(tip, data) + 1 || (type == \'1\' && str.indexOf(tip) + 1)) == this.checked || this.click();
        }
    }).each(function() {
        if (!/^A?B?C?D?E?F?G?$/.test(opt)) return false;
        Boolean(opt.match(this.value)) == this.checked || this.click();
    });
    if (type.match(/^[013]$/)) {
        $input.is(\':checked\') || (setting.none ? ($input[Math.floor(Math.random() * $input.length)] || $()).click() : setting.lose++);
    } else if (type.match(/^(2|[4-9]|1[08])$/)) {
        data = String(obj.answer).split(/#|\x01|\|/);
        str = $li.end().find(\'textarea\').each(function(index) {
            index = (obj.code > 0 && data[index]) || \'\';
            UE.getEditor(this.name).setContent(index.trim());
        }).length;
        (obj.code > 0 && data.length == str) || setting.none || setting.lose++;
    } else {
        setting.none || setting.lose++;
    }
    return state == setting.lose;
}

function saveThis() {
    if (!setting.auto) return setTimeout(saveThis, setting.time);
    setting.div.children(\'button:lt(3)\').hide().eq(1).click();
    _self.alert = console.log;
    $(\'#tempsave\').click();
    setting.regl();
}

function submitThis() {
    if (!setting.auto) {
    } else if (!$(\'.Btn_blue_1:visible\').length) {
        setting.div.children(\'button:lt(3)\').hide().eq(1).click();
        return setting.regl();
    } else if ($(\'#confirmSubWin:visible\').length) {
        var btn = $(\'#tipContent + * > a\').offset() || {top: 0, left: 0},
        mouse = document.createEvent(\'MouseEvents\');
        btn = [btn.left + Math.ceil(Math.random() * 46), btn.top + Math.ceil(Math.random() * 26)];
        mouse.initMouseEvent(\'click\', true, true, document.defaultView, 0, 0, 0, btn[0], btn[1], false, false, false, false, 0, null);
        _self.event = $.extend(true, {}, mouse);
        delete _self.event.isTrusted;
        _self.form1submit();
    } else {
        $(\'.Btn_blue_1\')[0].click();
    }
    setTimeout(submitThis, Math.ceil(setting.time * Math.random()) * 2);
}

function checkToNext() {
    var $tip = $(setting.job.join(\', \'), document).prevAll(\'.ans-job-icon\' + setting.normal);
    setInterval(function() {
        $tip.parent(\':not(.ans-job-finished)\').length || setting.jump && toNext();
    }, setting.time);
}

function toNext() {
    var $cur = $(\'#cur\' + $(\'#chapterIdid\').val()),
    $tip = $(\'span.currents ~ span\'),
    sel = setting.review ? \'html\' : \'.blue\';
    if (!$cur.has(sel).length && $tip.length) return $tip.eq(0).click();
    $tip = $(\'.roundpointStudent, .roundpoint\').parent();
    $tip = $tip.slice($tip.index($cur) + 1).not(\':has(\' + sel + \')\');
    $tip.not(setting.lock ? \':has(.lock)\' : \'html\').find(\'span\').eq(0).click();
    $tip.length || setting.course && switchCourse();
}

function switchCourse() {
    GM_xmlhttpRequest({
        method: \'GET\',
        url: \'/visit/courses/study?isAjax=true&fileId=0&debug=\',
        headers: {
            \'Referer\': location.origin + \'/visit/courses\',
            \'X-Requested-With\': \'XMLHttpRequest\'
        },
        onload: function(xhr) {
            var list = $(\'h3 a[target]\', xhr.responseText).map(function() {
                return $(this).attr(\'href\');
            }),
            index = list.map(function(index) {
                return this.match(top.courseId) && index;
            }).filter(function() {
                return $.isNumeric(this);
            })[0] + 1 || 0;
            setting.course = list[index] ? goCourse(list[index]) : 0;
        }
    });
}

function goCourse(url) {
    GM_xmlhttpRequest({
        method: \'GET\',
        url: url,
        onload: function(xhr) {
            $.globalEval(\'location.href = "\' + $(\'.articlename a[href]\', xhr.responseText).attr(\'href\') + \'";\');
        }
    });
}

function autoRead() {
    $(\'html, body\').animate({
        scrollTop: $(document).height() - $(window).height()
    }, Math.round(setting.read) * 1E3, function() {
        $(\'.nodeItem.r i\').click();
    }).one(\'click\', \'#top\', function(event) {
        $(event.delegateTarget).stop();
    });
}

function DisplayURL() {
    _self.WAY.box.hide();
    var $li = $(this).closest(\'li\');
    $.get(\'/visit/goToCourseByFace\', {
        courseId: $li.find(\'input[name=courseId]\').val(),
        clazzId: $li.find(\'input[name=classId]\').val()
    }, function(data) {
        $li.find(\'[onclick^=openFaceTip]\').removeAttr(\'onclick\').attr({
            target: \'_blank\',
            href: $(data).filter(\'script:last\').text().match(/n\("(.+?)"/)[1]
        });
        alert(\'本课程已临时解除面部识别\');
    }, \'html\');
}

function getSchoolId() {
    var school = /^1\d{10}$/.test(setting.username) ? \'\' : setting.school;
    if (!isNaN(school)) return setTimeout(toLogin, setting.time, school);
    if (school == \'账号为手机号可以不修改此参数\') return alert(\'请修改school参数\');
    $.getJSON(\'/org/searchUnis?filter=\' + encodeURI(school) + \'&product=44\', function(data) {
        if (!data.result) return alert(\'学校查询错误\');
        var msg = $.grep(data.froms, function(value) {
            return value.name == school;
        })[0];
        msg ? setTimeout(toLogin, setting.time, msg.schoolid) : alert(\'学校名称不完整\');
    });
}

function toLogin(fid) {
    GM_xmlhttpRequest({
        method: \'GET\',
        url: \'/api/login?name=\' + setting.username + \'&pwd=\' + setting.password + \'&schoolid=\' + fid + \'&verify=0\',
        onload: function(xhr) {
            var obj = $.parseJSON(xhr.responseText) || {};
            obj.result ? location.href = decodeURIComponent($(\'#ref, #refer_0x001\').val()) : alert(obj.errorMsg || \'Error\');
        }
    });
}

function submitAnswer($job, data) {
    $job.removeClass(\'ans-job-finished\');
    data = data.length ? $(data) : $(\'.TiMu\').map(function() {
        var title = filterImg($(\'.Zy_TItle .clearfix\', this));
        return {
            question: title.replace(/^【.*?】\s*/, \'\'),
            type: ({单选题: 0, 多选题: 1, 填空题: 2, 判断题: 3})[title.match(/^【(.*?)】|$/)[1]]
        };
    });
    data = $.grep(data.map(function(index) {
        var $TiMu = $(\'.TiMu\').eq(index);
        if (!($.isPlainObject(this) && this.type < 4 && $TiMu.find(\'.fr\').length)) {
            return false;
        } else if (this.type == 2) {
            var $ans = $TiMu.find(\'.Py_tk, .Py_answer\').eq(0);
            if (!$TiMu.find(\'.cuo\').length && this.code) {
                return false;
            } else if (!$ans.find(\'.cuo\').length) {
                this.option = $ans.find(\'.clearfix\').map(function() {
                    return $(this).text().trim();
                }).get().join(\'#\') || \'无\';
            } else if (this.code) {
                this.code = -1;
            } else {
                return false;
            }
        } else if (this.type == 3) {
            var ans = $TiMu.find(\'.font20:last\').text();
            if ($TiMu.find(\'.cuo\').length) {
                this.option = ({\'√\': \'错误\', \'×\': \'正确\'})[ans] || \'无\';
            } else if (!this.code) {
                this.option = ({\'√\': \'正确\', \'×\': \'错误\'})[ans] || \'无\';
            } else {
                return false;
            }
        } else {
            var text = $TiMu.find(\'.Py_answer > span:eq(0)\').text();
            if ($TiMu.find(\'.dui\').length && this.code && !/^A?B?C?D?E?F?G?$/.test(this.option)) {
                return false;
            } else if ($TiMu.find(\'.dui\').length || text.match(\'正确答案\')) {
                text = text.match(/[A-G]/gi) || [];
                this.option = $.map(text, function(value) {
                    return filterImg($TiMu.find(\'.fl:contains(\' + value + \') + a\'));
                }).join(\'#\') || \'无\';
                this.key = text.join(\'\');
            } else if (this.code) {
                this.code = -1;
            } else {
                return false;
            }
        }
        return this;
    }), function(value) {
        return value && value.option != \'无\';
    });
    setting.curs = $(\'script:contains(courseName)\', top.document).text().match(/courseName:\\'(.+?)\\'|$/)[1] || $(\'h1\').text().trim() || \'无\';
    data.length && GM_xmlhttpRequest({
        method: \'POST\',
        url: \'http://mooc.forestpolice.org/upload/cx/\' + (setting.token || 0) + \'/?workRelationId=\' + $(\'#workId\').val(),
        headers: {
            \'Content-type\': \'application/x-www-form-urlencoded\'
        },
        data: \'course=\' + encodeURIComponent(setting.curs) + \'&data=\' + encodeURIComponent((Ext.encode || JSON.stringify)(data)) + \'&id=\' + $(\'#jobid\').val().slice(5)
    });
    $job.addClass(\'ans-job-finished\');
}
/*
function filterImg(dom) {
    return $(dom).clone().find(\'img[src]\').replaceWith(function() {
        return $(\'<p></p>\').text(\'<img src="\' + $(this).attr(\'src\') + \'">\');
    }).end().find(\'iframe[src]\').replaceWith(function() {
        return $(\'<p></p>\').text(\'<iframe src="\' + $(this).attr(\'src\') + \'"></irame>\');
    }).end().text().trim();
}
*/
function filterImg(dom) {
    return $(dom).clone().find(\'img[src]\').replaceWith(function() {
        return $(\'<p></p>\').text(\'\');
    }).end().find(\'iframe[src]\').replaceWith(function() {
        return $(\'<p></p>\').text(\'\');
    }).end().text().trim();
}

脚本②(油猴)

超星学习通油猴脚本
// ==UserScript==
// @name         超星网课助手(改)(查题可用)
// @version      4.5.7
// @namespace    coder_tq
// @description  自动挂机看尔雅MOOC,支持视频、音频、文档、图书自动完成,章节测验自动答题提交,支持自动切换任务点、挂机阅读时长、自动登录等,解除各类功能限制,开放自定义参数
// @author       coder_tq
// @match        *://*.chaoxing.com/*
// @match        *://*.edu.cn/*
// @match        *://*.nbdlib.cn/*
// @match        *://*.hnsyu.net/*
// @connect      cx.beaa.cn
// @connect      cx.icodef.com
// @run-at       document-end
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_setClipboard
// @license      MIT
// ==/UserScript==

// 设置修改后,需要刷新或重新打开网课页面才会生效
var setting = {
    // 5E3 == 5000,科学记数法,表示毫秒数
    time: 5E3 // 默认响应速度为5秒,不建议小于5秒
    ,token: \'\' // token可以增加并发次数,用来打码,采集题库奖励
    ,review: 0 // 复习模式,完整挂机视频(音频)时长,支持挂机任务点已完成的视频和音频,默认关闭
    ,queue: 1 // 队列模式,开启后任务点逐一完成,关闭则单页面所有任务点同时进行,默认开启

    // 1代表开启,0代表关闭
    ,video: 1 // 视频支持后台、切换窗口不暂停,支持多视频,默认开启
    ,work: 0 // 自动答题功能(章节测验),作业需要手动开启查询,高准确率,默认开启
    ,audio: 1 // 音频自动播放,与视频功能共享vol和rate参数,默认开启
    ,book: 1 // 图书阅读任务点,非课程阅读任务点,默认开启
    ,docs: 1 // 文档阅读任务点,PPT类任务点自动完成阅读任务,默认开启
    // 本区域参数,上方为任务点功能,下方为独立功能
    ,jump: 1 // 自动切换任务点、章节、课程(需要配置course参数),默认开启
    ,read: \'65\' // 挂机课程阅读时间,单位是分钟,\'65\'代表挂机65分钟,请手动打开阅读页面,默认\'65\'分钟
    ,face: 1 // 解除面部识别(不支持二维码类面部采集),此功能仅为临时解除,默认开启
    ,total: 1 // 显示课程进度的统计数据,在学习进度页面的上方展示,默认开启

    // 仅开启video(audio)时,修改此处才会生效
    ,line: \'公网1\' // 视频播放的默认资源线路,此功能适用于系统默认线路无资源,默认\'公网1\'
    ,http: \'标清\' // 视频播放的默认清晰度,无效参数则使用系统默认清晰度,默认\'标清\'
    // 本区域参数,上方为video功能独享,下方为audio功能共享
    ,vol: \'0\' // 默认音量的百分数,设定范围:[0,100],\'0\'为静音,默认\'0\'
    ,rate: \'3\' // 视频播放默认倍率,参数范围0∪[0.0625,16],\'0\'为秒过,默认\'1\'倍

    // 仅开启work时,修改此处才会生效
    ,auto: 0 // 答题完成后自动提交,默认关闭
    ,none: 0 // 无匹配答案时执行默认操作,关闭后若题目无匹配答案则会暂时保存已作答的题目,默认开启
    ,scale: 0 // 富文本编辑器高度自动拉伸,用于文本类题目,答题框根据内容自动调整大小,默认关闭

    // 仅开启jump时,修改此处才会生效
    ,course: 0 // 当前课程完成后自动切换课程,仅支持按照根目录课程顺序切换,默认开启
    ,lock: 1 // 跳过未开放(图标是锁)的章节,即闯关模式或定时发放的任务点,默认开启

    // 自动登录功能配置区
    ,school: \'账号为手机号可以不修改此参数\' // 学校/单位/机构码,要求完整有效可查询,例如\'清华大学\'
    ,username: \'\' // 学号/工号/借书证号(邮箱/手机号/账号),例如\'2018010101\',默认\'\'
    ,password: \'\' // 密码,例如\'123456\',默认\'\'

    // 题库接口配置区
    ,tk_num: 0 // 题库接口,默认0
},
    _self = unsafeWindow,
    url = location.pathname,
    top = _self;


setting.tk_num = GM_getValue(\'tk_num\');
setting.tk_num = setting.tk_num == undefined ? 1:setting.tk_num;
setting.tk_num = isNaN(setting.tk_num)? 1:setting.tk_num;


if (url != \'/studyApp/studying\' && top != _self.top) document.domain = location.host.replace(/.+?\./, \'\');

try {
    while (top != _self.top) {
        top = top.parent.document ? top.parent : _self.top;
        if (top.location.pathname == \'/mycourse/studentstudy\') break;
    }
} catch (err) {
    // console.log(err);
    top = _self;
}

var $ = _self.jQuery || top.jQuery,
    parent = _self == top ? self : _self.parent,
    Ext = _self.Ext || parent.Ext || {},
    UE = _self.UE,
    vjs = _self.videojs;

String.prototype.toCDB = function() {
    return this.replace(/\s/g, \'\').replace(/[\uff01-\uff5e]/g, function(str) {
        return String.fromCharCode(str.charCodeAt(0) - 65248);
    }).replace(/[“”]/g, \'"\').replace(/[‘’]/g, "\'").replace(/。/g, \'.\');
};

setting.normal = \'\'; // \':visible\'
// setting.time += Math.ceil(setting.time * Math.random()) - setting.time / 2;
setting.job = [\':not(*)\'];

setting.video && setting.job.push(\'iframe[src*="/video/index.html"]\');
setting.work && setting.job.push(\'iframe[src*="/work/index.html"]\');
setting.audio && setting.job.push(\'iframe[src*="/audio/index.html"]\');
setting.book && setting.job.push(\'iframe[src*="/innerbook/index.html"]\');
setting.docs && setting.job.push(\'iframe[src*="/ppt/index.html"]\', \'iframe[src*="/pdf/index.html"]\');

setting.tip = !setting.queue || top != _self && jobSort($ || Ext.query);

if (url == \'/mycourse/studentstudy\') {
    _self.checkMobileBrowerLearn = $.noop;
    var classId = location.search.match(/cla[zs]{2}id=(\d+)/i)[1] || 0,
        courseId = _self.courseId || location.search.match(/courseId=(\d+)/i)[1] || 0;
    setting.lock || $(\'#coursetree\').on(\'click\', \'[onclick*=void], [href*=void]\', function() {
        _self.getTeacherAjax(courseId, classId, $(this).parent().attr(\'id\').slice(3));
    });
} else if (url == \'/ananas/modules/video/index.html\' && setting.video) {
    if (setting.review) _self.greenligth = Ext.emptyFn;
    checkPlayer(_self.supportH5Video());
} else if (url == \'/work/doHomeWorkNew\' || url == \'/api/work\' || url == \'/work/addStudentWorkNewWeb\') {
    if (!UE) {
        var len = ($ || Ext.query || Array)(\'font:contains(未登录)\', document).length;
        setTimeout(len == 1 ? top.location.reload : parent.greenligth, setting.time);
    } else if (setting.work) {
        setTimeout(relieveLimit, 0);
        beforeFind();
    }
} else if (url == \'/ananas/modules/audio/index.html\' && setting.audio) {
    if (setting.review) _self.greenligth = Ext.emptyFn;
    _self.videojs = hookAudio;
    hookAudio.xhr = vjs.xhr;
} else if (url == \'/ananas/modules/innerbook/index.html\' && setting.book && setting.tip) {
    setTimeout(function() {
        _self.setting ? _self.top.onchangepage(_self.getFrameAttr(\'end\')) : _self.greenligth();
    }, setting.time);
} else if (url.match(/^\/ananas\/modules\/(ppt|pdf)\/index\.html$/) && setting.docs && setting.tip) {
    setTimeout(function() {
        _self.setting ? _self.finishJob() : _self.greenligth();
    }, setting.time);
    frameElement.setAttribute(\'download\', 1);
} else if (url == \'/knowledge/cards\') {
    $ && checkToNext();
} else if (url.match(/^\/(course|zt)\/\d+\.html$/)) {
    setTimeout(function() {
        +setting.read && _self.sendLogs && $(\'.course_section:eq(0) .chapterText\').click();
    }, setting.time);
} else if (url == \'/ztnodedetailcontroller/visitnodedetail\') {
    setting.read *= 60 / $(\'.course_section\').length;
    setting.read && _self.sendLogs && autoRead();
} else if (url == \'/mycourse/studentcourse\') {
    var gv = location.search.match(/d=\d+&/g);
    setting.total && $(\'<a>\', {
        href: \'/moocAnalysis/chapterStatisticByUser?classI\' + gv[1] + \'courseI\' + gv[0] + \'userId=\' + _self.getCookie(\'_uid\') + \'&ut=s\',
        target: \'_blank\',
        title: \'点击查看章节统计\',
        style: \'margin: 0 25px;\',
        html: \'本课程共\' + $(\'.icon\').length + \'节,剩余\' + $(\'em:not(.openlock)\').length + \'节未完成\'
    }).appendTo(\'.zt_logo\').parent().width(\'auto\');
} else if (url.match(/^\/visit\/(courses|interaction)$/)) {
    setting.face && $(\'.zmodel\').on(\'click\', \'[onclick^=openFaceTip]\', DisplayURL);
} else if (location.host.match(/^passport2/)) {
    setting.username && getSchoolId();
} else if (location.hostname == \'i.mooc.chaoxing.com\') {
    _self.layui.use(\'layer\', function() {
        this.layer.open({content: \'拖动进度条、倍速播放、秒过会导致不良记录!题库在慢慢补充,搜不到的题目系统会在次日进行自动补充\', title: \'超星网课助手提示\', btn: \'我已知悉\', offset: \'t\', closeBtn: 0});
    });
} else if (url == \'/widget/pcvote/goStudentVotePage\') {
    $(\':checked\').click();
    $(\'.StudentTimu\').each(function(index) {
        var ans = _self.questionlist[index].answer;
        $(\':radio, :checkbox\', this).each(function(num) {
            ans[num].isanswer && this.click();
        });
        $(\':text\', this).val(function(num) {
            return $(ans[num].content).text().trim();
        });
    });
} else if (url == \'/work/selectWorkQuestionYiPiYue\') {
    submitAnswer(getIframe().parent(), $.extend(true, [], parent._data));
}

function getIframe(tip, win, job) {
    if (!$) return Ext.get(frameElement || []).parent().child(\'.ans-job-icon\') || Ext.get([]);
    do {
        win = win ? win.parent : _self;
        job = $(win.frameElement).prevAll(\'.ans-job-icon\');
    } while (!job.length && win.parent.frameElement);
    return tip ? win : job;
}

function jobSort($) {
    var fn = $.fn ? [getIframe(1), \'length\'] : [self, \'dom\'],
        sel = setting.job.join(\', :not(.ans-job-finished) > .ans-job-icon\' + setting.normal + \' ~ \');
    if ($(sel, fn[0].parent.document)[0] == fn[0].frameElement) return true;
    if (!getIframe()[fn[1]] || getIframe().parent().is(\'.ans-job-finished\')) return null;
    setInterval(function() {
        $(sel, fn[0].parent.document)[0] == fn[0].frameElement && fn[0].location.reload();
    }, setting.time);
}

function checkPlayer(tip) {
    _self.videojs = hookVideo;
    hookVideo.xhr = vjs.xhr;
    Ext.isSogou = Ext.isIos = Ext.isAndroid = false;
    var data = Ext.decode(_self.config(\'data\')) || {};
    delete data.danmaku;
    data.doublespeed = 1;
    frameElement.setAttribute(\'data\', Ext.encode(data));
    if (tip) return;
    _self.supportH5Video = function() {return true;};
    alert(\'此浏览器不支持html5播放器,请更换浏览器\');
}

function hookVideo() {
    _self.alert = console.log;
    var config = arguments[1],
        line = Ext.Array.filter(Ext.Array.map(config.playlines, function(value, index) {
            return value.label == setting.line && index;
        }), function(value) {
            return Ext.isNumber(value);
        })[0] || 0,
        http = Ext.Array.filter(config.sources, function(value) {
            return value.label == setting.http;
        })[0];
    config.playlines.unshift(config.playlines[line]);
    config.playlines.splice(line + 1, 1);
    config.plugins.videoJsResolutionSwitcher.default = http ? http.res : 360;
    config.plugins.studyControl.enableSwitchWindow = 1;
    config.plugins.timelineObjects.url = \'/richvideo/initdatawithviewer?\';
    config.plugins.seekBarControl.enableFastForward = 1;
    if (!setting.queue) delete config.plugins.studyControl;
    // config.preload = setting.tip ? \'auto\' : \'none\';
    var player = vjs.apply(this, arguments),
        a = \'<a href="https://d0.ananas.chaoxing.com/download/\' + _self.config(\'objectid\') + \'" target="_blank">\',
        img = \'<img src="https://d0.ananas.chaoxing.com/download/e363b256c0e9bc5bd8266bf99dd6d6bb" style="margin: 6px 0 0 6px;">\';
    player.volume(Math.round(setting.vol) / 100 || 0);
    Ext.get(player.controlBar.addChild(\'Button\').el_).setHTML(a + img + \'</a>\').dom.title = \'下载视频\';
    player.on(\'loadstart\', function() {
        setting.tip && this.play().catch(Ext.emptyFn);
        this.playbackRate(setting.rate > 16 || setting.rate < 0.0625 ? 1 : setting.rate);
    });
    player.one([\'loadedmetadata\', \'firstplay\'], function() {
        setting.two = setting.rate === \'0\' && setting.two < 1;
        setting.two && config.plugins.seekBarControl.sendLog(this.children_[0], \'ended\', Math.floor(this.cache_.duration));
    });
    player.on(\'ended\', function() {
        Ext.fly(frameElement).parent().addCls(\'ans-job-finished\');
    });
    return player;
}

function hookAudio() {
    _self.alert = console.log;
    var config = arguments[1];
    config.plugins.studyControl.enableSwitchWindow = 1;
    config.plugins.seekBarControl.enableFastForward = 1;
    if (!setting.queue) delete config.plugins.studyControl;
    var player = vjs.apply(this, arguments),
        a = \'<a href="https://d0.ananas.chaoxing.com/download/\' + _self.config(\'objectid\') + \'" target="_blank">\',
        img = \'<img src="https://d0.ananas.chaoxing.com/download/e363b256c0e9bc5bd8266bf99dd6d6bb" style="margin: 6px 0 0 6px;">\';
    player.volume(Math.round(setting.vol) / 100 || 0);
    player.playbackRate(setting.rate > 16 || setting.rate < 0.0625 ? 1 : setting.rate);
    Ext.get(player.controlBar.addChild(\'Button\').el_).setHTML(a + img + \'</a>\').dom.title = \'下载音频\';
    player.on(\'loadeddata\', function() {
        setting.tip && this.play().catch(Ext.emptyFn);
    });
    player.one(\'firstplay\', function() {
        setting.rate === \'0\' && config.plugins.seekBarControl.sendLog(this.children_[0], \'ended\', Math.floor(this.cache_.duration));
    });
    player.on(\'ended\', function() {
        Ext.fly(frameElement).parent().addCls(\'ans-job-finished\');
    });
    return player;
}

function relieveLimit() {
    if (setting.scale) _self.UEDITOR_CONFIG.scaleEnabled = false;
    $.each(UE.instants, function() {
        var key = this.key;
        this.ready(function() {
            this.destroy();
            UE.getEditor(key);
        });
    });
}

function beforeFind() {
    setting.regl = parent.greenligth || $.noop;
    if ($.type(parent._data) == \'array\') return setting.regl();
    setting.div = $(
        \'<div style="border: 2px dashed rgb(0, 85, 68); width: 330px; position: fixed; top: 0; right: 0; z-index: 99999; background-color: rgba(70, 196, 38, 0.6); overflow-x: auto;">\' +
        \'<span style="font-size: medium;"></span>\' +
        \'<div style="font-size: medium;">正在搜索答案...</div>\' +
        \'<button style="margin-right: 10px;">暂停答题</button>\' +
        \'<button style="margin-right: 10px;">\' + (setting.auto ? \'取消本次自动提交\' : \'开启本次自动提交\') + \'</button>\' +
        \'<button style="margin-right: 10px;">重新查询</button>\' +
        \'<button>折叠面板</button><br>\' +
        \'<div style="font-size: medium;">当前查题接口:\'+ (setting.tk_num%2+1) + \'</div>\' +
        \'<button id = "next_tk">切换为下一个查题接口</button>\' +
        \'<div style="max-height: 300px; overflow-y: auto;">\' +
        \'<table border="1" style="font-size: 12px;">\' +
        \'<thead>\' +
        \'<tr>\' +
        \'<th style="width: 25px; min-width: 25px;">题号</th>\' +
        \'<th style="width: 60%; min-width: 130px;">题目(点击可复制)</th>\' +
        \'<th style="min-width: 130px;">答案(点击可复制)</th>\' +
        \'</tr>\' +
        \'</thead>\' +
        \'<tfoot style="display: none;">\' +
        \'<tr>\' +
        \'<th colspan="3">答案提示框 已折叠</th>\' +
        \'</tr>\' +
        \'</tfoot>\' +
        \'<tbody>\' +
        \'<tr>\' +
        \'<td colspan="3" style="display: none;"></td>\' +
        \'</tr>\' +
        \'</tbody>\' +
        \'</table>\' +
        \'</div>\' +
        \'</div>\'
    ).appendTo(\'body\').on(\'click\', \'button, td\', function() {
        var len = $(this).prevAll(\'button\').length;
        if (this.nodeName == \'TD\') {
            $(this).prev().length && GM_setClipboard($(this).text());
        } else if (!$(this).siblings().length) {
            $(this).parent().text(\'正在搜索答案...\');
            setting.num++;
        } else if (len === 0) {
            if (setting.loop) {
                clearInterval(setting.loop);
                delete setting.loop;
                len = [\'已暂停搜索\', \'继续答题\'];
            } else {
                setting.loop = setInterval(findAnswer, setting.time);
                len = [\'正在搜索答案...\', \'暂停答题\'];
            }
            setting.div.children(\'div:eq(0)\').html(function() {
                return $(this).data(\'html\') || len[0];
            }).removeData(\'html\');
            $(this).html(len[1]);
        } else if (len == 1) {
            setting.auto = !setting.auto;
            $(this).html(setting.auto ? \'取消本次自动提交\' : \'开启本次自动提交\');
        } else if (len == 2) {
            parent.location.reload();
        } else if (len == 3) {
            setting.div.find(\'tbody, tfoot\').toggle();
        } else if (len == 4) {
            setting.tk_num++;
            GM_setValue(\'tk_num\',setting.tk_num);
            setting.tk_num = GM_getValue(\'tk_num\');
            console.log(setting.tk_num);
            parent.location.reload();
        }
    }).find(\'table, td, th\').css(\'border\', \'1px solid\').end();
    setting.lose = setting.num = 0;
    setting.data = parent._data = [];
    setting.over = \'<button style="margin-right: 10px;">跳过此题</button>\';
    setting.curs = $(\'script:contains(courseName)\', top.document).text().match(/courseName:\\'(.+?)\\'|$/)[1] || $(\'h1\').text().trim() || \'无\';
    setting.loop = setInterval(findAnswer, setting.time);
    var tip = ({undefined: \'任务点排队中\', null: \'等待切换中\'})[setting.tip];
    tip && setting.div.children(\'div:eq(0)\').data(\'html\', tip).siblings(\'button:eq(0)\').click();
}

function findAnswer() {
    if (setting.num >= $(\'.TiMu\').length) {
        var arr = setting.lose ? [\'共有 <font color="red">\' + setting.lose + \'</font> 道题目待完善(已深色标注)\', saveThis] : [\'答题已完成\', submitThis];
        setting.div.children(\'div:eq(0)\').data(\'html\', arr[0]).siblings(\'button:eq(0)\').hide().click();
        return setTimeout(arr[1], setting.time);
    }
    var $TiMu = $(\'.TiMu\').eq(setting.num),
        question = filterImg($TiMu.find(\'.Zy_TItle:eq(0) .clearfix\')).replace(/^【.*?】\s*/, \'\').replace(/\s*(\d+\.\d+分)$/, \'\').replace(/[(]\s*[)]。$/,\'\').replace(/(\s*)。$/,\'\').replace(/[(]\s*[)]$/,\'\').replace(/(\s*)$/,\'\').replace(/。$/,\'\'),
        type = $TiMu.find(\'input[name^=answertype]:eq(0)\').val() || \'-1\';


    //setting.div.children(\'div:eq(0)\').text(encodeURIComponent(question)+\'正在搜索答案...\');
    switch(setting.tk_num%2)
    {
        case 0:{
            GM_xmlhttpRequest({
                method: \'POST\',
                url: \'http://cx.icodef.com/wyn-nb\',
                headers: {
                    \'Content-type\': \'application/x-www-form-urlencoded\',
                    \'Authorization\': setting.token,
                },
                data: \'question=\' + encodeURIComponent(question) + \'&type=\' + type + \'&id=\' + ($(\'#workLibraryId\').val() || $(\'#oldWorkId\').val()),
                timeout: setting.time,
                onload: function(xhr) {
                    if (!setting.loop) {
                    } else if (xhr.status == 200) {
                        var obj = $.parseJSON(xhr.responseText) || {};
                        obj.answer = obj.data;
                        if (obj.code) {
                            setting.div.children(\'div:eq(0)\').text(\'正在搜索答案...\');
                            var td = \'<td style="border: 1px solid;\',
                                answer = String(obj.answer).replace(/&/g, \'&amp;\').replace(/<(?!img)/g, \'&lt;\');
                            obj.answer = /^http/.test(answer) ? \'<img src="\' + obj.answer + \'">\' : obj.answer;
                            $(
                                \'<tr>\' +
                                td + \' text-align: center;">\' + $TiMu.find(\'.Zy_TItle:eq(0) i\').text().trim() + \'</td>\' +
                                td + \'" title="点击可复制">\' + (question.match(\'<img\') ? question : question.replace(/&/g, \'&amp;\').replace(/</g, \'&lt\')) + \'</td>\' +
                                td + \'" title="点击可复制">\' + (/^http/.test(answer) ? obj.answer : \'\') + answer + \'</td>\' +
                                \'</tr>\'
                            ).appendTo(setting.div.find(\'tbody\')).css(\'background-color\', fillAnswer($TiMu.find(\'ul:eq(0)\').find(\'li\'), obj, type) ? \'\' : \'rgba(0, 150, 136, 0.6)\');
                            setting.data[setting.num++] = {
                                code: obj.code > 0 ? 1 : 0,
                                question: question,
                                option: obj.answer,
                                type: Number(type)
                            };
                        } else {
                            setting.div.children(\'div:eq(0)\').html(obj.answer || setting.over + \'服务器繁忙,正在重试...\');
                        }
                        setting.div.children(\'span\').html(obj.msg || \'\');
                    } else if (xhr.status == 403) {
                        var html = xhr.responseText.indexOf(\'{\') ? \'请求过于频繁,单击下面的切换题库接口按钮试试吧\' : $.parseJSON(xhr.responseText).data;
                        setting.div.children(\'div:eq(0)\').data(\'html\', html).siblings(\'button:eq(0)\').click();
                    } else {
                        setting.div.children(\'div:eq(0)\').html(\'题库异常,单击下面的切换题库接口按钮试试吧...\');
                    }
                },
                ontimeout: function() {
                    setting.loop && setting.div.children(\'div:eq(0)\').html(setting.over + \'服务器超时,正在重试...\');
                }
            });
        }; break;
        case 1:{
            GM_xmlhttpRequest({
                method: \'POST\',
                url: \'http://cx.beaa.cn/cx.php\',
                headers: {
                    \'Content-type\': \'application/x-www-form-urlencoded\',
                },
                data: \'content=\' + encodeURIComponent(question.replace(/^<img src="/,"").replace(/">$/,"")),
                timeout: setting.time,
                onload: function(xhr) {
                    if (!setting.loop) {
                    } else if (xhr.status == 200) {
                        var obj = $.parseJSON(xhr.responseText.replace(/^操作数据失败!/,\'\')) || {};
                        if (obj.code) {
                            setting.div.children(\'div:eq(0)\').text(\'正在搜索答案...\');
                            var td = \'<td style="border: 1px solid;\',
                                answer = S

脚本③(控制台)

/**
 * 学习通
 */

// 当前小节
window.unitCount = $(".ncells h4").index($(".currents")) + 1;
// 获取小节数量
window.unit = $(".ncells h4").length;

function main(){
    const frameObj = $("iframe").eq(0).contents().find("iframe.ans-insertvideo-online");
    const videoNum = frameObj.length;
    if(videoNum > 0){
        console.log("%c当前小节中包含 " + videoNum + " 个视频","color:#FF7A38;font-size:18px");
        var v_done = 0;
        // 添加事件处理程序
        addEventListener("playdone" ,()=>{
            v_done++;
            if(v_done > videoNum){
                // 下一节
            } else if(v_done < videoNum){
                watchVideo(frameObj, v_done)
            } else {
                console.log("%c本小节视频播放完毕,等待跳转至下一小节...","font-size:18px");nextUnit();
            }
        });
        // 播放
        watchVideo(frameObj, v_done);
    } else {
        if(window.unitCount < window.unit){
            console.log("%c当前小节中无视频,6秒后将跳转至下一节","font-size:18px");
            nextUnit();
        } else {
            console.log("%c好了好了,毕业了","color:red;font-size:18px");
        }
    }
}
function watchVideo(frameObj, v_done){
    // 添加播放事件
    var playDoneEvent = new Event("playdone");
    // 获取播放对象
    var v = undefined;
    v = frameObj.contents().eq(v_done).find("video#video_html5_api").get(0);window.a = v;
    // 设置倍速
    try{ v.playbackRate = 8;}
    catch(e){console.error("倍速设置失败!此节可能有需要回复内容,不影响,跳至下一节。错误信息:"+e); nextUnit(); return;}
    // 播放
    v.play();
    console.log("%c正在 " + v.playbackRate + " 倍速播放第 " + (v_done + 1) + " 个视频","font-size:18px");
    // 循环获取播放进度
    window.inter = setInterval(()=>{
        v = window.a;
        if(v.currentTime >= v.duration){
            dispatchEvent(playDoneEvent);
            clearInterval(window.inter);
        }
        if(v.paused){
            v.play();
        }
    },1000);
}
function nextUnit(){
    console.log("%c即将进入下一节...","color:red;font-size:18px");
    setTimeout(() => {
        $(document).scrollTop($(document).height()-$(window).height());
        $(".orientationright").click();
        console.log("%c行了别看了,我知道你学会了,下一节","color:red;font-size:18px");// (已经跳转" +(++window.unitCount)+"次)");
        if(window.unitCount++ < window.unit){ setTimeout(() => main(), 10000) }
    }, 6000);
}
console.log("%c 欢迎使用本脚本,此科目有%c %d %c个小节,当前为 %c第%d小节 %c-chao", "color:#6dbcff", "color:red", window.unit, "color:#6dbcff", "color:red", window.unitCount, "font-size:8px");
main();

版权声明:本文为melodyjerry原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/melodyjerry/p/13074285.html