智慧樹考試自動答題【油猴腳本】

今天智慧樹選修課期末測試【自己搜答案,不可能的】,所以自己去找了一下相關的腳本 ,

剛纔親自使用了一下, 效果很不錯 ,幾分鐘之後題目就自動答完了,分數還不錯 ,95+ ,(滿分100分)

有需要的自提, 源碼如下 【來自Greasy Fork】

// ==UserScript==
// @name         智慧樹網課助手(最強題庫-精準答題)
// @namespace    qackqi & Stars
// @version      1.0.3
// @description  超星網課助手鍊接內附 | 自動掛機看知到MOOC,支持自動切換任務點、章測試及考試自動答題、視頻自動倍速播放 | 解除各類功能限制,開放自定義參數
// @author       qackqi & Stars
// @match        *://*.zhihuishu.com/*
// @connect      qs.nnarea.cn
// @run-at       document-end
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @grant        GM_setClipboard
// @supportURL   
// @license      MIT
// ==/UserScript==

// 設置修改後,需要刷新或重新打開網課頁面纔會生效
var setting = {
    // 5E3 == 5000,科學記數法,表示毫秒數
    time: 5E3 // 默認響應速度爲5秒,不建議小於3秒
    ,token: '' // 捐助用戶可以使用定製功能,更精準的匹配答案,此處填寫捐助後獲取的識別碼

    // 1代表開啓,0代表關閉
    ,video: 1 // 視頻支持課程、見面課,默認關閉
    ,work: 1 // 自動答題功能,支持章測試、考試,高準確率,默認開啓
    ,jump: 1 // 自動切換視頻,支持課程、見面課,默認關閉

    // 僅開啓video時,修改此處纔會生效
    ,line: '流暢' // 視頻播放的默認線路,可選參數:['高清', '流暢', '校內'],默認'流暢'
    ,vol: '0' // 默認音量的百分數,設定範圍:[0,100],'0'爲靜音,默認'0'
    ,speed: '1.5' // 進度統計速率,高倍率可以快速完成任務點,設定範圍:(0,+∞),默認'1.5'倍
    // 上方參數支持在頁面改動,下方參數僅支持代碼處修改
    ,que: 1 // 屏蔽視頻時間點對應的節試題,取消屏蔽則自動切換爲模擬點擊關閉彈題,默認開啓
    ,danmu: 0 // 見面課彈幕,關閉後在網頁中無法手動開啓,默認關閉
    ,habit: '0' // 限制視頻掛機時長,單位是分鐘,如需掛機習慣分,可以修改參數爲'30',默認不限制

    // 僅開啓work時,修改此處纔會生效
    ,none: 0 // 無匹配答案時執行默認操作,默認關閉
    ,hide: 0 // 不加載答案搜索提示框,鍵盤↑和↓可以臨時移除和加載,默認關閉
},
_self = unsafeWindow,
url = location.pathname,
$ = _self.jQuery,
xhr = _self.XMLHttpRequest;

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.time += Math.ceil(setting.time * Math.random()) - setting.time / 2;
setting.queue = setting.curs = [];

