暴力猴用户脚本从入门到精通:安装、编写、调试与自动化实战
2026/9/24 19:14:49 网站建设 项目流程

1. 暴力猴到底是个什么东西

第一次听到“暴力猴”这个名字,很多人会以为是什么游戏外挂或者黑客工具。其实它就是一个浏览器扩展,核心功能只有一件事:让你在别人的网页上运行自己写的或者别人写好的JavaScript脚本。你可以把它理解成一个“网页改造器”——网页原本长什么样、有什么功能,是网站开发者决定的;装上暴力猴之后,你就有了一支笔,可以在网页加载完成后往上面涂改、添加、删除任何东西。

我用了大概三年多的暴力猴,从最开始只会装现成脚本,到后来自己写脚本解决工作中的重复操作,再到现在团队里十几个人的浏览器标配。这篇文章我会把暴力猴的完整使用链路讲清楚:它解决什么问题、脚本从哪来、怎么装、怎么写、怎么调试、怎么管理、有哪些坑。不管你是完全没接触过的新手,还是已经装过几个脚本但想深入的人,应该都能找到有用的东西。

暴力猴本身不提供任何脚本,它只是一个运行环境。真正干活的是“用户脚本”——一段段JavaScript代码,通过暴力猴注入到指定网页中执行。这些脚本能做的事情包括但不限于:去掉网页广告、解锁复制限制、批量下载文件、自动填写表单、修改页面样式、抓取数据导出表格、给网页添加快捷键、跳过视频片头等等。只要你能想到的网页操作,基本都能通过用户脚本实现。

适合读这篇文章的人大概有三类:一是每天要在网页上做大量重复操作的人,比如运营、数据分析、行政;二是对前端有一点了解、想通过脚本提升效率的开发者;三是纯粹对浏览器自动化感兴趣、想找个切入点上手的人。下面我按实际使用的流程来展开,每一步都会说清楚为什么这么做、怎么做、做了之后会怎样。

2. 用户脚本的获取渠道与筛选方法

2.1 脚本来源的几种类型

用户脚本的获取渠道主要有这么几个:第一类是脚本托管平台,最知名的是Greasy Fork,上面有海量的用户脚本,按功能分类,支持搜索和评分;第二类是GitHub,很多脚本作者会把源码放在仓库里,适合想看代码或者自己改的人;第三类是论坛和社区,比如一些垂直领域的讨论区,会有人分享针对特定网站的脚本;第四类就是自己写,这个后面会详细讲。

Greasy Fork是我最常用的来源。它的脚本页面会显示脚本名称、作者、适用网站、安装量、评分、最近更新时间、代码行数等信息。这些信息非常关键,因为用户脚本有一个天然的风险:它运行在你的浏览器里,能读取和修改你访问的网页内容。如果一个脚本作者写了恶意代码,理论上可以窃取你在该网站上的数据。所以筛选脚本的时候,安装量和评分是第一个参考维度,最近更新时间是第二个——如果一个脚本两年没更新了,大概率已经失效了。

2.2 判断一个脚本是否值得安装

我总结了一个简单的判断流程,每次装新脚本之前都会过一遍:

  • 看适用网站:脚本页面上会写明它匹配哪些网址。如果匹配范围是*://*/*(所有网站),就要多留个心眼,除非是那种通用工具类脚本(比如网页暗色模式),否则一个针对特定网站的脚本不应该匹配所有网址。
  • 看代码行数和权限:Greasy Fork上可以直接看代码。如果脚本很短(几十行),基本能快速扫一眼它在干什么。如果很长(几千行),至少看看开头有没有GM_xmlhttpRequest这种跨域请求的权限申请,以及有没有往陌生服务器发送数据的操作。
  • 看更新时间和反馈:最近更新在半年内的比较可靠。评论区如果有大量“失效了”“报错了”的反馈,说明脚本可能已经跟不上网站改版了。
  • 看作者的其他脚本:如果同一个作者发布了很多脚本,而且都有不错的安装量,可信度会高一些。

注意:不要安装来源不明的脚本。尤其是那种通过私聊、群聊发过来的.user.js文件,没有经过平台审核,风险很高。尽量从Greasy Fork或GitHub这类可以查看源码和社区反馈的地方获取。

2.3 脚本安装的实际操作

安装脚本的流程很简单,但有几个细节值得说清楚。当你在Greasy Fork上点击“安装此脚本”按钮时,浏览器会跳转到一个.user.js文件地址,暴力猴会拦截这个请求并弹出安装确认页面。页面上会显示脚本的名称、版本、作者、匹配的网址范围、以及它申请的特殊权限(比如跨域请求、访问本地存储等)。

