术→技巧, 研发

篡改猴脚本编写指南

钱魏Way · · 7 次浏览

在当今的网页浏览体验中,我们常常会遇到各种不便,例如恼人的广告、不友好的界面设计,或是希望自动化某些重复操作。Tampermonkey(俗称油猴或篡改猴)作为一款强大的浏览器扩展,允许用户通过编写JavaScript脚本,深度定制和增强任何网页的功能与外观。

认识篡改猴:你的网页“魔法棒”

篡改猴本质上是一个用户脚本管理器。它允许你在特定的网页上,自动运行你自己编写的JavaScript代码。这意味着你可以:

  • 修改页面内容与布局:移除广告、美化UI、重新排版。
  • 增强网页功能:自动填充表单、添加快捷操作按钮、实现VIP视频解析等。
  • 自动化交互:自动执行点击、滚动、数据抓取等任务。
  • 突破限制:解除网页复制粘贴限制、实现跨域请求。

其核心工作原理是:在目标网页加载完成后,篡改猴将你的脚本代码注入到页面中并执行,从而实现对原网页的“篡改”。

准备工作:安装与创建第一个脚本

安装篡改猴扩展

首先,你需要在浏览器中安装Tampermonkey扩展。主流浏览器(Chrome、Edge、Firefox等)的扩展商店中均可搜索“Tampermonkey”并安装。安装成功后,浏览器工具栏会出现一个猴子图标。

创建并理解脚本结构

点击猴子图标,选择“管理面板”或“创建新脚本”,即可进入脚本编辑器。你会看到一个预设好框架的新脚本:

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      2024-08-08
// @description  try to take over the world!
// @author       You
// @match        https://www.example.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=example.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    // Your code here...
})();

这个结构分为两个关键部分:

  • 元数据块 (// ==UserScript== 内):以注释形式定义脚本的配置信息,是脚本的“身份证”和“说明书”。
  • 执行函数 ((function() { … })();):包裹在立即执行函数表达式(IIFE)中的主逻辑代码,‘use strict’; 表示启用严格模式,避免常见错误。

详解元数据:脚本的配置核心

元数据通过 @ 开头的指令进行配置,是控制脚本何时、何地以及如何运行的关键。

  • @name:脚本的名称,显示在管理列表中。
  • @namespace:与 @name 共同作为脚本的唯一标识符。
  • @version:版本号,用于更新管理。
  • @description:脚本功能的简要描述。
  • @author:作者信息。
  • @match / @include:最为重要。指定脚本生效的URL模式,支持通配符 *。例如:
    • // @match https://www.baidu.com/* 匹配百度所有页面。
    • // @match https://*.taobao.com/* 匹配所有淘宝子域名下的页面。
  • @exclude:排除某些匹配的URL,即使它们符合 @match 规则。
  • @grant:声明脚本需要使用的篡改猴特殊API权限。例如 GM_setValue、GM_xmlhttpRequest 等。如果不需要,则设为 none。
  • @run-at:控制脚本注入的时机。常用值有 document-end(页面加载完成后,默认)、document-start(页面开始加载时)等。
  • @require:在脚本运行前,引入外部JavaScript库,如jQuery。

实战案例:编写你的功能脚本

理解了基础后,我们通过几个由浅入深的实例来掌握脚本编写。

案例1:网页UI美化与元素移除

许多网站侧边栏或顶部有干扰性的广告或推广面板。我们可以通过DOM操作将其移除。

  • 目标:移除某技术博客文章页的侧边悬浮面板。
  • 思路:打开目标网页,使用浏览器开发者工具(F12)检查元素,找到该面板的CSS选择器(如类名 .article-suspended-panel),然后在脚本中将其删除。
// ==UserScript==
// @name         移除文章侧边栏
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  移除特定博客文章的侧边悬浮面板
// @match        https://juejin.cn/post/7383374760577826835
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    // 等待页面主体内容加载
    window.addEventListener('load', function() {
        // 通过CSS选择器查找目标元素
        const panel = document.querySelector('.article-suspended-panel');
        if (panel) {
            panel.remove();
            console.log('侧边悬浮面板已移除');
        }
    });
})();

