您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
根据输入的XPath定位元素进行循环点击及按指定文本查找点击元素,优化了遍历框架查找元素、点击停止功能、执行顺序及延时机制,设置成分区形式,美化按钮样式,并添加每次点击时间显示功能,同时添加脚本保活机制。
当前为
// ==UserScript== // @name 网页基于xpath|文本的自动点击(优化版) // @namespace https://game.lpengine.cn/* // @version 1.0.2 // @description 根据输入的XPath定位元素进行循环点击及按指定文本查找点击元素,优化了遍历框架查找元素、点击停止功能、执行顺序及延时机制,设置成分区形式,美化按钮样式,并添加每次点击时间显示功能,同时添加脚本保活机制。 // @author toyourtomorrow // @match https://fz.lpengine.cn/* // @match https://game.lpengine.cn/* // @match *://*/* // @grant GM_setValue // @grant GM.getValue // @grant GM_addStyle // ==/UserScript== (function () { 'use strict'; // 创建用于输入XPath、延时、指定文本以及显示状态的HTML元素,并设置样式使其在最上方显示,同时设置初始为可拖动状态,设置分区形式 const inputDiv = document.createElement('div'); inputDiv.style.position = 'fixed'; inputDiv.style.top = '10px'; inputDiv.style.left = '10px'; inputDiv.style.zIndex = '9999'; inputDiv.style.backgroundColor = '#f8f9fa'; inputDiv.style.padding = '10px'; inputDiv.style.borderRadius = '5px'; inputDiv.style.boxShadow = '0 0 5px rgba(0, 0, 0, 0.2)'; inputDiv.style.userSelect = 'none'; // 防止文本被误选 inputDiv.draggable = true; // 设置可拖动 inputDiv.innerHTML = ` <div style="display: flex; flex-direction: column;"> <!-- XPath 分区 --> <div style="background-color: #e9ecef; padding: 10px; border-radius: 5px; margin-bottom: 10px;"> <div style="display: flex; align-items: center; margin-bottom: 10px;"> <label for="xpathInput" style="margin-right: 10px;">XPath表达式:</label> <input type="text" id="xpathInput" style="padding: 5px; border: 1px solid #ced4da; border-radius: 3px; width: 300px;" /> </div> <div style="display: flex; align-items: center; margin-bottom: 10px;"> <label for="xpathDelayInput" style="margin-right: 10px;">XPath延时(毫秒):</label> <input type="number" id="xpathDelayInput" style="padding: 5px; border: 1px solid #ced4da; border-radius: 3px; width: 100px;" value="300" /> </div> <div style="display: flex; align-items: center;"> <button id="startXPathButton" style="padding: 5px 10px; border: none; border-radius: 3px; background-color: #007bff; color: white; cursor: pointer;">开始点击(XPath)</button> <button id="stopXPathButton" style="padding: 5px 10px; border: none; border-radius: 3px; background-color: #dc3545; color: white; cursor: pointer;">停止点击(XPath)</button> </div> <span id="xpathStatus" style="margin-left: 10px; color: #6c757d; margin-top: 10px;">状态: 未开始</span> <span id="xpathLastClickTime" style="margin-left: 10px; color: #6c757d; margin-top: 5px;">上次点击时间(XPath): -</span> <span id="xpathNextClickTime" style="margin-left: 10px; color: 6c757d; margin-top: 5px;">下次点击时间(XPath): -</span> </div> <!-- 文本分区 --> <div style="background-color: #e9ecef; padding: 10px; border-radius: 5px;"> <div style="display: flex; align-items: center; margin-bottom: 10px;"> <label for="textInput" style="margin-right: 10px;">指定文本:</label> <input type="text" id="textInput" style="padding: 5px; border: 1px solid #ced4da; border-radius: 3px; width: 200px;" /> </div> <div style="display: flex; align-items: center; margin-bottom: 10px;"> <label for="textDelayInput" style="margin-right: 10px;">文本延时(毫秒):</label> <input type="number" id="textDelayInput" style="padding: 5px; border: 1px solid #ced4da; border-radius: 3px; width: 100px;" value="300" /> </div> <div style="display: flex; align-items: center;"> <button id="startTextButton" style="padding: 5px 10px; border: none; border-radius: 3px; background-color: #28a745; color: white; cursor: pointer;">开始点击(文本)</button> <button id="stopTextButton" style="padding: 5px 10px; border: none; border-radius: 3px; background-color: #6c757d; color: white; cursor: pointer;">停止点击(文本)</button> </div> <span id="textStatus" style="margin-left: 10px; color: #6c757d; margin-top: 10px;">状态: 未开始</span> <span id="textLastClickTime" style="margin-left: 10px; color: #6c757d; margin-top: 5px;">上次点击时间(文本): -</span> <span id="textNextClickTime" style="margin-left: 10px; color: 6c757d; margin-top: 5px;">下次点击时间(文本): -</span> </div> <button id="closeButton" style="padding: 5px 10px; border: none; border-radius: 3px; background-color: #6c757d; color: white; cursor: pointer; margin-top: 15px;">关闭</button> <button id="minimizeButton" style="padding: 5px 10px; border: none; border-radius: 3px; background-color: #6c757d; color: white; cursor: pointer; margin-top: 5px;">缩小</button> </div> `; document.body.appendChild(inputDiv); // 用于记录鼠标按下时的坐标,实现拖动功能 let startX, startY; // 为可拖动元素添加鼠标按下、移动和抬起事件监听器,正确实现拖动功能 inputDiv.addEventListener('mousedown', function (e) { startX = e.clientX; startY = e.clientY; document.addEventListener('mousemove', drag); document.addEventListener('mouseup', stopDrag); }); function drag(e) { const dx = e.clientX - startX; const dy = e.clientY - startY; inputDiv.style.left = (parseInt(inputDiv.style.left) || 0) + dx + 'px'; inputDiv.style.top = (parseInt(inputDiv.style.top) || 0) + dy + 'px'; startX = e.clientX; startY = e.clientY; } function stopDrag() { document.removeEventListener('mousemove', drag); document.removeEventListener('mouseup', stopDrag); } // 记录界面是否最小化 let isMinimized = false; // 缩小按钮点击事件处理函数 function minimize() { if (isMinimized) { // 如果已最小化,恢复原始大小,并重新显示文字相关元素 inputDiv.style.width = 'auto'; inputDiv.style.height = 'auto'; inputDiv.querySelectorAll('span').forEach(span => span.style.display = ''); isMinimized = false; } else { // 如果未最小化,缩小界面并隐藏文字相关元素 inputDiv.style.width = '30px'; inputDiv.style.height = '30px'; inputDiv.querySelectorAll('span').forEach(span => span.style.display = 'none'); isMinimized = true; } } // 获取相关DOM元素 const xpathInput = document.getElementById('xpathInput'); const xpathDelayInput = document.getElementById('xpathDelayInput'); const startXPathButton = document.getElementById('startXPathButton'); const stopXPathButton = document.getElementById('stopXPathButton'); const textInput = document.getElementById('textInput'); const textDelayInput = document.getElementById('textDelayInput'); const startTextButton = document.getElementById('startTextButton'); const stopTextButton = document.getElementById('stopTextButton'); const closeButton = document.getElementById('closeButton'); const minimizeButton = document.getElementById('minimizeButton'); const xpathStatusSpan = document.getElementById('xpathStatus'); const xpathLastClickTimeSpan = document.getElementById('xpathLastClickTime'); const xpathNextClickTimeSpan = document.getElementById('xpathNextClickTime'); const textStatusSpan = document.getElementById('textStatus'); const textLastClickTimeSpan = document.getElementById('textLastClickTime'); const textNextClickTimeSpan = document.getElementById('textNextClickTime'); // 初始化保存的XPath值、延时值和指定文本值(如果存在) (async () => { const savedXPath = await GM.getValue('savedXPath', ''); const savedXPathDelay = await GM.getValue('savedXPathDelay', 300); const savedText = await GM.getValue('savedText', ''); const savedTextDelay = await GM.getValue('savedTextDelay', 300); xpathInput.value = savedXPath; xpathDelayInput.value = savedXPathDelay; textInput.value = savedText; textDelayInput.value = savedTextDelay; })(); // 用于存储基于XPath点击的定时器标识和基于文本点击的定时器标识 let xPathIntervalId = null; let textIntervalId = null; // 递归遍历所有节点(包括跨iframe、处理Shadow DOM等)查找元素的函数(XPath方式),优化错误处理 function findElementsByXPathInAllContexts(xpath, context = document) { const results = []; const iterate = (node) => { try { const elements = document.evaluate(xpath, node, null, XPathResult.ANY_TYPE, null).iterateNext(); while (elements) { results.push(elements); elements = document.evaluate(xpath, node, null, XPathResult.ANY_TYPE, null).iterateNext(); } } catch (error) { console.error('XPath查找元素出现错误:', error); } const shadowRoots = node.querySelectorAll('*'); shadowRoots.forEach((element) => { if (element.shadowRoot) { iterate(element.shadowRoot); } }); const iframes = node.querySelectorAll('iframe'); for (const iframe of iframes) { try { const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; iterate(iframeDoc); } catch (error) { console.error('处理iframe时出现错误:', error); continue; } } }; iterate(context); return results; } // 递归遍历所有节点(包括跨iframe、处理Shadow DOM等)查找包含指定文本元素的函数,优化错误处理 function findElementsByTextInAllContexts(text, context = document) { const results = []; const iterate = (node) => { const elements = node.querySelectorAll('*'); elements.forEach((element) => { try { if (element.textContent.includes(text)) { results.push(element); } } catch (error) { console.error('文本查找元素出现错误:', error); } }); const shadowRoots = node.querySelectorAll('*'); shadowRoots.forEach((element) => { if (element.shadowRoot) { iterate(element.shadowRoot); } }); const iframes = node.querySelectorAll('iframe'); for (const iframe of iframes) { try { const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; iterate(iframeDoc); } catch (error) { console.error('处理iframe时出现错误:', error); continue; } } }; iterate(context); return results; } // 等待页面加载完成(包括所有资源、iframe等加载完毕)后再执行查找等操作的函数 function waitForPageLoad(callback) { if (document.readyState === 'complete') { callback(); } else { window.addEventListener('load', callback); } } // 开始点击的函数(基于XPath),优化执行顺序和时间显示 async function startClickingByXPath() { const xpath = xpathInput.value; const delay = parseInt(xpathDelayInput.value, 10); GM_setValue('savedXPath', xpath); GM_setValue('savedXPathDelay', delay); try { waitForPageLoad(() => { const startTime = Date.now(); const doClick = async () => { const elements = findElementsByXPathInAllContexts(xpath); if (elements.length > 0) { for (const element of elements) { element.click(); } const currentTime = Date.now(); xpathLastClickTimeSpan.textContent = `上次点击时间(XPath): ${new Date(currentTime).toLocaleString()}`; xpathNextClickTimeSpan.textContent = `下次点击时间(XPath): ${new Date(currentTime + delay).toLocaleString()}`; } else { clearInterval(xPathIntervalId); alert('未找到匹配XPath的元素,已停止点击。'); xpathStatusSpan.textContent = '状态: 已停止(未找到元素)'; } }; doClick(); xPathIntervalId = setInterval(doClick, delay); xpathStatusSpan.textContent = '状态: 正在点击(XPath)'; }); } catch (error) { clearInterval(xPathIntervalId); alert('执行过程出现错误,请检查XPath表达式是否正确。'); xpathStatusSpan.textContent = '状态: 已停止(出错)'; } } // 开始点击的函数(基于指定文本),优化执行顺序和时间显示 async function startClickingByText() { const text = textInput.value; const delay = parseInt(textDelayInput.value, 10); GM_setValue('savedText', text); GM_setValue('savedTextDelay', delay); try { waitForPageLoad(() => { const startTime = Date.now(); const doClick = async () => { const elements = findElementsByTextInAllContexts(text); if (elements.length > 0) { for (const element of elements) { element.click(); } const currentTime = Date.now(); textLastClickTimeSpan.textContent = `上次点击时间(文本): ${new Date(currentTime).toLocaleString()}`; textNextClickTimeSpan.textContent = `下次点击时间(文本): ${new Date(currentTime + delay).toLocaleString()}`; } else { clearInterval(textIntervalId); alert('未找到包含指定文本的元素,已停止点击。'); textStatusSpan.textContent = '状态: 已停止(未找到元素)'; } }; doClick(); textIntervalId = setInterval(doClick, delay); textStatusSpan.textContent = '状态: 正在点击(文本)'; }); } catch (error) { clearInterval(textIntervalId); alert('执行过程出现错误,请检查输入的文本是否正确。'); textStatusSpan.textContent = '状态: 已停止(出错)'; } } // 为开始按钮(XPath方式)添加点击事件监听器 startXPathButton.addEventListener('click', startClickingByXPath); // 为停止按钮(XPath方式)添加点击事件监听器 stopXPathButton.addEventListener('click', () => { if (xPathIntervalId) { clearInterval(xPathIntervalId); xPathIntervalId = null; xpathStatusSpan.textContent = '状态: 已停止'; } }); // 为开始按钮(文本方式)添加点击事件监听器 startTextButton.addEventListener('click', startClickingByText); // 为停止按钮(文本方式)添加点击事件监听器 stopTextButton.addEventListener('click', () => { if (textIntervalId) { clearInterval(textIntervalId); textIntervalId = null; textStatusSpan.textContent = '状态: 已停止'; } }); // 为关闭按钮添加点击事件监听器,点击后移除整个输入框区域 closeButton.addEventListener('click', () => { inputDiv.remove(); }); // 为缩小按钮添加点击事件监听器 minimizeButton.addEventListener('click', minimize); // 脚本保活机制,定期执行一个简单的函数来保持脚本活跃,这里简单打印个信息示例,可按需调整具体逻辑 setInterval(() => { console.log('脚本保持活跃'); }, 60000); // 每60秒执行一次,可根据实际情况调整时间间隔 })();