10个基于AI与Tampermonkey的网页自动化技巧:从表单填充到数据抓取

📅 2026/8/24 19:07:25
10个基于AI与Tampermonkey的网页自动化技巧:从表单填充到数据抓取
在实际工作中我们经常需要重复执行一些网页操作比如批量填写表单、抓取特定信息、自动点击按钮或者与网页内容进行交互。手动操作不仅耗时还容易出错。虽然市面上有各种自动化工具但如果你已经习惯使用 ChatGPT 这类 AI 助手那么利用浏览器插件将其与自动化脚本结合可以创造出非常高效的工作流。本文将以 Chrome 浏览器为环境探讨如何借助 ChatGPT 浏览器插件或类似工具的思路实现 10 个实用的网页自动化技巧。我们将从环境搭建、基础脚本编写开始逐步深入到复杂场景并解释每一步背后的原理和常见陷阱。无论你是前端开发者、测试工程师还是希望提升办公效率的普通用户都能从中找到可复现的解决方案。1. 理解浏览器自动化与 AI 插件的结合点浏览器自动化通常指通过脚本程序模拟用户在浏览器中的操作如点击、输入、导航等。传统实现方式包括使用 Selenium、Puppeteer、Playwright 等库。而“ChatGPT 浏览器插件”在这里更多是一个启发性的概念它代表了一种通过自然语言指令或 AI 辅助生成自动化逻辑的可能性。实际上我们可以将自动化需求描述给 AI由 AI 生成对应的 JavaScript 脚本然后通过浏览器的开发者工具或用户脚本管理器如 Tampermonkey来执行。这种结合的核心优势在于降低了编写自动化脚本的门槛。你不需要记忆复杂的 DOM 选择器 API 或事件触发细节只需清晰地描述任务由 AI 生成基础代码你再进行微调和调试。本章节将澄清几个关键概念为后续实践打下基础。1.1 自动化脚本的运行环境内容脚本 vs. 浏览器控制台要在浏览器中执行自动化脚本主要有两种环境浏览器控制台Console这是开发者工具的一部分可以直接执行 JavaScript 来操作当前页面的 DOM。这种方式简单快捷适合临时性、一次性的任务。脚本执行后刷新页面即失效。用户脚本管理器如 Tampermonkey, Violentmonkey这是一个浏览器插件允许你创建和管理能在指定网站自动运行的 JavaScript 脚本称为 UserScript。脚本可以持久化在页面加载时自动注入并执行适合需要重复使用的自动化任务。浏览器插件Extension功能更强大可以拥有自己的界面、后台脚本并能跨标签页操作。开发复杂度较高适合需要复杂交互和持久化存储的自动化场景。对于本文讨论的大多数“技巧”我们将主要使用Tampermonkey和浏览器控制台作为执行环境因为它们学习曲线平缓且能快速验证 AI 生成的代码。1.2 AI 的角色从需求描述到代码生成你不能直接让 ChatGPT 插件“自动化”你的浏览器。正确的工作流是需求分析你自己明确要自动化什么例如“自动点击页面上的‘加载更多’按钮直到它消失”。指令构造将需求转化为给 AI 的清晰提示Prompt例如“请写一段 JavaScript 代码在 Chrome 浏览器控制台运行用于自动查找并点击一个按钮该按钮的文本内容是‘加载更多’直到这个按钮在页面上消失。”代码生成与审查AI 会返回一段 JavaScript 代码。你必须理解这段代码的大致逻辑特别是它如何查找元素使用document.querySelector等以及如何触发事件。环境执行与调试将代码复制到目标环境控制台或 Tampermonkey 脚本中运行并根据实际页面结构进行微调例如修改选择器。1.3 核心工具准备在开始之前请确保你的 Chrome 浏览器已安装以下工具Tampermonkey从 Chrome 网上应用店搜索并安装。它是管理用户脚本的瑞士军刀。开发者工具按F12或CtrlShiftI即可打开。我们主要使用Elements面板查看 DOM 结构和Console面板执行脚本。2. 环境搭建与第一个自动化脚本让我们从一个最简单的例子开始自动填充登录表单。这个例子涵盖了元素选择、事件触发等基础操作是后续所有复杂技巧的基石。2.1 创建并管理 Tampermonkey 脚本安装 Tampermonkey 后点击浏览器工具栏中的 Tampermonkey 图标选择“创建新脚本”。你会看到一个预设好模板的编辑器。一个基本的用户脚本结构如下// UserScript // name 自动填充示例 // namespace http://tampermonkey.net/ // version 1.0 // description 尝试在特定页面自动填充表单 // author You // match https://example.com/login* // grant none // /UserScript (function() { use strict; // 你的代码写在这里 console.log(脚本已加载到, window.location.href); })();关键元数据解释name脚本名称。match最重要。指定脚本在哪些网址上运行。支持通配符*。例如https://example.com/login*会匹配所有以/login开头的页面。grant声明脚本需要使用的特殊 Tampermonkey API。初始可以设为none。保存脚本CtrlS后它会在匹配的页面自动生效。你可以通过 Tampermonkey 仪表板启用/禁用或编辑脚本。2.2 第一个技巧自动填充输入框假设目标登录页面的用户名输入框id为username密码框id为password。你可以向 ChatGPT 提出这样的请求“写一段 Tampermonkey 用户脚本在页面加载完成后自动向 id 为 ‘username’ 的输入框填充值 ‘testexample.com’向 id 为 ‘password’ 的输入框填充值 ‘mypassword123’。”AI 可能会生成如下代码// UserScript // name 自动填充登录表单 // namespace http://tampermonkey.net/ // version 1.0 // description 自动填充指定登录表单 // author You // match https://your-target-site.com/login // grant none // /UserScript (function() { use strict; // 等待页面基本元素加载完成 window.addEventListener(load, function() { // 延迟执行确保动态加载的输入框也已就绪 setTimeout(function() { const usernameInput document.getElementById(username); const passwordInput document.getElementById(password); if (usernameInput) { usernameInput.value testexample.com; // 触发输入事件让某些框架能感知到值的变化 usernameInput.dispatchEvent(new Event(input, { bubbles: true })); } if (passwordInput) { passwordInput.value mypassword123; passwordInput.dispatchEvent(new Event(input, { bubbles: true })); } console.log(表单已自动填充。); }, 1000); // 延迟1秒可根据实际情况调整 }); })();代码解析与注意事项等待机制直接执行document.getElementById可能因为元素尚未加载而失败。我们使用window.addEventListener(‘load’)等待页面资源加载完毕再用setTimeout增加一个延迟以应对通过 AJAX 动态生成的表单。赋值与触发事件仅仅设置input.value可能不会触发页面的验证逻辑。使用dispatchEvent触发一个input事件可以模拟真实用户输入让依赖事件监听的框架如 Vue、React正确响应。元素选择器getElementById是最直接的方式但实际网页中元素可能没有id或id是动态生成的。这时需要更灵活的选择器如document.querySelector(‘input[name“username”]’)。常见坑点选择器失效这是自动化失败的首要原因。务必使用开发者工具的Elements面板右键点击目标元素选择 “Copy” - “Copy selector” 或 “Copy JS path” 来获取最准确的选择器。时机不对脚本执行过早。如果页面是单页应用SPAload事件可能不适用。可以尝试使用MutationObserver监听 DOM 变化或使用setInterval轮询直到元素出现。安全限制一些重要页面如银行、支付可能会检测并禁止自动化脚本的输入这是正常的安全措施。3. 实用自动化技巧详解掌握了基础之后我们来看一系列更实用的场景。每个技巧都将包含场景描述、给 AI 的提示词示例、生成的代码核心逻辑以及调试要点。3.1 技巧一自动点击“同意”或“关闭”弹窗许多网站有 Cookie 同意通知或广告弹窗。提示词示例“写一段 JavaScript 代码在页面加载后自动查找并点击文本内容包含‘同意’或‘接受’Agree, Accept的按钮如果找不到则查找 class 或 id 中含有 ‘close’ 或 ‘dismiss’ 的元素并点击。”核心逻辑代码块function clickAcceptButton() { // 策略1: 通过按钮文本查找 const buttons Array.from(document.querySelectorAll(button, a, div[rolebutton])); const targetButton buttons.find(btn { const text btn.textContent.trim().toLowerCase(); return text.includes(同意) || text.includes(接受) || text.includes(agree) || text.includes(accept) || text.includes(确定); }); if (targetButton) { targetButton.click(); console.log(已点击同意按钮:, targetButton); return true; } // 策略2: 通过常见选择器查找关闭按钮 const closeSelectors [.close, .modal-close, [aria-label*close], .btn-dismiss, .notification-close]; for (let selector of closeSelectors) { const closeEl document.querySelector(selector); if (closeEl) { closeEl.click(); console.log(已点击关闭元素选择器:, selector); return true; } } console.log(未找到可自动关闭的元素。); return false; } // 页面加载后执行 window.addEventListener(load, () setTimeout(clickAcceptButton, 2000));3.2 技巧二无限滚动页面自动抓取内容适用于需要翻页加载内容的列表页如社交媒体、商品列表。提示词示例“写一个 Tampermonkey 脚本自动滚动到页面底部触发加载更多内容并收集所有加载出来的条目比如文章标题到一个数组中直到没有新内容加载为止。假设每个条目都有一个 class 为 ‘.item-title’ 的元素包裹标题。”核心逻辑代码块// UserScript // name 无限滚动内容收集器 // namespace http://tampermonkey.net/ // version 1.0 // description 自动滚动并收集内容 // match https://example.com/feed* // grant GM_setValue // grant GM_getValue // /UserScript (function() { use strict; const collectedItems []; let lastItemCount 0; let noNewContentCount 0; const MAX_RETRY 5; // 连续5次无新内容则停止 function collectTitles() { const titles document.querySelectorAll(.item-title); titles.forEach(title { const text title.textContent.trim(); if (text !collectedItems.includes(text)) { collectedItems.push(text); } }); console.log(当前已收集 ${collectedItems.length} 条标题。); } function scrollAndLoad() { // 1. 先收集当前内容 collectTitles(); const currentCount collectedItems.length; // 2. 判断是否还有新内容 if (currentCount lastItemCount) { noNewContentCount; console.log(第 ${noNewContentCount} 次滚动未发现新内容。); } else { noNewContentCount 0; // 有新内容重置计数器 } lastItemCount currentCount; // 3. 停止条件判断 if (noNewContentCount MAX_RETRY) { console.log(已停止滚动最终收集内容:, collectedItems); // 可以将 collectedItems 存储或导出 // GM_setValue(collectedData, collectedItems); return; } // 4. 滚动到底部触发加载 window.scrollTo(0, document.body.scrollHeight); console.log(已滚动到底部等待新内容加载...); // 5. 设置下一次检查的延迟等待网络请求和DOM更新 setTimeout(scrollAndLoad, 3000); // 3秒后再次检查 } // 等待初始页面加载后开始 window.addEventListener(load, () setTimeout(scrollAndLoad, 2000)); })();3.3 技巧三批量操作列表项如全选、删除管理后台经常需要批量删除或处理列表项。提示词示例“写一段控制台代码自动勾选一个表格中所有行的复选框假设复选框的type是checkbox然后点击一个id为batch-delete-btn的批量删除按钮。”核心逻辑代码块// 在目标页面的控制台中直接执行 (function batchSelectAndDelete() { // 1. 找到所有的复选框排除表头的全选复选框如果有 const allCheckboxes document.querySelectorAll(table tbody input[typecheckbox]); if (allCheckboxes.length 0) { console.error(未找到列表中的复选框。); return; } // 2. 勾选每一个 allCheckboxes.forEach(cb { if (!cb.checked) { cb.click(); // 模拟点击以触发可能的事件 // 也可以直接设置 cb.checked true; 并触发 change 事件 // cb.checked true; // cb.dispatchEvent(new Event(change, { bubbles: true })); } }); console.log(已勾选 ${allCheckboxes.length} 个复选框。); // 3. 找到并点击删除按钮 const deleteBtn document.getElementById(batch-delete-btn); if (deleteBtn) { // 可以添加一个确认防止误操作 if (confirm(确认要批量删除 ${allCheckboxes.length} 项吗)) { deleteBtn.click(); } } else { console.error(未找到批量删除按钮。); } })();注意批量删除操作具有破坏性。务必先在测试环境验证并在生产环境中谨慎使用确认提示。最好先操作一两项进行测试。3.4 技巧四自动填写复杂表单下拉框、日期选择器对于包含下拉选择、日期组件等复杂元素的表单自动化需要更精细的操作。提示词示例“写一段 JavaScript自动选择一个select下拉框id为country中值为 ‘CN’ 的选项并触发一个原生的日期输入框type“date”id为birthday的值为 ‘2023-11-01’。”核心逻辑代码块function fillComplexForm() { // 处理下拉框 const countrySelect document.getElementById(country); if (countrySelect countrySelect.tagName SELECT) { // 方法1: 直接设置 value countrySelect.value CN; // 触发 change 事件让监听器生效 countrySelect.dispatchEvent(new Event(change, { bubbles: true })); console.log(已选择国家: CN); } // 处理原生日期输入框 const dateInput document.getElementById(birthday); if (dateInput dateInput.type date) { dateInput.value 2023-11-01; dateInput.dispatchEvent(new Event(change, { bubbles: true })); dateInput.dispatchEvent(new Event(input, { bubbles: true })); console.log(已设置日期: 2023-11-01); } // 注意对于非原生日期组件如自定义的日期选择器插件上述方法无效。 // 需要查看组件文档或手动触发其内部事件这可能非常复杂。 } // 执行 setTimeout(fillComplexForm, 1500);对于自定义UI组件如基于 div 的日期选择器这通常是自动化中最棘手的部分。通用方法是通过触发组件上的点击事件来打开选择器然后模拟点击选择日期。这需要具体分析组件的 DOM 结构。一个可能的探索路径是用开发者工具的Event Listeners面板查看原始输入框绑定了哪些事件然后尝试直接触发focus或click事件再通过选择器找到日历面板中的日期元素并点击。3.5 技巧五监控页面特定元素变化并通知你需要监控某个商品价格、库存状态或某个特定消息的出现。提示词示例“写一个 Tampermonkey 脚本每隔 10 秒检查页面中某个元素比如id为price的span的文本内容是否发生变化或者是否出现了一个包含‘缺货’文本的元素。如果发生变化或出现目标文本则在页面右上角显示一个提示框并播放提示音。”核心逻辑代码块// UserScript // name 页面变化监控器 // namespace http://tampermonkey.net/ // version 1.0 // description 监控价格变化或特定文本出现 // match https://example.com/product/* // grant GM_notification // /UserScript (function() { use strict; let lastPrice ; const TARGET_TEXT 缺货; const CHECK_INTERVAL 10000; // 10秒 function createNotificationBox(message, type info) { // 在页面创建一个小提示框 const box document.createElement(div); box.style.cssText position: fixed; top: 20px; right: 20px; padding: 15px; background: ${type alert ? #f8d7da : #d1ecf1}; border: 1px solid ${type alert ? #f5c6cb : #bee5eb}; border-radius: 5px; z-index: 99999; font-family: sans-serif; box-shadow: 0 2px 10px rgba(0,0,0,0.1); ; box.textContent [监控提示] ${message}; document.body.appendChild(box); // 5秒后自动移除 setTimeout(() box.remove(), 5000); } function checkChanges() { // 检查价格变化 const priceEl document.getElementById(price); if (priceEl) { const currentPrice priceEl.textContent.trim(); if (lastPrice currentPrice ! lastPrice) { const msg 价格发生变化从“${lastPrice}”变为“${currentPrice}”; console.log(msg); createNotificationBox(msg); // 可选播放声音 (需要用户交互后浏览器才允许自动播放) // new Audio(https://example.com/notification.mp3).play().catch(econsole.log(e)); } lastPrice currentPrice; } // 检查是否出现“缺货”文本 if (document.body.textContent.includes(TARGET_TEXT)) { // 更精确的查找查找包含该文本的元素 const walker document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT); let node; while (node walker.nextNode()) { if (node.textContent.includes(TARGET_TEXT)) { const msg 页面出现“${TARGET_TEXT}”状态; console.log(msg); createNotificationBox(msg, alert); break; // 找到一次即可 } } } } // 初始化记录初始价格 const initPriceEl document.getElementById(price); if (initPriceEl) lastPrice initPriceEl.textContent.trim(); // 启动定时监控 setInterval(checkChanges, CHECK_INTERVAL); console.log(页面变化监控已启动。); })();3.6 技巧六自动提取页面结构化数据并导出从列表页提取商品名称、价格、链接等信息并整理成 JSON 或 CSV 格式。提示词示例“写一段代码从当前页面中提取所有 class 为 ‘product-item’ 的元素并从每个元素中提取商品名称子元素.name、价格.price和详情链接a标签的href属性最后将所有数据以 JSON 格式打印在控制台并提供一个下载为 JSON 文件的按钮。”核心逻辑代码块function extractData() { const items document.querySelectorAll(.product-item); const data Array.from(items).map(item { const nameEl item.querySelector(.name); const priceEl item.querySelector(.price); const linkEl item.querySelector(a); return { name: nameEl ? nameEl.textContent.trim() : N/A, price: priceEl ? priceEl.textContent.trim() : N/A, link: linkEl ? linkEl.href : N/A, // 可以添加更多字段 }; }); return data; } function downloadJSON(data, filename data.json) { const jsonStr JSON.stringify(data, null, 2); // 美化输出 const blob new Blob([jsonStr], { type: application/json }); const url URL.createObjectURL(blob); const a document.createElement(a); a.href url; a.download filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } // 执行提取并展示 const extractedData extractData(); console.log(提取到的数据:, extractedData); console.log(共 ${extractedData.length} 条记录。); // 在页面上添加一个下载按钮可选 const btn document.createElement(button); btn.textContent 下载数据 (${extractedData.length} 条); btn.style.cssText position:fixed; top:10px; right:10px; z-index:10000; padding:10px;; btn.onclick () downloadJSON(extractedData, products_${Date.now()}.json); document.body.appendChild(btn);3.7 技巧七模拟用户操作序列登录-导航-操作将多个独立操作串联起来形成一个完整的工作流。提示词示例“写一个 Tampermonkey 脚本在特定网站执行以下序列1. 访问登录页并自动填写凭证假设有记住登录状态。2. 登录后等待跳转完成然后导航到‘我的订单’页面。3. 在订单列表页自动点击第一个订单的‘详情’按钮。”核心逻辑代码块概念性更强严重依赖具体网站结构// UserScript // name 自动化工作流示例 // namespace http://tampermonkey.net/ // version 1.0 // description 自动登录并执行后续操作 // match https://example.com/* // grant none // /UserScript (function() { use strict; const STATE { IDLE: idle, LOGGING_IN: logging_in, NAVIGATING: navigating, OPERATING: operating, DONE: done }; let currentState STATE.IDLE; const config { username: your_username, password: your_password, targetPage: /my/orders }; function attemptLogin() { if (window.location.pathname /login) { const userInput document.querySelector(input[typetext], input[typeemail]); const passInput document.querySelector(input[typepassword]); const submitBtn document.querySelector(button[typesubmit], input[typesubmit]); if (userInput passInput) { userInput.value config.username; passInput.value config.password; userInput.dispatchEvent(new Event(input, { bubbles: true })); passInput.dispatchEvent(new Event(input, { bubbles: true })); setTimeout(() { if (submitBtn) submitBtn.click(); console.log(已提交登录信息。); currentState STATE.NAVIGATING; }, 500); } } } function navigateToOrders() { // 假设登录后首页有一个链接可以跳转到目标页 if (window.location.pathname / || window.location.pathname /dashboard) { const orderLink document.querySelector(a[href*${config.targetPage}]); if (orderLink) { orderLink.click(); console.log(正在跳转到订单页面...); currentState STATE.OPERATING; } } } function operateOnOrders() { if (window.location.pathname.includes(config.targetPage)) { // 等待订单列表加载 const firstDetailBtn document.querySelector(.order-list .detail-btn:first-child); if (firstDetailBtn) { firstDetailBtn.click(); console.log(已点击第一个订单的详情按钮。); currentState STATE.DONE; } } } // 主控制循环使用轮询检查状态和页面变化 function mainController() { switch (currentState) { case STATE.IDLE: attemptLogin(); break; case STATE.NAVIGATING: navigateToOrders(); break; case STATE.OPERATING: operateOnOrders(); break; case STATE.DONE: console.log(自动化工作流执行完毕。); return; // 停止循环 } // 每2秒检查一次状态 setTimeout(mainController, 2000); } // 页面加载后启动控制器 window.addEventListener(load, () setTimeout(mainController, 3000)); })();重要提醒此类多步骤自动化脚本极其脆弱因为严重依赖页面的特定 DOM 结构和流程。任何前端改动都可能导致脚本失效。它更适合内部系统或变化不频繁的页面且需要定期维护。3.8 技巧八修改页面样式或屏蔽特定元素临时修改页面 CSS 以提升阅读体验或屏蔽烦人的元素。提示词示例“写一段脚本自动隐藏页面上的所有广告元素假设广告都有class包含 ‘ad’ 或 ‘advertisement’并将整个页面的字体设置为 16px行高设置为 1.6。”核心逻辑代码块// 在控制台执行或作为 Tampermonkey 脚本 (function enhancePage() { use strict; // 1. 隐藏广告 const adSelectors [.ad, .advertisement, [id*ad], [class*banner]]; adSelectors.forEach(selector { const ads document.querySelectorAll(selector); ads.forEach(ad { ad.style.display none; console.log(已隐藏广告元素: ${selector}); }); }); // 2. 修改全局字体样式 const style document.createElement(style); style.textContent body, p, div, span, li { font-size: 16px !important; line-height: 1.6 !important; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif !important; } ; document.head.appendChild(style); console.log(已应用增强阅读样式。); })();3.9 技巧九拦截与修改网络请求用于调试、修改 API 请求参数或响应或者屏蔽某些请求。这需要更高级的浏览器插件 API如GM_xmlhttpRequest或fetch重写且受同源策略限制。Tampermonkey 的grant GM_xmlhttpRequest允许跨域请求但直接拦截和修改请求比较困难。更常见的做法是重写全局的fetch和XMLHttpRequest来监听请求。提示词示例高级“写一段 Tampermonkey 脚本监听所有从当前页面发出的、指向 ‘/api/data’ 的fetch请求并在控制台打印出请求的 URL 和参数。”核心逻辑代码块// UserScript // name 网络请求监听器 // namespace http://tampermonkey.net/ // version 1.0 // description 监听特定API请求 // match https://example.com/* // grant none // /UserScript (function() { use strict; // 保存原始的 fetch 函数 const originalFetch window.fetch; // 重写 fetch window.fetch function(...args) { const requestUrl args[0]; // 第一个参数可能是 Request 对象或 URL 字符串 const url (typeof requestUrl string) ? requestUrl : requestUrl.url; // 只监听特定 API if (url.includes(/api/data)) { console.group(监听到 /api/data 请求); console.log(请求 URL:, url); console.log(请求参数:, args[1]); // 第二个参数是配置对象 console.groupEnd(); // 你可以在这里修改请求参数 args[1] // 例如args[1].headers[X-Custom-Header] MyValue; } // 继续执行原始 fetch return originalFetch.apply(this, args); }; console.log(Fetch 监听器已注入。); })();警告重写核心 API如fetch、XMLHttpRequest可能影响页面正常运行且可能被网站的反爬虫机制检测到。仅用于学习和调试目的。3.10 技巧十与本地应用或剪贴板交互将网页数据复制到剪贴板或读取剪贴板内容填充到网页。提示词示例“写一段脚本在页面上添加一个按钮点击后可以将指定元素id为result的文本内容复制到用户的剪贴板。”核心逻辑代码块function addCopyButton() { const targetEl document.getElementById(result); if (!targetEl) { console.error(未找到 id 为 “result” 的元素。); return; } const btn document.createElement(button); btn.textContent 复制结果; btn.style.cssText margin-left: 10px; padding: 5px 10px;; btn.onclick async () { try { // 使用现代 Clipboard API await navigator.clipboard.writeText(targetEl.textContent.trim()); const originalText btn.textContent; btn.textContent 已复制; btn.style.backgroundColor #d4edda; setTimeout(() { btn.textContent originalText; btn.style.backgroundColor ; }, 1500); } catch (err) { console.error(复制失败:, err); // 降级方案使用已弃用的 document.execCommand const textArea document.createElement(textarea); textArea.value targetEl.textContent.trim(); document.body.appendChild(textArea); textArea.select(); const success document.execCommand(copy); document.body.removeChild(textArea); if (success) { alert(内容已复制到剪贴板); } else { alert(复制失败请手动选择文本复制。); } } }; // 将按钮插入到目标元素后面 targetEl.parentNode.insertBefore(btn, targetEl.nextSibling); } // 等待目标元素加载后执行 if (document.getElementById(result)) { addCopyButton(); } else { // 如果元素是动态加载的使用 MutationObserver const observer new MutationObserver((mutations, obs) { if (document.getElementById(result)) { addCopyButton(); obs.disconnect(); // 找到后停止观察 } }); observer.observe(document.body, { childList: true, subtree: true }); }4. 调试、排错与最佳实践自动化脚本的编写只是第一步让它在复杂多变的真实网页环境中稳定运行才是挑战。4.1 通用调试流程与常见问题排查当脚本不工作时请按以下顺序排查问题现象可能原因检查方式处理建议脚本未执行Tampermonkey 未启用match模式不匹配脚本有语法错误。1. 检查 Tampermonkey 仪表板脚本是否启用。2. 检查当前 URL 是否匹配match。3. 打开浏览器控制台 (F12) 查看是否有 JS 错误。修正match模式检查并修复脚本语法确保 Tampermonkey 图标显示脚本已运行。找不到元素元素选择器错误页面结构已更新元素是动态加载的脚本执行过早。1. 在控制台手动执行document.querySelector(‘你的选择器’)测试。2. 在 Elements 面板确认元素是否存在及其完整结构。3. 查看 Network 面板确认是否为 AJAX 加载。使用更稳健的选择器如>点击/输入无效元素被遮挡元素是div模拟的按钮需要触发特定事件页面有事件监听器阻止默认行为。1. 检查元素样式pointer-events和z-index。2. 尝试element.click()和element.dispatchEvent(new MouseEvent(‘click’))。3. 在 Event Listeners 面板查看元素绑定的事件。对于自定义组件尝试触发mousedown、mouseup事件组合对于表单触发input和change事件。跨域问题脚本尝试访问不同源的资源如图片、API。控制台会显示CORS错误。Tampermonkey 脚本可使用grant GM_xmlhttpRequest发起跨域请求。普通脚本无法绕过 CORS 限制。被网站检测网站有反自动化机制检测到非人类操作模式。操作后页面无反应、弹出验证码、或账号被临时限制。增加随机延迟模拟人类操作避免过高频率的请求考虑使用更专业的自动化框架如 Puppeteer配合 Stealth 插件。4.2 编写健壮脚本的最佳实践使用稳健的选择器优先使用id、name或明确的>function waitForElement(selector, timeout 10000) { return new Promise((resolve, reject) { if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } const observer new MutationObserver(() { if (document.querySelector(selector)) { observer.disconnect(); resolve(document.querySelector(selector)); } }); observer.observe(document.body, { childList: true, subtree: true }); setTimeout(() { observer.disconnect(); reject(new Error(等待元素超时: ${selector})); }, timeout); }); } // 使用 waitForElement(‘.my-button’).then(btn btn.click());模拟人类操作在连续操作间添加随机延迟避免被识别为机器人。function humanDelay(min 500, max 2000) { return new Promise(resolve setTimeout(resolve, Math.random() * (max - min) min)); } // 在操作间使用 await humanDelay();错误处理与日志使用try...catch包裹可能失败的操作并用console.log或GM_log输出关键步骤信息便于调试。配置外置化将需要频繁修改的变量如选择器、URL、凭证放在脚本开头的配置对象中而不是硬编码在逻辑里。尊重网站规则仅对你有权操作的页面或数据使用自动化。避免对他人网站进行高频访问以免对其服务器造成压力或触发风控。4.3 从 Tampermonkey 脚本到浏览器插件当你的自动化需求变得复杂需要与多个标签页交互、拥有自己的弹出界面或需要更强大的后台能力时可以考虑开发一个完整的浏览器插件。Chrome 扩展主要包含manifest.json配置文件。background.js后台脚本生命周期长。content.js注入页面的内容脚本类似 Tampermonkey 脚本。popup.html/popup.js点击插件图标弹出的界面。开发插件可以获得更完整的浏览器 API 权限但复杂度也显著增加。对于大多数自动化任务Tampermonkey 脚本已经足够强大和便捷。通过结合 AI 的代码生成能力和你对具体网页结构的理解浏览器自动化可以极大地解放生产力。关键在于将模糊的需求转化为精确的、可执行的指令并掌握调试和排错的方法。从简单的表单填充开始逐步尝试更复杂的监控、数据提取和工作流串联你会逐渐构建起一套属于自己的网页自动化工具箱。