if (!$) {
} else if (url.match('/videoList')) {
    $.tmDialog.alert({content: '2.X版本已取消支持舊版界面', title: '智慧樹網課助手提示'});
} else if (url == '/videoStudy.html') {
    setting.habit *= 6E4;
    setting.video && hookVideo(_self.vjsComponent, 1);
    setting.jump && setInterval(checkToNext, setting.time);
} else if (url == '/portals_h5/2clearning.html') {
    setting.video && hookVideo(_self.vjsComponent, 2);
    setting.jump && setInterval(checkToNext, setting.time);
} else if (url == '/live/vod_room.html') {
    setting.video && hookVideo(_self.vjsComponent);
    setting.jump && setInterval(checkToNext, setting.time, 1);
} else if (location.hostname.match('examh5')) {
    setTimeout(relieveLimit, 100, document);
    if (location.hash.match(/dohomework|doexamination/) && setting.work) beforeFind();
    $(window).on('hashchange', function() {
        setting.work && location.reload();
    });
} else if (url.match('/sourceLearning')) {
    setting.video && hookVideo(_self.vjsComponent, 3);
    setting.jump && setInterval(checkToNext, setting.time, $('.source-file-item'));
} else if (url == '/shareCourse/questionDetailPage') {
    setTimeout(relieveLimit, 100, document);
    $('textarea[oncut]').each(function() {
        setTimeout(relieveLimit, 100, this);
    });
} else if (url.match('exerciseList') && setting.work) {
    _self.XMLHttpRequest = hookHiexam;
    setInterval(function() {
        $(setting.queue.shift()).parent().click();
    }, 1E3);
    setting.jump && setInterval(function() {
        // var $li = setting.queue.length ? $() : $('.jobclassallnumber-div li');
        // $li.slice($li.index($('.greenbordercur')) + 1).not('.greenbgcur').eq(0).click();
        setting.queue.length || $('.Topicswitchingbtn:contains(下一題)').click();
    }, setting.time);
}

function hookVideo(Hooks, tip) {
    // _self.PlayerUtil.debugMode = true;
    _self.vjsComponent = function() {
        var config = arguments[0],
        options = config.options,
        line = $.map(options.sourceSrc.lines, function(value) {
            return value.lineName.replace('標準', '高清');
        }),
        vol = setting.vol > 100 ? 100 : setting.vol,
        rate = tip == 3 ? [1, 1.25, 1.5, 2, 2.5, 3] : [1, 1.25, 1.5];
        vol = Math.round(vol) / 100;
        options.volume = vol > 0 ? vol : 0;
        options.autostart = true;
        setting.speed = setting.speed > 0 ? +setting.speed : 1;
        options.rate = $.inArray(setting.speed, rate) < 0 ? options.rate : setting.speed;
        tip && config.callback.playbackRate(setting.speed);
        options.chooseLine = $.inArray(setting.line, line) + 1 || options.chooseLine + 1;
        options.src = options.sourceSrc.lines[--options.chooseLine].lineUrl || options.src;
        if (!setting.danmu) {
            config.defOptions.control.danmuBtn = false;
            delete options.control.danmuBtn;
        }
        Hooks.apply(this, arguments);
        config.player.on('loadstart', function() {
            this.loop(true);
            this.play();
            $('.speedBox span').text('X ' + setting.speed);
        });
    };
    $(document).on('click', '.definiLines b', function() {
        setting.line = ({xiaonei: '校內', line1gq: '高清', line1bq: '流暢'})[this.classList[0]];
    }).on('mouseup click', function() {
        setting.vol = _self.PlayerStarter.playerArray[0].player.cache_.volume * 100;
    }).on('click', '.speedList div', function() {
        setting.speed = $(this).attr('rate');
    });
    if (tip != 1) return;
    setting.tip = setting.habit && setInterval(totalTime, setting.time);
    setInterval(doTest, 1E3);
    _self.XMLHttpRequest = setting.que ? function() {
        var ajax = new xhr(),
        open = ajax.open;
        ajax.open = function(method, url) {
            if (url.match('/loadVideoPointerInfo')) method = 'OPTIONS';
            return open.apply(this, arguments);
        };
        return ajax;
    } : xhr;
}

function totalTime() {
    var player = _self.PlayerStarter.playerArray[0].player;
    setting.habit -= player.paused() ? 0 : setting.time;
    if (setting.habit >= 0) return;
    clearInterval(setting.tip);
    player.pause();
    $.getScript('//cdn.jsdelivr.net/gh/sentsin/layer/dist/layer.js', function() {
        _self.layer.open({content: '已達到掛機限制時間', title: '智慧樹網課助手提示', end: function() {
            setting.habit = 0;
        }});
    });
}