这里有一个很多人忽略的点:安装确认页面上的“匹配网址”是可以手动修改的。比如一个脚本原本只匹配https://example.com/*,你可以改成https://example.com/specific-page/*来缩小生效范围,避免在不必要的页面上运行。反过来也可以扩大范围,但一般不建议这么做。

安装完成后,脚本会出现在暴力猴的管理面板里。面板里可以看到所有已安装的脚本,每个脚本可以单独开启或关闭、编辑代码、检查更新、删除。我习惯把脚本按用途分组,比如“工作效率”“网页净化”“数据抓取”三类,虽然暴力猴本身没有分组功能,但可以通过命名前缀来实现,比如[效率] 自动填写周报

3. 暴力猴的核心功能与配置详解

3.1 管理面板的各个模块

暴力猴的管理面板是日常使用中最常打交道的地方。面板顶部有几个标签页:已安装脚本、实用工具、设置、关于。已安装脚本页面是主界面,列出了所有脚本,每个脚本右侧有开关按钮和操作菜单。操作菜单里包含编辑、更新、导出、删除等选项。

“实用工具”标签页里有两个很实用的功能:一个是“检查脚本更新”,可以一键检查所有已安装脚本是否有新版本;另一个是“导入/导出”,可以把所有脚本打包成一个压缩文件,方便换电脑或者重装浏览器时迁移。我每次换工作环境,第一件事就是导出脚本包,到新环境导入,省去一个个重装的麻烦。

设置页面里值得关注的选项包括:脚本更新频率(默认每周检查一次,可以改成每天)、编辑器主题(写脚本时用深色还是浅色)、以及“配置模式”的高级选项。配置模式里可以设置脚本运行的默认行为,比如是否允许脚本在iframe中运行、是否启用同步功能等。

3.2 脚本的匹配规则与运行时机

用户脚本的元数据块(就是脚本开头那段注释)里,有几个关键指令决定了脚本在什么页面、什么时机运行:

  • @match:指定脚本生效的网址模式。支持通配符,比如*://*.example.com/*匹配example.com的所有子域名和路径。
  • @include@exclude:和@match类似,但语法更灵活,可以用正则表达式。
  • @run-at:决定脚本在页面加载的哪个阶段执行。可选值有document-start(页面开始加载时)、document-end(DOM加载完成时)、document-idle(页面完全加载后)。默认是document-end
  • @grant:声明脚本需要使用的特殊API权限。比如GM_setValueGM_getValue用于跨页面存储数据,GM_xmlhttpRequest用于发起跨域请求。

@run-at的选择很关键。如果你要修改页面上的某个元素,但那个元素是异步加载的,用document-end可能拿不到,这时候要么用document-idle,要么在脚本里自己写一个轮询等待元素出现。我一般先用document-end,如果发现元素找不到,再改成document-idle或者加一个MutationObserver来监听DOM变化。

3.3 数据存储与跨域请求

暴力猴提供了几个专用的API,让脚本可以做一些普通网页脚本做不到的事情。最常用的两个是存储和跨域请求。

存储方面,GM_setValue(key, value)GM_getValue(key, defaultValue)可以在浏览器的本地存储里读写数据,这些数据在脚本的所有匹配页面上都能访问。比如你写了一个脚本记录某个网站上的操作历史,就可以用这两个API来存。数据是持久化的,关掉浏览器再打开还在。

跨域请求方面,GM_xmlhttpRequest允许脚本向任意服务器发起HTTP请求,不受同源策略限制。这个功能非常强大,比如你可以写一个脚本,在网页上添加一个按钮,点击后把当前页面的数据发送到自己的服务器,或者从别的API拉取数据展示在页面上。但这也意味着脚本有能力把你的数据发到外部,所以安装脚本时看到这个权限要格外注意。

提示:如果你自己写脚本,GM_xmlhttpRequest需要先在元数据块里声明@grant GM_xmlhttpRequest,否则调用会失败。另外,这个API的用法和普通的fetchXMLHttpRequest略有不同,它是回调式的,不是Promise式的,写的时候要注意。

4. 从零写一个用户脚本的完整流程

4.1 确定需求与拆解步骤

写脚本的第一步不是打开编辑器,而是把需求想清楚。我一般会问自己三个问题:这个操作我每天要做多少次?每次花多长时间?能不能用代码自动化?

举个例子,我之前每天要在公司内部系统里导出前一天的订单数据,流程是:打开系统→登录→进入订单页面→选择日期→点击导出→等待文件下载→把文件移动到指定文件夹。整个流程大概两分钟,每天做一次。虽然时间不长,但很枯燥,而且容易忘。于是我决定写一个脚本来自动化这个流程。