案例2:动态添加页面功能

我们可以为网页添加原本没有的交互元素。

  • 目标:在B站视频播放器速度调节菜单中,增加更高的倍速选项(如3.0x, 4.0x)。
  • 思路:定位到速度调节菜单的DOM元素,循环创建新的倍速选项列表项(<li>),并绑定点击事件来修改视频(<video>)的播放速率。
// ==UserScript==
// @name         B站视频超速播放
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  为B站视频添加更高倍速选项
// @match        https://www.bilibili.com/video/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    // 使用定时器等待动态生成的菜单元素出现
    const timer = setInterval(() => {
        const menu = document.querySelector('.bpx-player-ctrl-playbackrate-menu');
        if (menu) {
            clearInterval(timer);
            // 添加2.5倍到5.5倍的选项
            for (let rate = 2.5; rate <= 5.5; rate += 0.5) {
                const li = document.createElement('li');
                li.className = 'bpx-player-ctrl-playbackrate-menu-item';
                li.textContent = `${rate.toFixed(1)}x`;
                li.addEventListener('click', () => {
                    document.querySelector('video').playbackRate = rate;
                });
                menu.insertBefore(li, menu.firstChild);
            }
        }
    }, 1000);
})();

案例3:使用高级API实现数据存储与通信

篡改猴提供了强大的 GM_* API,允许脚本进行数据持久化、跨域请求等。

  • 目标:制作一个简单的页面访问计数器,数据保存在本地。
  • 思路:使用 GM_getValue 和 GM_setValue API来读写存储。在页面上创建一个显示计数的元素。
// ==UserScript==
// @name         页面访问计数器
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  记录并显示访问此页面的次数
// @match        https://www.example.com/*
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function() {
    'use strict';
    const key = 'page_visit_count';
    // 获取当前计数,默认为0
    let count = GM_getValue(key, 0);
    // 计数加1
    count++;
    // 保存新计数
    GM_setValue(key, count);

    // 在页面右上角创建显示元素
    const badge = document.createElement('div');
    badge.textContent = `访问次数: ${count}`;
    badge.style.cssText = 'position:fixed; top:10px; right:10px; padding:5px; background:#333; color:#fff; z-index:9999; border-radius:3px;';
    document.body.appendChild(badge);
})();

案例4:自动化操作

  • 目标:访问某登录页面时,自动填写用户名和密码并点击登录(仅适用于个人测试环境,切勿用于他人网站)。
  • 思路:找到用户名、密码输入框和登录按钮的CSS选择器,通过 value 属性赋值,并模拟 click 事件。
// ==UserScript==
// @name         测试站点自动登录
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  在测试站点自动填充凭证
// @match        https://login.test-site.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    // 使用 setTimeout 确保 DOM 完全就绪
    setTimeout(() => {
        const usernameField = document.querySelector('#username');
        const passwordField = document.querySelector('#password');
        const loginButton = document.querySelector('#login-btn');

        if (usernameField && passwordField && loginButton) {
            usernameField.value = 'your_test_username';
            passwordField.value = 'your_test_password';
            console.log('凭证已自动填充');
            // 自动点击登录按钮
            loginButton.click();
        }
    }, 500);
})();

调试、发布与最佳实践

  • 调试:脚本运行后,打开浏览器的开发者工具(F12),在“控制台”(Console)标签页可以查看log 输出的信息以及任何错误报告,这是调试的主要手段。
  • 发布:如果你编写了一个对他人有用的脚本,可以将其发布到 GreasyFork、OpenUserJS 等用户脚本共享平台。发布前请确保代码安全、无害,并填写清晰的描述。
  • 最佳实践
    • 精确匹配:尽量使用具体的 @match 规则,避免脚本在无关页面上运行,影响性能和安全。
    • 优雅等待:对于动态加载内容的页面,使用 setInterval/setTimeout 或 MutationObserver 来等待目标元素出现,而不是直接操作。
    • 申请权限:按需申请 @grant 权限,不需要时使用 none,以遵循最小权限原则。
    • 代码清晰:保持代码良好的可读性和注释,便于日后维护。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注