function checkToNext(tip) {
    if (setting.habit < 0) return;
    var $tip = $('.video, .lessonItem');
    if ($('.current_play .time_icofinish').length) {
        $tip.slice($tip.index($('.current_play')) + 1).not(':has(.time_icofinish)').eq(0).click();
    } else if ($('.lessonItemActive .finish').length) {
        // _self.PlayerStarter.playerArray[0].callback.playerNext();
        $tip.slice($tip.index($('.lessonItemActive')) + 1).not(':has(.finish)').eq(0).click();
    } else if (tip == 1) {
        $('.current_player:contains("100%") + li').click();
        // $('.finish_tishi').hasClass('disNo') || console.log('簽到已完成');
    } else if ($('.settleOn .finish').length) {
        tip.slice(tip.index($('.settleOn')) + 1).not(':has(.finish)').eq(0).find('.file-name').click();
    }
}

function doTest() {
    if (!$('.dialog-test').length) {
    } else if (setting.queue.length) {
        $(setting.queue.shift()).parent().click();
    } else if (!$('.answer').length) {
        $('.topic-item').eq(0).click();
    } else if (!$('.right').length) {
        var tip = $('.answer span').text().match(/[A-Z]/g) || [];
        if (tip.length == 1) return $('.topic-option-item:contains(' + tip[0] + ')').click();
        $('.topic-option-item').each(function() {
            $.inArray($(this).text().slice(0, 1), tip) < 0 == $(this).hasClass('active') && setting.queue.push(this);
        });
    } else if ($('.btn-next:enabled').length) {
        $('.btn-next:enabled').click();
    } else {
        $('.dialog-test .btn').click();
        _self.PlayerStarter.playerArray[0].player.play();
    }
}

function relieveLimit(doc) {
    if (!doc.oncut && !doc.onselectstart) return setTimeout(relieveLimit, 100, doc);
    doc.oncontextmenu = doc.onpaste = doc.oncopy = doc.oncut = doc.onselectstart = null;
}

function beforeFind() {
    setting.div = $(
        '<div style="border: 2px dashed rgb(149, 252, 251); width: 330px; position: fixed; top: 0; left: 0; z-index: 99999; background-color: rgba(184, 247, 255, 0.3); 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;">重新查詢</button>' +
            '<button style="margin-right: 10px;">摺疊面板</button>' +
            '<button style="display: none;">未作答題目</button>' +
            '<form style="margin: 2px 0;">' +
                '<label style="font-weight: bold; color: red;">自定義答題範圍:</label>' +
                '<input name="num" type="number" min="1" placeholder="開始" style="width: 60px;" disabled>' +
                '<span> ~ </span>' +
                '<input name="max" type="number" min="1" placeholder="結束" style="width: 60px;" disabled>' +
            '</form>' +
            '<div style="max-height: 300px; overflow-y: auto;">' +
                '<table border="1" style="font-size: 12px;">' +
                    '<thead>' +
                        '<tr>' +
                            '<th style="width: 30px; min-width: 30px; font-weight: bold; text-align: center;">題號</th>' +
                            '<th style="width: 60%; min-width: 130px; font-weight: bold; text-align: center;">題目(點擊可複製)</th>' +
                            '<th style="min-width: 130px; font-weight: bold; text-align: center;">答案(點擊可複製)</th>' +
                        '</tr>' +
                    '</thead>' +
                    '<tfoot style="display: none;">' +
                        '<tr>' +
                            '<th colspan="3" style="font-weight: bold; text-align: center;">答案提示框 已摺疊</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 (len === 0) {
            if (setting.loop) {
                clearInterval(setting.loop);
                delete setting.loop;
                len = [false, '已暫停搜索', '繼續答題'];
            } else {
                setting.loop = setInterval(findAnswer, setting.time);
                len = [true, '正在搜索答案...', '暫停答題'];
            }
            setting.div.find('input').attr('disabled', len[0]);
            setting.div.children('div:eq(0)').html(function() {
                return $(this).data('html') || len[1];
            }).removeData('html');
            $(this).html(len[2]);
        } else if (len == 1) {
            location.reload();
        } else if (len == 2) {
            setting.div.find('tbody, tfoot').toggle();
        } else if (len == 3) {
            var $li = $('.el-scrollbar__wrap li'),
            $tip = $li.filter('.white, .yellow').eq(0);
            $tip.click().length ? setting.div.children('div:last').scrollTop(function() {
                var $tr = $('tbody tr', this).has('td:nth-child(1):contains(' + $tip.text() + ')');
                if (!$tr.length) return arguments[1];
                return $tr.offset().top - $tr.parents('table').offset().top; // $tr[0].offsetTop
            }) : $(this).hide();
        }
    }).on('change', 'input', function() {
        setting[this.name] = this.value.match(/^\d+$/) ? parseInt(this.value) - 1 : -1;
        if (!this.value) setting[this.name] = this.name == 'num' ? 0 : undefined;
    }).detach(setting.hide ? '*' : 'html');
    setting.type = {
        單選題: 1,
        多選題: 2,
        填空題: 3,
        問答題: 4,
        '分析題/解答題/計算題/證明題': 5,
        '閱讀理解(選擇)/完型填空': 9,
        判斷題: 14
    };
    setting.lose = setting.num = setting.small = 0;
    $(document).keydown(function(event) {
        if (event.keyCode == 38) {
            setting.div.detach();
        } else if (event.keyCode == 40) {
            setting.div.appendTo('body');
        }
    });
    setting.loop = setInterval(findAnswer, setting.time, true);
    setInterval(function() {
        $(setting.queue.shift()).parent().click();
    }, 1E3);
}