拆解下来就是几个步骤:页面加载后自动点击“订单”菜单→在日期选择器里填入昨天的日期→点击“导出”按钮→监听下载事件。每一步都需要在页面上找到对应的元素,然后模拟点击或输入。

4.2 编写脚本的基本结构

一个用户脚本的基本结构包括元数据块和代码主体。元数据块用注释的形式写在最上面,告诉暴力猴这个脚本叫什么、匹配什么网址、需要什么权限。代码主体就是普通的JavaScript,可以用浏览器支持的任何API。

下面是一个最简单的脚本模板,功能是在页面加载完成后弹出一个提示:

// ==UserScript== // @name 我的第一个脚本 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 在页面加载后弹出提示 // @author 我 // @match https://example.com/* // @grant none // ==/UserScript== (function() { 'use strict'; alert('页面加载完成!'); })();

这个模板里,@match指定了脚本只在https://example.com下运行,@grant none表示不需要特殊权限。代码主体用了一个立即执行函数把逻辑包起来,避免变量污染全局作用域。'use strict'开启严格模式,能帮你避免一些常见的编码错误。

4.3 元素定位与事件模拟

写脚本最核心的技能是找到页面上的元素并操作它。浏览器开发者工具(F12)是必备的。你可以用“选择元素”工具点击页面上的任意元素,然后在Elements面板里看到它的HTML结构。找到元素的id、class、或者独特的属性,就可以用document.querySelectordocument.querySelectorAll来定位。

比如要点击一个按钮,按钮的HTML是<button id="export-btn" class="btn primary">导出</button>,那么代码就是:

const btn = document.querySelector('#export-btn'); if (btn) { btn.click(); }

这里加了一个if (btn)的判断,是因为页面元素可能还没加载出来。如果脚本在document-end阶段运行,而按钮是异步加载的,querySelector会返回null,直接调用.click()就会报错。所以每次操作元素之前都要判空。

对于输入框,不能直接改value属性,因为很多框架(比如React、Vue)会监听input事件来更新内部状态。正确的做法是模拟用户输入:

const input = document.querySelector('#date-input'); if (input) { input.value = '2024-01-01'; input.dispatchEvent(new Event('input', { bubbles: true })); input.dispatchEvent(new Event('change', { bubbles: true })); }

bubbles: true让事件冒泡到父元素,这样框架的监听器才能捕获到。

4.4 等待异步元素出现的几种方案

异步加载是写用户脚本时最常见的难题。页面上很多元素不是一开始就有的,而是通过AJAX请求或者前端框架动态渲染出来的。这时候有几种应对方案:

第一种是轮询。写一个setInterval,每隔几百毫秒检查一次元素是否存在,存在了就执行操作并清除定时器。简单粗暴,但不够优雅。

