问卷星脚本

详见代码中的描述;任何疑问,请加qq群咨询:427847187;我看到了一定会耐心解答的!

目前为 2023-05-25 提交的版本。查看 最新版本

// ==UserScript==
// @name         问卷星脚本
// @author       钟天宇
// @version      1.2
// @description  详见代码中的描述;任何疑问,请加qq群咨询:427847187;我看到了一定会耐心解答的!
// @match        https://www.wjx.cn/*
// @namespace    https://gf.qytechs.cn/users/1079332
// ==/UserScript==

localStorage.clear();
sessionStorage.clear();
console.log("Storage已清除!")
var cancelBtn = document.querySelector('a.layui-layer-btn1');
if (cancelBtn) {
    cancelBtn.click();
}

(function () {
    //将下面的链接替换成你的问卷链接
    var url = "https://www.wjx.cn/vm/hxxt2Oe.aspx";
    // 若当前页面为问卷调查完成页,重定向到目标 URL,下面这个链接不要替换
    if (window.location.href.includes("https://www.wjx.cn/wjx/join/complete")) {
        window.location.href = url;
    }
    var opt;

    //在单选题的函数single()中,括号里需要写题号和每个选项的比例,比如single(1, [1,2,3])表示第1题,选A占1/6,B占2/6,C占3/6;选项数量和比例数量必须一致,否则会报错
    //在多选题的函数multiple(),括号里需写题号和各选项选择的人数比,比如multiple(2, [50,10,100])表示第2题,选A的人有50%,选B的人有10%,选C的人有100%;
    //在填空题的函数vacant()中,括号里需写题号,内容和每个内容对应的比例,比如vacant(3,[1,1],["lzm","zty"])表示第3题,填写lzm和zty的比例为1: 1
    //nextPage()表示翻页
    //{"1": [1, 0, 0, 0, 0],.......}表示矩阵题各个小题的比例,其中的每个小题概率含义与单选题一致
    //在矩阵题的函数matrix()中,括号里需要写题号和每个选项的比例,比如matrix(4,{...})表示第4题,每个小题按照中括号里写的比例刷数据
    //在单选题的函数scale()中,括号里需要写题号和每个选项的比例,比如scale(5,[1,1,2,2,6])表示第5题,A:B:C:D:E = 1:1:2:2:6(和单选题一致)
    //在滑块题的函数slide()中,括号里需写题号,结果完全随机
    //所有输入,请在英文输入法里进行,中文和英文的很多符号是不一样的,比如---->    ()()  {}{}   ::   ,, ;;




    //目前脚本可以处理单选(single)、多选(mutiple)、矩阵(matrix)、滑块(slide)、填空(vacant)、量表(scale)类问题,这也包括了大部分常见题型
    //下面是需要修改的代码
    single(1, [1, 2, 3])
    multiple(2, [50, 10, 100])
    vacant(3, ["lzm", "zty","gq"], [1, 1, 2])
    nextPage();
    matrix(4, { "1": [1, 0, 0, 0, 0], "2": [1, 1, 1, 1, 1], "3": [1, 0, 0, 0, 0], "4": [1, 0, 0, 0, 0]})
    scale(5, [1, 1, 2, 2, 6])
    scale(6, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
    slide(7,50,70)
    opt = single(8,[1,1])
    if(opt == 1){
        single(9,[1,1])
    }
    //到此结束,下面的代码可以不用管了;你需要关注的代码就是:
    //①问卷链接需要替换
    //②刷题逻辑
    //③不要删除下面的任何代码求求了;只能改你的问卷链接和刷题逻辑的代码,其余不要删;
    //我希望得到你们的任何反馈,不论是好评或者差评,以帮助我更新代码!!求求了~~~(2023-05-24)




    //滚动到页面底端
    window.scrollTo(0,document.body.scrollHeight)
    //点击提交按钮
    const nextBtn = document.evaluate('//*[@id="ctlNext"]', document, null,
                                 XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    if (nextBtn) {
        nextBtn.click();
    }
    setTimeout(function(){
        //点击确认按钮
        document.querySelector('.layui-layer-btn0').click();
        //点击验证按钮
        document.querySelector('#rectMask').click();
        try{
            //5秒后滑动滑块
            setTimeout(simulateSliderVerification,4000)}
        catch(err){
            console.log("啦啦啦")
        }
    },1500)
    //滑动验证函数
    async function simulateSliderVerification() {
        // 获取滑块元素
        const slider = document.querySelector('#nc_1__scale_text > span');
        console.log("slider",slider)
        // 判断滑块提示文本是否为“请按住滑块”
        if (slider.textContent.startsWith('请按住滑块')) {
            // 计算滑动距离
            const width = slider.offsetWidth;
            // 定义触发事件选项
            const eventOptions = { bubbles: true, cancelable: true };
            // 创建鼠标按下事件
            const dragStartEvent = new MouseEvent('mousedown', eventOptions);
            // 创建鼠标释放事件
            const dragEndEvent = new MouseEvent('mouseup', eventOptions);
            /////////////////////////////////////////
            const steps = 10;
            const stepWidth = width / steps;
            let currX = stepWidth / 2;
            // 模拟鼠标点击并保持不动
            slider.dispatchEvent(dragStartEvent);
            // 移动一定距离
            const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
            for (let i = 0; i < steps; i++) {
                slider.dispatchEvent(new MouseEvent('mousemove', Object.assign({ clientX: currX }, eventOptions)));
                currX += stepWidth;
                await delay(50);
            }
            // 松开鼠标
            slider.dispatchEvent(dragEndEvent);
            console.log("滑动完成")
        }
    }
    //下一页
    function nextPage(){
        document.querySelector('a.button.mainBgColor').click();
    }
    //单选题函数
    function single(current, ratio) {
        current = current - 1
        var lists = document.querySelectorAll('.field.ui-field-contain')
        //该单选题的选项
        var ops = lists[current].getElementsByClassName('ui-controlgroup column1')[0].children
        ratio = normArray(ratio)
        //待点击的选项,返回第几个数
        var index = singleRatio([1, ops.length], ratio)
        ops[index - 1].click()
        console.log("第", current + 1, "题选择了第", index, "个选项")
        return index
    }
    //多选题函数
    function multiple(current, ratio) {
        current = current - 1
        var lists = document.querySelectorAll('.field.ui-field-contain')
        //该多选题的选项
        var ops = lists[current].getElementsByClassName('ui-controlgroup column1')[0].children
        let mul_list = [];
        // 获取随机数列表
        function getRandomNumberList(ratio, mul_list) {
            return ratio.map((item) => Math.random() < item / 100 ? 1 : 0);
        }
        //生成至少包含一个1的多选题数组
        while (mul_list.reduce((acc, curr) => acc + curr, 0) <= 0) {
            mul_list = getRandomNumberList(ratio, mul_list);
        }
        for (const [index, item] of mul_list.entries()) {
            if (item == 1) {
                ops[index].click()
                console.log("第", current + 1, "题选择了第", index + 1, "个选项")
            }
        }
    }
    //矩阵题函数
    function matrix(current, matrix_prob) {
        const xpath1 = `//*[@id="divRefTab${current}"]/tbody/tr`;
        const a = document.evaluate(xpath1, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
        let q_num = 0;
        //遍历每项判断是否为题
        for (let i = 0; i < a.snapshotLength; i++) {
            const tr = a.snapshotItem(i);
            if (tr.getAttribute("rowindex") !== null) {
                q_num++;
            }
        }
        const xpath2 = `//*[@id="drv${current}_1"]/td`;
        const b = document.evaluate(xpath2, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
        // 矩阵题的选项数量
        const optionCount = b.snapshotLength - 1;
        // 转嵌套的数组/////////////////////////////////////////////////////////////
        const matrix_arrays = Object.values(matrix_prob);
        // 遍历每个数组并归一化
        const normalizedArrays = matrix_arrays.map((arr) => {
            return normArray(arr)
        });
        for (let i = 1; i <= q_num; i++) {
            //生成[2,optionCount]之间的随机数
            var opt = singleRatio([2, optionCount], normalizedArrays[i - 1])
            var nthElement = document.querySelectorAll(`#drv${current}_${i} td`)[opt - 1];
            nthElement.click()
        }
    }
    //量表题函数
    function scale(current, ratio) {
        let xpath = `//*[@id="div${current}"]/div[2]/div/ul/li`;
        let a = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
        let b = singleRatio([1, a.snapshotLength], ratio);
        let element = document.querySelector(`#div${current} > div.scale-div > div > ul > li:nth-child(${b})`);
        element.click();
        console.log("第", current, "题选择了第", b, "个选项")
        return b
    }
    //滑块题函数
    function slide(current,min,max) {
        var score = randint(min, max)
        document.querySelector(`#q${current}`).value = score
        console.log("第", current, "题填写了", score)
    }
    //填空题函数
    function vacant(current, texts, ratio) {
        var text_index = singleRatio([0, texts.length - 1], ratio)
        document.querySelector(`#q${current}`).value = texts[text_index]
        console.log("第", current, "题填写了", texts[text_index])
    }

    //数组归一化
    function normArray(arr) {
        // 计算数组元素的总和
        const sum = arr.reduce((accum, val) => accum + val, 0);
        // 对每个元素进行最大值归一化
        return arr.map(val => val / sum);
    }
    //单选题概率函数:返回一个数字[1, 4],[0.1, 0.2, 0.3, 0.4]
    function singleRatio(range, ratio) {
        let weight = [];
        let sum = 0;
        for (let i = range[0]; i <= range[1]; i++) {
            sum += ratio[i - range[0]];
            weight.push(sum);
        }
        const rand = Math.random() * sum;
        for (let i = 0; i < weight.length; i++) {
            if (rand < weight[i]) {
                return i + range[0];
            }
        }
    }
    // 生成介于a到b之间的随机整数,包括a和b
    function randint(a, b) {
        return Math.floor(Math.random() * (b - a + 1) + a);
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址