function findAnswer(tip) {
    if (setting.queue.length) {
        return;
    } else if (tip && !$('.answerCard').length) {
        return setting.div.children('div:eq(0)').data('html', '非自動答題頁面').siblings('button:eq(0)').click();
    } else if (setting.max < 0 || setting.num < 0) {
        return setting.div.children('div:eq(0)').data('html', '範圍參數應爲 <font color="red">正整數</font>').siblings('button:eq(0)').click();
    } else if (setting.num >= $('.subject_stem').length || setting.num > setting.max) {
        // setting.div.children('button:eq(3)').toggle(!!setting.lose);
        tip = setting.lose ? '共有 <font color="red">' + setting.lose + '</font> 道題目待完善(已深色標註)' : '答題已完成';
        return setting.div.children('div:eq(0)').data('html', tip).siblings('button:eq(0), form').hide().click();
    } else if (!setting.curs.length) {
        setting.curs = $('.infoList span').map(function() {
            return $(this).text().trim();
        });
        if (!setting.curs.length) return;
    }
    var $TiMu = $('.subject_stem').eq(setting.num).parent(),
    $dom = $TiMu.find('.smallStem_describe').eq(setting.small).children('div').slice(1, -1),
    question = filterStyle($dom) || filterStyle($TiMu.find('.subject_describe')),
    type = $TiMu.find('.subject_type').text().match(/【(.+)】|$/)[1];
    type = type ? setting.type[type] || 0 : -1;
    GM_xmlhttpRequest({
        method: 'POST',
        url: 'http://qs.nnarea.cn/OnlineCourseBot/topic',
        headers: {
            'Content-type': 'application/x-www-form-urlencoded'
        },
        data: 'q=' + encodeURIComponent(question) + '&type=' + type,
        timeout: setting.time,
        onload: function(xhr) {
            if (!setting.loop) {
            } else if (xhr.status == 200) {
                var obj = $.parseJSON(xhr.responseText) || {};
                if (obj.success == "true") {
                    setting.div.children('div:eq(0)').text('正在搜索答案...');
                    var data = obj.answer.replace(/&/g, '&amp;').replace(/<([^i])/g, '&lt;$1');
                    obj.answer = /^http/.test(data) ? '<img src="' + obj.answer + '">' : obj.answer;
                    $(
                        '<tr>' +
                            '<td style="text-align: center;">' + $TiMu.find('.subject_num').text().trim().replace('.', '') + '</td>' +
                            '<td title="點擊可複製">' + (question.match('<img') ? question : question.replace(/&/g, '&amp;').replace(/</g, '&lt')) + '</td>' +
                            '<td title="點擊可複製">' + (/^http/.test(data) ? obj.answer : '') + data + '</td>' +
                        '</tr>'
                    ).appendTo(setting.div.find('tbody')).css('background-color', function() {
                        $dom = $dom.length ? $dom.closest('.examPaper_subject') : $TiMu;
                        if (fillAnswer($dom, obj, type)) return '';
                        setting.div.children('button:eq(3)').show();
                        return 'rgba(99, 215, 247, 0.6)';
                    });
                    setting.small = ++setting.small < $TiMu.find('.smallStem_describe').length ? setting.small : (setting.num++, 0);
                } else {
                    setting.div.children('div:eq(0)').html(obj.answer || '服務器繁忙,正在重試...');
                }
                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)').text('服務器異常,正在重試...');
            }
        },
        ontimeout: function() {
            setting.loop && setting.div.children('div:eq(0)').text('服務器超時,正在重試...');
        }
    });
}