const timer = setInterval(() => { const el = document.querySelector('#target'); if (el) { clearInterval(timer); // 执行操作 } }, 500);

第二种是MutationObserver。监听DOM变化,当目标元素被添加到页面时触发回调。这种方式更精确,不会做无用的轮询。

const observer = new MutationObserver((mutations, obs) => { const el = document.querySelector('#target'); if (el) { obs.disconnect(); // 执行操作 } }); observer.observe(document.body, { childList: true, subtree: true });

第三种是等待某个特定请求完成。如果元素是在某个AJAX请求返回后才出现的,可以拦截XMLHttpRequestfetch,在请求完成后执行操作。这种方式最精确,但实现起来也最复杂。

我一般优先用MutationObserver,因为它兼顾了精确性和简洁性。只有在目标元素的位置不固定、或者需要等待多个元素时,才会用轮询。

5. 脚本调试与问题排查实战

5.1 调试工具与断点设置

暴力猴的脚本编辑器自带一个简单的代码编辑界面,但真正调试还是要在浏览器的开发者工具里。打开F12,切换到Sources面板,在左侧的文件树里找到“Tampermonkey”或“Violentmonkey”分组,里面会列出所有正在运行的脚本。点击脚本文件,就可以像调试普通JavaScript一样设置断点、查看变量、单步执行。

我常用的调试流程是:先在脚本的关键位置加console.log输出变量值,看看执行到哪一步出了问题。如果逻辑比较复杂,就在Sources面板里设断点,一步步跟。断点调试的好处是可以看到调用栈和当前作用域里的所有变量,比console.log高效得多。

还有一个技巧是在脚本里加debugger;语句。当开发者工具打开时,执行到这一行会自动暂停,相当于一个临时的断点。调试完成后记得删掉,否则每次都会暂停。

5.2 常见报错与修复方法

写脚本过程中遇到的报错大概有这么几类:

  • Cannot read property 'click' of null:说明querySelector没找到元素。原因可能是选择器写错了、元素还没加载出来、或者元素在iframe里面。检查选择器是否正确,确认元素是否在iframe中(如果在,需要先获取iframe的contentDocument)。
  • GM_xmlhttpRequest is not defined:忘了在元数据块里声明@grant GM_xmlhttpRequest。加上重新安装即可。
  • 脚本不生效:检查@match是否匹配当前网址。可以在暴力猴面板里看脚本的开关是否打开,以及当前页面是否在脚本的匹配范围内。有时候网址带了参数或者用了不同的域名,@match没覆盖到。
  • 脚本执行了但没效果:可能是操作的元素不对,或者事件没有正确触发。用开发者工具检查元素的实际状态,确认操作是否生效。

5.3 脚本冲突与性能问题

当你装了很多脚本时,可能会出现脚本之间互相干扰的情况。比如两个脚本都修改了同一个元素的样式,或者都监听了同一个事件。排查方法是逐个禁用脚本,看问题是否消失,然后定位到具体的冲突脚本。

性能问题也值得注意。如果一个脚本在document-start阶段运行,并且做了大量DOM操作,会明显拖慢页面加载速度。我一般会把不必要的操作延迟到document-idle,或者用requestIdleCallback在浏览器空闲时执行。另外,MutationObserver如果监听范围太大(比如监听整个documentsubtree),也会影响性能,尽量缩小监听范围。

提示:定期清理不再使用的脚本。每个脚本都会占用一点内存和CPU,装了几十个脚本之后,浏览器会明显变慢。我一般每个月检查一次,把失效的、不再需要的脚本删掉。

6. 浏览器自动化的进阶玩法

6.1 批量操作与循环处理

用户脚本最强大的地方在于可以批量处理重复操作。比如你有一个列表页面,每行都有一个“审核”按钮,你需要逐个点击。手动点几十次很累,用脚本就可以自动遍历所有行,依次点击。

const buttons = document.querySelectorAll('.audit-btn'); buttons.forEach((btn, index) => { setTimeout(() => { btn.click(); }, index * 1000); // 每隔1秒点一个,避免请求过快 });

这里用setTimeout做了延迟,是因为很多系统对请求频率有限制,点太快会被拦截或者导致数据错乱。延迟的时间根据实际情况调整,一般500毫秒到2秒之间。

6.2 数据抓取与导出

另一个常见需求是把网页上的数据抓下来,整理成表格。比如商品列表页有几十个商品,每个商品有名称、价格、销量,你想导出成Excel。用脚本可以自动遍历页面,提取数据,然后生成CSV文件下载。

const rows = document.querySelectorAll('.product-row'); const data = []; rows.forEach(row => { const name = row.querySelector('.name')?.textContent.trim(); const price = row.querySelector('.price')?.textContent.trim(); const sales = row.querySelector('.sales')?.textContent.trim(); data.push([name, price, sales]); }); // 生成CSV const csv = data.map(row => row.join(',')).join('\n'); const blob = new Blob(['\ufeff' + csv], { type: 'text/csv;charset=utf-8' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'data.csv'; a.click(); URL.revokeObjectURL(url);

注意\ufeff是BOM头,加上之后Excel打开CSV不会乱码。?.是可选链操作符,如果元素不存在会返回undefined而不是报错。

6.3 页面样式改造与广告净化

除了功能自动化,用户脚本还可以用来改造页面样式。比如把某个网站的背景改成暗色、把字体调大、隐藏侧边栏广告等。这类脚本的原理就是往页面里注入CSS。

const style = document.createElement('style'); style.textContent = ` .ad-banner { display: none !important; } body { background: #1a1a1a; color: #e0e0e0; } .content { max-width: 900px; margin: 0 auto; } `; document.head.appendChild(style);

!important用来覆盖原有的样式。这种脚本写起来简单,效果立竿见影,适合对CSS有基本了解的人。

6.4 快捷键与自定义交互

给网页添加快捷键也是常见需求。比如按Ctrl+S保存当前页面数据、按Alt+1切换到某个标签页等。实现方式是监听keydown事件:

document.addEventListener('keydown', (e) => { if (e.ctrlKey && e.key === 's') { e.preventDefault(); // 阻止浏览器默认的保存行为 // 执行自定义保存逻辑 saveData(); } });

e.preventDefault()用来阻止浏览器的默认行为,比如Ctrl+S默认是保存网页,Ctrl+P默认是打印。如果不阻止,你的自定义逻辑和默认行为会同时触发。

7. 脚本管理与长期维护经验

7.1 版本管理与备份策略

用户脚本虽然不像正式项目那样需要严格的版本管理,但养成好习惯能省很多事。我每个脚本的元数据块里都会写清楚@version@description,每次修改后递增版本号。这样在暴力猴面板里能一眼看出哪个脚本最近更新过。

备份方面,我每周会把所有脚本导出一次,存到云盘里。导出的文件是一个压缩包,里面包含所有脚本的.user.js文件和暴力猴的配置文件。换电脑或者重装系统时,导入这个压缩包就能恢复所有脚本和设置。

如果脚本比较复杂,我还会在GitHub上建一个私有仓库,把脚本源码放进去。这样不仅有版本历史,还能在不同设备之间同步。暴力猴本身也支持通过云存储同步脚本,但需要配置,我嫌麻烦就没用,手动导出导入也够用了。

7.2 脚本失效的应对流程

网站改版是用户脚本最大的敌人。一个脚本可能今天还好好的,明天网站一更新就失效了。遇到这种情况,我的处理流程是:

  1. 先确认是不是脚本的问题。禁用脚本,手动操作一遍,看网站本身是否正常。
  2. 打开开发者工具,检查脚本操作的元素是否还存在。如果元素的id或class变了,更新选择器即可。
  3. 如果页面结构变化很大,可能需要重写部分逻辑。
  4. 如果脚本是从Greasy Fork装的,去看看评论区有没有人反馈同样的问题,或者作者有没有发布更新。
  5. 如果作者长期不更新,可以考虑自己接手维护,或者找替代脚本。

我一般会在脚本里加一些容错逻辑,比如元素找不到时输出一条警告日志,而不是直接报错。这样即使网站小改版,脚本也不会完全崩溃,只是部分功能失效,方便定位问题。

7.3 安全使用的基本原则

最后再强调一下安全问题。用户脚本运行在你的浏览器里,拥有和你相同的权限。一个恶意脚本可以读取你在任何匹配网站上的数据,包括登录凭证、聊天记录、支付信息等。所以:

  • 只从可信来源安装脚本,优先选择开源、有社区反馈的脚本。
  • 安装前看一眼代码,特别是@match的范围和@grant的权限。
  • 定期检查已安装的脚本,删除不再使用的。
  • 不要在涉及敏感信息的网站上随意安装脚本。
  • 如果自己写脚本,不要把敏感数据硬编码在代码里,也不要把数据发送到不可信的服务器。

注意:暴力猴本身是一个工具,工具没有好坏,关键在于怎么用。用它来提升效率、简化操作,它就是好帮手;用来做违规的事情,后果自负。

8. 我个人的一些实操体会

写了这么多,最后分享几个我在实际使用中总结的小经验。第一个是关于脚本的命名,我习惯用[场景] 功能描述的格式,比如[内部系统] 自动导出订单[论坛] 屏蔽特定用户,这样在面板里一眼就能找到想要的脚本。第二个是关于代码复用,很多脚本里都有“等待元素出现”“模拟输入”这类通用逻辑,我会把这些抽成一个公共函数库,每个脚本通过@require引入,避免重复写。

第三个是关于调试效率,我发现在脚本里加一个简单的日志面板比console.log更直观。就是在页面角落创建一个固定定位的div,把日志输出到里面,这样不用开开发者工具就能看到脚本的运行状态。代码大概是这样:

const logPanel = document.createElement('div'); logPanel.style.cssText = 'position:fixed;bottom:10px;right:10px;background:rgba(0,0,0,0.8);color:#0f0;padding:8px;font-size:12px;max-height:200px;overflow:auto;z-index:99999;'; document.body.appendChild(logPanel); function log(msg) { const line = document.createElement('div'); line.textContent = `[${new Date().toLocaleTimeString()}] ${msg}`; logPanel.appendChild(line); logPanel.scrollTop = logPanel.scrollHeight; }

这个面板在调试复杂脚本时特别有用,能实时看到每一步的执行情况。调试完成后把相关代码删掉或者注释掉就行。

第四个体会是关于心态。写用户脚本这件事,入门很容易,写一个能用的脚本可能只需要十几行代码。但要做到稳定、健壮、能长期使用,需要不断迭代。网站会改版,需求会变化,脚本也要跟着更新。把它当成一个持续维护的小项目,而不是一次性的工具,这样才能真正发挥它的价值。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询