您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
英华自动答题
当前为
// ==UserScript== // @name 英华自动答题PRO // @namespace http://tampermonkey.net/ // @version 2.0 // @description 英华自动答题 // @author AAAcon // @match *://*/user/work* // @match *://*/user/node* // @match *://*/user/exam* // @grant GM_xmlhttpRequest // @grant GM_openInTab // @license MIT // ==/UserScript== (function() { 'use strict'; // 在脚本开始时初始化日志系统 window.unifiedWindow = createUnifiedWindow(); const logger = createLogger(); // 创建一个新的代理对象来处理控制台输出 const consoleProxy = new Proxy(console, { get: function(target, property) { const original = target[property]; if (typeof original === 'function') { return function(...args) { // 调用原始方法 original.apply(target, args); // 记录到我们的日志系统 if (logger && typeof logger.log === 'function') { try { logger.log(args.join(' '), property); } catch (e) { original.call(target, '日志记录失败:', e); } } }; } return original; } }); // 替换全局 console 对象 window.console = consoleProxy; // 确保在所有初始化完成后再切换到日志标签 setTimeout(() => { const { logContent } = window.unifiedWindow; if (logContent) { logContent.style.display = 'block'; const testInfoContent = window.unifiedWindow.testInfoContent; if (testInfoContent) { testInfoContent.style.display = 'none'; } // 更新标签样式 const logTab = document.querySelector('button'); const testTab = document.querySelectorAll('button')[0]; if (logTab && testTab) { logTab.style.background = '#1890ff'; logTab.style.color = 'white'; testTab.style.background = '#f5f5f5'; testTab.style.color = '#666'; } console.log('日志页面已初始化并显示'); } }, 500); // 自动寻找测试章节的脚本 // 修改 findTestSections 函数为异步函数 async function findTestSections() { const chapterGroups = document.querySelectorAll('.detmain-navlist .group'); const testSections = []; const promises = []; chapterGroups.forEach(group => { const chapterName = group.querySelector('.name a')?.getAttribute('title') || ''; const items = group.querySelectorAll('.list .item a'); let homeworkItem = Array.from(items).find(item => item.textContent.includes('章节作业')); if (!homeworkItem) { homeworkItem = Array.from(items).find(item => item.textContent.includes('章')); if (!homeworkItem) return; } // 将每个 fetch 操作添加到 promises 数组中 promises.push( fetch(homeworkItem.href) .then(response => response.text()) .then(html => { const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); const startButton = doc.querySelector('.detmain-stard a[target="_blank"]'); if (!startButton || !startButton.textContent.includes('开始做题')) return null; return { chapter: chapterName, title: (doc.querySelector('.detmain-title')?.textContent || '').replace('作业标题:', '').trim(), startTime: (doc.querySelector('.detmain-notes .item:nth-child(1)')?.textContent || '').replace('开始时间:', '').trim(), endTime: (doc.querySelector('.detmain-notes .item:nth-child(2)')?.textContent || '').replace('结束时间:', '').trim(), totalScore: (doc.querySelector('.good')?.textContent || '').replace('总分:', '').replace('分', '').trim(), attempts: doc.querySelector('.detmain-dest .item span')?.textContent || '', startUrl: startButton.href }; }) .catch(error => { console.error('获取章节信息失败:', error); return null; }) ); }); // 等待所有 fetch 操作完成 const results = await Promise.all(promises); results.forEach(result => { if (result) testSections.push(result); }); // 更新显示 displayTestInfo(testSections); return testSections; } // 修改 findAndShowTests 函数为异步函数 async function findAndShowTests() { const tests = await findTestSections(); console.log('找到的测试章节:', tests); return tests; } // 修改自动执行部分 setTimeout(async () => { try { const tests = await findTestSections(); console.log('找到的测试章节:', tests); if (tests && tests.length > 0) { console.log('自动开始完成所有作业'); await startAutoComplete(tests); } } catch (error) { console.error('执行自动答题时出错:', error); } }, 1000); // 修改 createLogger 函数 function createLogger() { if (!window.unifiedWindow) { window.unifiedWindow = createUnifiedWindow(); } const { logContent } = window.unifiedWindow; logContent.style.cssText = ` display: none; max-height: 350px; overflow-y: auto; font-family: monospace; background: rgba(0, 0, 0, 0.8); border-radius: 8px; padding: 15px; color: #fff; `; // 添加清空按钮 const clearButton = document.createElement('button'); clearButton.textContent = '清空日志'; clearButton.style.cssText = ` background: none; border: 1px solid rgba(255,255,255,0.3); color: #fff; padding: 5px 10px; border-radius: 4px; cursor: pointer; margin-bottom: 10px; `; clearButton.onclick = () => { logContent.innerHTML = ''; logContent.appendChild(clearButton); }; logContent.appendChild(clearButton); return { log: (message, type = 'info') => { const time = new Date().toLocaleTimeString(); const colors = { info: '#8cc', success: '#8c8', error: '#c88', warn: '#cc8' }; const line = document.createElement('div'); line.style.cssText = ` margin: 5px 0; color: ${colors[type]}; word-break: break-all; `; line.innerHTML = `[${time}] ${message}`; logContent.appendChild(line); logContent.scrollTop = logContent.scrollHeight; } }; } // 创建统一窗口 function createUnifiedWindow() { const container = document.createElement('div'); container.style.cssText = ` position: fixed; top: 20px; right: 20px; width: 300px; max-height: 80vh; background: white; border: 1px solid #eee; border-radius: 12px; padding: 20px; z-index: 9999; overflow-y: auto; box-shadow: 0 8px 24px rgba(0,0,0,0.12); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial; transition: all 0.3s ease; backdrop-filter: blur(10px); background: rgba(255, 255, 255, 0.95); `; // 创建标题栏 const header = document.createElement('div'); header.style.cssText = ` display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid #eee; `; // 创建标签切换按钮 const tabs = document.createElement('div'); tabs.style.cssText = ` display: flex; gap: 10px; `; const testTab = document.createElement('button'); const logTab = document.createElement('button'); const tabStyle = ` padding: 6px 12px; border: none; border-radius: 6px; cursor: pointer; font-size: 14px; transition: all 0.3s; `; testTab.textContent = '测试章节'; logTab.textContent = '运行日志'; testTab.style.cssText = tabStyle; logTab.style.cssText = tabStyle; tabs.appendChild(testTab); tabs.appendChild(logTab); header.appendChild(tabs); // 创建关闭按钮 const closeButton = document.createElement('button'); closeButton.innerHTML = '×'; closeButton.style.cssText = ` background: none; border: none; font-size: 20px; cursor: pointer; color: #999; padding: 0 5px; &:hover { color: #666; } `; closeButton.onclick = () => container.remove(); header.appendChild(closeButton); container.appendChild(header); // 创建内容区域 const testInfoContent = document.createElement('div'); const logContent = document.createElement('div'); testInfoContent.style.display = 'block'; logContent.style.display = 'none'; container.appendChild(testInfoContent); container.appendChild(logContent); // 标签切换功能 testTab.onclick = () => { testTab.style.background = '#1890ff'; testTab.style.color = 'white'; logTab.style.background = '#f5f5f5'; logTab.style.color = '#666'; testInfoContent.style.display = 'block'; logContent.style.display = 'none'; }; logTab.onclick = () => { logTab.style.background = '#1890ff'; logTab.style.color = 'white'; testTab.style.background = '#f5f5f5'; testTab.style.color = '#666'; testInfoContent.style.display = 'none'; logContent.style.display = 'block'; }; // 初始状态 - 修改这里,默认显示日志页面 logTab.click(); document.body.appendChild(container); return { container, testInfoContent, logContent }; } // 修改 displayTestInfo 函数 function displayTestInfo(tests) { const { testInfoContent } = window.unifiedWindow || createUnifiedWindow(); if (tests.length === 0) { testInfoContent.innerHTML = '<p style="color: #ff4d4f; font-size: 14px; text-align: center;">未找到可用的测试章节</p>'; return; } let html = '<h3 style="margin: 0 0 15px 0; color: #1a1a1a; font-size: 16px;">找到的测试章节:</h3>'; html += ` <div style="margin-bottom: 20px;"> <button id="autoStartAllTests" style=" width: 100%; background: linear-gradient(145deg, #1890ff, #40a9ff); color: white; border: none; padding: 10px 20px; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 14px; transition: all 0.3s ease; box-shadow: 0 2px 8px rgba(24, 144, 255, 0.15);"> 自动开始所有作业 </button> </div> `; tests.forEach((test, index) => { html += ` <div style=" margin-bottom: 15px; padding: 15px; border: 1px solid #f0f0f0; border-radius: 10px; background: #fff; transition: all 0.3s ease; cursor: pointer; position: relative; overflow: hidden; &:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.08); border-color: #e6f7ff; }"> <div style="font-weight: 600; font-size: 15px; color: #262626; margin-bottom: 8px;"> ${index + 1}. ${test.chapter} </div> <div style="font-weight: 500; margin: 8px 0; color: #1890ff;"> ${test.title} </div> <div style="font-size: 13px; color: #595959; margin: 12px 0;"> <div style="display: flex; justify-content: space-between; margin-bottom: 6px;"> <span>开始时间: ${test.startTime}</span> <span>结束时间: ${test.endTime}</span> </div> <div style="display: flex; justify-content: space-between;"> <span>总分: ${test.totalScore}分</span> <span>剩余次数: ${test.attempts}次</span> </div> </div> <a href="${test.startUrl}" target="_blank" style=" display: block; width: 100%; padding: 8px 0; background: #f5f5f5; color: #262626; text-decoration: none; border-radius: 6px; font-size: 13px; text-align: center; transition: all 0.3s ease; margin-top: 10px; &:hover { background: #e6f7ff; color: #1890ff; }"> 开始做题 </a> </div> `; }); // 添加关闭按钮 html += ` <button onclick="this.parentElement.remove()" style="position: absolute; top: 12px; right: 12px; background: none; border: none; cursor: pointer; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; font-size: 18px; color: #999; border-radius: 50%; transition: all 0.3s ease; &:hover { background: #f5f5f5; color: #666; }"> × </button> `; testInfoContent.innerHTML = html; // 使用 setTimeout 确保 DOM 完全更新后再绑定事件 setTimeout(() => { const autoStartButton = document.getElementById('autoStartAllTests'); if (autoStartButton) { autoStartButton.addEventListener('click', () => { console.log('点击了:autoStartAllTests'); console.log('开始自动完成所有作业,共', tests.length, '个章节'); startAutoComplete(tests); }); console.log('事件监听器已成功绑定'); } else { console.error('未找到自动开始按钮'); } }, 0); } // 添加自动答题初始化函数 function initAutoAnswer() { // 检查当前页面是否是答题页面 if (window.location.href.includes('/user/work') || window.location.href.includes('/user/exam')) { console.log('检测到是答题页面'); // 处理开始答题页面 async function handleStartPage() { // 使用更精确的选择器 await waitForElement('#startArea #start-btn.start-work' || '#startArea #start-btn.start-exam', () => { console.log('找到开始答题按钮'); const startBtn = document.querySelector('#startArea #start-btn.start-work'); const startBt = document.querySelector('#startArea #start-btn.start-exam'); if (startBtn || startBt) { startBtn.click(); startBtn.click(); console.log('点击开始答题按钮'); } }); // 等待确认弹窗出现 await waitForElement('.layui-layer-btn0', () => { console.log('找到确认弹窗'); const confirmBtn = document.querySelector('.layui-layer-btn0'); if (confirmBtn) { setTimeout(() => { confirmBtn.click(); console.log('点击确认按钮'); }, randomDelay()); } }); // 等待题目加载完成后开始答题 await waitForElement('.topic-item', () => { console.log('答题页面加载完成,自动开始答题'); autoAnswer(); }); } // 开始执行 handleStartPage(); } } // 等待页面加载完成 function waitForElement(selector, callback) { if (document.querySelector(selector)) { callback(); } else { setTimeout(() => waitForElement(selector, callback), 500); } } // 随机延迟函数 (1-3秒) const randomDelay = () => Math.floor(Math.random() * 2000) + 1000; // 自动答题主函数 async function autoAnswer() { try { // 检查弹窗 const confirmBtn = document.querySelector('.layui-layer-btn0'); if (confirmBtn) { console.log('检测到弹窗,点击确认按钮'); confirmBtn.click(); // 等待随机延迟 await new Promise(resolve => setTimeout(resolve, randomDelay())); // 处理可能的后续弹窗 for (let i = 0; i < 2; i++) { const nextConfirmBtn = document.querySelector('.layui-layer-btn0'); if (nextConfirmBtn) { console.log('检测到弹窗,点击确认按钮'); nextConfirmBtn.click(); await new Promise(resolve => setTimeout(resolve, randomDelay())); } } // 检查完成按钮 const completeBtn = document.querySelector('.complete'); if (completeBtn && completeBtn.style.display !== 'none') { console.log('点击完成作业按钮'); completeBtn.click(); // 等待最后的确认弹窗 await new Promise(resolve => setTimeout(resolve, randomDelay())); const finalConfirmBtn = document.querySelector('.layui-layer-btn0'); if (finalConfirmBtn) { console.log('检测到弹窗,点击确认按钮'); finalConfirmBtn.click(); } } else { await continueAnswer(); } return; } // 如果没有弹窗,继续答题流程 await continueAnswer(); } catch (error) { console.error('自动答题过程出错:', error); } } // 答题逻辑函数 async function continueAnswer() { // 获取当前显示的题目 const currentQuestion = document.querySelector('.topic-item[style=""]') || document.querySelector('.topic-item:not([style*="none"])') || document.querySelector('.topic-item topic-type-1[style=""]'); if (!currentQuestion) { const completeBtn = document.querySelector('.complete'); if (completeBtn && completeBtn.style.display !== 'none') { console.log('所有题目已完成,点击完成按钮'); setTimeout(() => completeBtn.click(), randomDelay()); } return; } // 获取题目信息 const typeElement = currentQuestion.querySelector('.type'); const nameElement = currentQuestion.querySelector('.name'); if (!typeElement || !nameElement) { console.error('无法找到题目类型或题目内容元素'); return; } const questionType = typeElement.textContent.trim(); const questionText = nameElement.textContent.trim(); // 获取所有选项 const options = currentQuestion.querySelectorAll('.exam-inp'); if (!options.length) return; // 构建选项数组 const optionsArray = Array.from(options).map(option => { const textElement = option.parentElement.querySelector('.txt'); if (!textElement) { console.error('无法找到选项文本元素'); return { value: option.value, text: '' }; } return { value: option.value, text: textElement.textContent.trim() }; }); // 查询答案 const an = await queryAnswer(questionText, optionsArray, questionType); let answer = an.trim(); if(answer==='对'){ answer='正确'; } if (answer) { console.log('获取到答案:', answer); // 根据答案类型选择 if (questionType === '单选' || questionType === '判断') { let answerSlect = false; // 查找匹配的选项并点击 for (let option of options) { const optionText = option.parentElement.querySelector('.txt').textContent.trim(); if (optionText.includes(answer)) { option.click(); answerSlect = true; console.log(`${questionType}已选择:`, optionText); break; } } // 如果没有找到答案,使用随机选择 if(!answerSlect){ console.log('未找到答案,使用随机答案'); const randomIndex = Math.floor(Math.random() * options.length); options[randomIndex].click(); console.log(`${questionType}已随机选择: ${options[randomIndex].value}`); } } else if (questionType === '多选') { let answerSlect = false; // 处理多选题答案(使用###分隔的字符串) const answers = answer.split('###').map(a => a.trim()); for (let option of options) { const optionText = option.parentElement.querySelector('.txt').textContent.trim(); if (answers.some(ans => optionText.includes(ans))) { option.click(); answerSlect = true; console.log('多选已选择:', optionText); } } // 如果没有找到答案,使用随机选择 if(!answerSlect){ console.log('未批配答案,使用随机答案'); const selectedCount = Math.floor(Math.random() * 3) + 1; const shuffled = Array.from(options).sort(() => 0.5 - Math.random()); for (let i = 0; i < selectedCount; i++) { shuffled[i].click(); console.log(`多选已随机选择: ${shuffled[i].value}`); } } } } else { console.log('未找到答案,使用随机答案'); // 如果没有找到答案,使用随机选择 if (questionType === '单选' || questionType === '判断') { const randomIndex = Math.floor(Math.random() * options.length); options[randomIndex].click(); console.log(`${questionType}已随机选择: ${options[randomIndex].value}`); } else if (questionType === '多选') { const selectedCount = Math.floor(Math.random() * 3) + 1; const shuffled = Array.from(options).sort(() => 0.5 - Math.random()); for (let i = 0; i < selectedCount; i++) { shuffled[i].click(); console.log(`多选已随机选择: ${shuffled[i].value}`); } } } const randomDelay = () => Math.floor(Math.random() * 2000) + 2000; // 提交按钮 const submitBtn = currentQuestion.querySelector('.next_exam'); if (submitBtn) { setTimeout(() => { submitBtn.click(); console.log('已提交答案'); // 继续下一题 setTimeout(autoAnswer, randomDelay()); }, randomDelay()); } } // 查询答案函数 async function queryAnswer(question, options, type) { // 添加随机延迟 (2-4秒) const delay = Math.floor(Math.random() * 2000) + 2000; await new Promise(resolve => setTimeout(resolve, delay)); return new Promise((resolve, reject) => { console.log('正在查询答案...'); // 清理题目文本中的特殊字符 const cleanTitle = question.trim() .replace(/\s+/g, ' ') // 将多个空格替换为单个空格 .replace(/\xa0/g, ' '); // 替换特殊空格字符 // 标准化处理选项数据 const formattedOptions = options.map(opt => ({ value: opt.value.trim(), text: opt.text.trim() })); GM_xmlhttpRequest({ method: 'GET', url: `http://127.0.0.1:5000/api/query?title=${encodeURIComponent(cleanTitle)}&options=${encodeURIComponent(JSON.stringify(formattedOptions))}&type=${encodeURIComponent(type)}`, onload: function(response) { try { const result = JSON.parse(response.responseText); if (result.code === 0) { console.log('未找到答案'); resolve(null); } else { console.log('答案查询成功'); resolve(result.data.data); } } catch(e) { console.error('解析答案失败:', e); resolve(null); } }, onerror: function(error) { console.error('请求答案失败:', error); resolve(null); } }); }); } // 修改自动开始所有作业函数 async function startAutoComplete(tests) { if (!tests || tests.length === 0) { console.log('没有找到可用的测试'); return; } console.log('开始自动完成所有作业,共', tests.length, '个章节'); for (let i = 0; i < tests.length; i++) { const test = tests[i]; console.log(`开始完成第 ${i + 1} 个作业: ${test.title}`); // 使用 GM_openInTab 打开新标签页 GM_openInTab(test.startUrl, { active: true, insert: true, setParent: true }); // 等待一定时间后继续下一个作业 await new Promise(resolve => setTimeout(resolve, 50000)); } } // 在脚本开始时调用 setTimeout(initAutoAnswer, 1000); // 自动执行 setTimeout(findAndShowTests, 1000); // 在需要记录日志的地方使用 logger.log('初始化完成', 'info'); // 导出函数供其他模块使用 window.findAndShowTests = findAndShowTests; })();