function fillAnswer($TiMu, obj, type) {
    var $div = $TiMu.find('.nodeLab'),
    str = String(obj.answer).toCDB() || new Date().toString(),
    data = str.split(/#|\x01|\|/),
    state = setting.lose;
    // $div.find(':radio:checked').prop('checked', false);
    obj.success == "true" && $div.each(function() {
        var $input = $('input', this)[0],
        tip = filterStyle('.node_detail', this).toCDB() || new Date().toString();
        if (tip.match(/^(正確|是|對|√|T|ri)$/)) {
            data.join().match(/(^|,)(正確|是|對|√|T|ri)(,|$)/) && setting.queue.push($input);
        } else if (tip.match(/^(錯誤|否|錯|×|F|wr)$/)) {
            data.join().match(/(^|,)(錯誤|否|錯|×|F|wr)(,|$)/) && setting.queue.push($input);
        } else if (type == 2) {
            Boolean($.inArray(tip, data) + 1 || str.indexOf(tip) + 1) == $input.checked || setting.queue.push($input);
        } else {
            $.inArray(tip, data) + 1 && setting.queue.push($input);
        }
    });
    if (setting.queue.length) {
    } else if (/^(1|2|14)$/.test(type)) {
        var $input = $div.find('input');
        $input.is(':checked') || (setting.none ? setting.queue.push($input[Math.floor(Math.random() * $input.length)]) : setting.lose++);
    } else if (/^[3-5]$/.test(type)) {
        data = String(obj.answer).split(/#|\x01|\|/);
        str = $TiMu.find('textarea').each(function(index) {
            index = (obj.success == "true" && data[index]) || '';
            this.value = index.trim();
            // if (this.value == this._value) return true;
            this.dispatchEvent(new Event('input'));
            this.dispatchEvent(new Event('blur'));
        }).length;
        (obj.success == "true" && data.length == str) || setting.none || setting.lose++;
    } else {
        setting.none || setting.lose++;
    }
    return state == setting.lose;
}

function hookHiexam() {
    var ajax = new xhr();
    ajax.onload = function() {
        if (this.status != 200 || !this.responseURL.match('getDoQuestSingle')) return;
        var obj = JSON.parse(this.responseText).rt;
        $.each(obj.questionOptionList || [], function(index) {
            var $input = $('.TitleOptions-div input')[index];
            if (obj.questionTypeId == 1) {
                this.isCorrect && setting.queue.push($input);
            } else if (obj.questionTypeId == 2) {
                this.isCorrect == $input.checked || setting.queue.push($input);
            }
        });
    };
    return ajax;
}

function filterStyle(dom, that) {
    var $dom = $(dom, that).clone().find('style').remove().end();
    return $dom.find('img[src]').replaceWith(function() {
        return $('<p></p>').text('<img src="' + $(this).attr('src') + '">');
    }).end().text().trim();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章