您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
强国学习自动答题,目前实现 每日答题,每周答题,专项答题
当前为
// ==UserScript== // @name 好好学习,天天向上 // @namespace 雪导. // @version 1.0 // @description 强国学习自动答题,目前实现 每日答题,每周答题,专项答题 // @author 雪导 // @match https://pc.xuexi.cn/points/exam-practice.html* // @match https://pc.xuexi.cn/points/exam-weekly-detail.html* // @match https://pc.xuexi.cn/points/exam-paper-detail.html* // @match https://pc.xuexi.cn/points/my-study.html* // @match https://pc.xuexi.cn/points/exam-index.html* // @match https://pc-api.xuexi.cn/open/api/score/today/queryrate // @grant none // ==/UserScript== window.onload = function () { console.log('加载成功') //移除顶部 const header = document.querySelector('#app > div > div.layout-header') if (header != null) { header.parentNode.removeChild(header) console.log('移除header乱七八糟的dom') } //移除底部 const footer = document.querySelector('#app > div > div.layout-footer') if (footer != null) { footer.parentNode.removeChild(footer) console.log('移除footer乱七八糟的dom') } // setInterval(doit,500); const doit = () => { console.log('===========开始答题===========') let nextAll = document.querySelectorAll('.ant-btn') let next = nextAll[0] if (nextAll.length == 2) { //俩按钮,说明有个按钮是交卷。 next = nextAll[1] } console.log(next) if (next.disabled) { document.querySelector('.tips').click() //所有提示 let allTips = document.querySelectorAll('font[color=red]') //单选多选时候的按钮 let buttons = document.querySelectorAll('.q-answer') //填空时候的那个textbox,这里假设只有一个填空 let textboxs = document.querySelectorAll('input') //问题类型 let qType = document.querySelector('.q-header').textContent qType = qType.substr(0, 3) switch (qType) { case '填空题': //第几个填空 let mevent = new Event('input', { bubbles: true }) if (textboxs.length > 1) { //若不止是一个空 //填空数量和提示数量是否一致 if (allTips.length == textboxs.length) { for ( let i = 0; i < allTips.length; i++ //数量一致,则一一对应。 ) { let tip = allTips[i] let tipText = tip.textContent if (tipText.length > 0) { //通过设置属性,然后立即让他冒泡这个input事件. //否则1,setattr后,内容消失. //否则2,element.value=124后,属性值value不会改变,所以冒泡也不管用. textboxs[i].setAttribute('value', tipText) textboxs[i].dispatchEvent(mevent) // break; } } } else { //若填空数量和提示数量不一致,那么,应该都是提示数量多。 if (allTips.length > textboxs.length) { let lineFeed = document.querySelector('.line-feed').textContent //这个是提示的所有内容,不仅包含红色答案部分。 let n = 0 //计数,第几个tip。 for ( let j = 0; j < textboxs.length; j++ //多个填空 ) { let tipText = allTips[n].textContent let nextTipText = '' do { tipText += nextTipText if (n < textboxs.length - 1) { n++ nextTipText = allTips[n].textContent } else { nextTipText = '结束了,没有了。' } } while (lineFeed.indexOf(tipText + nextTipText)) textboxs[j].setAttribute('value', tipText) textboxs[j].dispatchEvent(mevent) } } else { //提示数量少于填空数量,则我无法分析, 回头研究,暂时放弃作答,刷新题库浏览器 location.reload() } } } else if (textboxs.length == 1) { //只有一个空,直接把所有tips合并。 let tipText = '' for (let i = 0; i < allTips.length; i++) { tipText += allTips[i].textContent } textboxs[0].setAttribute('value', tipText) textboxs[0].dispatchEvent(mevent) break } else { //怕有没空白的情况。 看视频。。 history.go(0) } break case '多选题': //循环选项列表。用来点击 for (let js = 0; js < buttons.length; js++) { let cButton = buttons[js] for ( let i = 0; i < allTips.length; i++ //循环提示列表。 ) { let tip = allTips[i] let tipText = tip.textContent if (tipText.length > 0) { //提示内容长度大于0 let cButtonText = cButton.textContent //选项按钮的内容 //循环对比点击 if ( cButtonText.indexOf(tipText) > -1 || tipText.indexOf(cButtonText) > -1 ) { cButton.click() break } } } } break case '单选题': //单选,所以所有的提示,其实是同一个。有时候,对方提示会分成多个部分。 //case 块里不能直接用let。所以增加了个if。 if (true) { //把红色提示组合为一条 let tipText = '' for (let i = 0; i < allTips.length; i++) { tipText += allTips[i].textContent } if (tipText.length > 0) { //循环对比后点击 let xiangsidu = [] // 相似度 let max_xiangsidu = 0 let index = 0 for (let js = 0; js < buttons.length; js++) { let cButton = buttons[js] let cButtonText = cButton.textContent console.log('cButtonText', cButtonText) console.log('tipText', tipText) //通过判断是否相互包含,来确认是不是此选项 if ( cButtonText.indexOf(tipText) > -1 || tipText.indexOf(cButtonText) > -1 ) { cButton.click() break } else { // 没有找到,判断 内容相似程度 xiangsidu.push(strSimilarity2Percent(tipText, cButtonText)) } } console.log(xiangsidu) max_xiangsidu = max(xiangsidu) index = xiangsidu.findIndex(item => item === max_xiangsidu) buttons[index].click() } // 选择完后,点击确定 console.log(document.querySelector('.ant-btn').click()) document.querySelector('.ant-btn').click() } break default: break } document.querySelector('.ant-btn').click() setTimeout(() => { doit() }, 2500) } else { if ( next.textContent != '再练一次' && next.textContent != '再来一组' && next.textContent != '查看解析' ) { next.click() } else { // 结束 } } } let btn = document.querySelector('.ant-btn') if (btn) { if (btn.textContent === '确 定') { doit() } else { location.reload() } } } // ============= 工具 ============= const strSimilarity2Number = (s, t) => { var n = s.length, m = t.length, d = [] var i, j, s_i, t_j, cost if (n == 0) return m if (m == 0) return n for (i = 0; i <= n; i++) { d[i] = [] d[i][0] = i } for (j = 0; j <= m; j++) { d[0][j] = j } for (i = 1; i <= n; i++) { s_i = s.charAt(i - 1) for (j = 1; j <= m; j++) { t_j = t.charAt(j - 1) if (s_i == t_j) { cost = 0 } else { cost = 1 } d[i][j] = Minimum( d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost ) } } return d[n][m] } const Minimum = (a, b, c) => { return a < b ? (a < c ? a : c) : b < c ? b : c } // 判断两个字符串 相似度 const strSimilarity2Percent = (s, t) => { var l = s.length > t.length ? s.length : t.length var d = strSimilarity2Number(s, t) return (1 - d / l).toFixed(4) } /** * 获取数组中的 最大值 * @param {*} arr * @returns */ const max = arr => { var num = arr[0] for (var i = 0; i < arr.length; i++) { if (num < arr[i]) { num = arr[i] } } return num }