三个真实脚本案例:去广告、自动展开全文、网页暗黑模式
API 认识了,元数据也会写了,这一篇把三者串起来,做三个真实场景的小脚本。每个都控制在几十行内,但都覆盖了完整流程:观察页面、写选择器、处理动态加载、验证效果。建议边读边在自己机器上跑。
案例一:去广告
思路是最简单的「找到就藏掉」。多数广告有稳定的类名或容器特征:
// ==UserScript==
// @name 通用去横幅广告
// @match https://*.news-site.com/*
// @run-at document-start
// @grant GM_addStyle
// ==/UserScript==
GM_addStyle(`
.ad-banner, .ad-wrapper, [class*="advert"] { display: none !important; }
`);
[class*="advert"] 是属性选择器,匹配 class 里含 advert 字样的元素,对付拼写的变体很有效。但这只能处理静态广告;现代页面的广告大多是异步插入的,样式先藏住占位,内容后到,还得补一手 MutationObserver:
new MutationObserver(() => {
document.querySelectorAll(".ad-lazy").forEach(el => el.remove());
}).observe(document.documentElement, { childList: true, subtree: true });
页面一有 DOM 变动就扫一遍,发现广告节点直接移除。注意性能:扫描选择器要尽量窄,别在每帧都全量 querySelector。
案例二:自动展开全文
很多资讯站把长文折叠,要点一下「展开」。通用思路是模拟点击展开按钮,或直接移除限制高度的样式:
// ==UserScript==
// @name 自动展开全文
// @match https://forum.example.com/thread/*
// @grant none
// ==/UserScript==
(function expand() {
// 方式一:找展开按钮就点
const btn = document.querySelector(".read-more-btn");
if (btn) btn.click();
// 方式二:解除高度限制与遮罩
const content = document.querySelector(".article-content");
if (content) {
content.style.maxHeight = "none";
content.style.overflow = "visible";
}
const mask = document.querySelector(".expand-mask");
if (mask) mask.remove();
})();
有的站点展开逻辑在内部状态里,点按钮也没用,这时要进 DevTools 的 Elements 面板观察类名变化,找到触发函数改调用。这个案例的主要技能是「用 DevTools 反推页面逻辑」,比写代码本身更重要。
案例三:网页暗黑模式
给没有夜间模式的老站点整体换肤。纯 CSS 暴力方案对简单页面够用:
// ==UserScript==
// @name 站点暗黑模式
// @match https://legacy.example.com/*
// @run-at document-start
// @grant GM_addStyle
// @grant GM_registerMenuCommand
// ==/UserScript==
let on = GM_getValue("dark", true);
function apply() {
GM_addStyle(`
html { filter: invert(1) hue-rotate(180deg); background: #fff; }
img, video, iframe, [style*="background-image"] {
filter: invert(1) hue-rotate(180deg);
}
`);
}
if (on) apply();
GM_registerMenuCommand("切换暗黑模式", () => {
on = !on;
GM_setValue("dark", on);
location.reload();
});
这里用了一个经典技巧:invert(1) hue-rotate(180deg) 先把整个页面颜色反转再转回色相,得到自然的深色效果,图片视频会被二次反转复原。这套滤镜方案是社区通行的「通用暗黑」做法。菜单项加开关,用 GM 存储记住选择。
三个案例的公共经验
- 先观察后动手。打开 DevTools,确认目标元素的选择器真的稳定,别对着猜的类名写代码。
- 考虑动态加载。主流站点都是 SPA 或流式渲染,一次性脚本常常只对首屏有效,MutationObserver 是标配工具。
- 给用户留开关。哪怕只给自己用,加个菜单开关也能避免「某些场景想临时关掉」时去改代码。
选择器和正则在三个案例里反复出现,不熟的话正则匹配写法可参考本站《正则表达式从入门到精通》:正则实战。习惯在本地编辑器开发的话,这三个脚本都适合放进 HBuilderX 工程管理,改完粘贴进油猴即可,见 HBuilderX 效率技巧。
案例四:强化版去广告的完整结构
案例一只给了片段,这里给一个可以直接跑的完整版本,展示「样式隐藏 + 动态移除 + 菜单开关」的三层结构:
// ==UserScript==
// @name 三层去广告
// @match https://*.news-site.com/*
// @run-at document-start
// @grant GM_addStyle
// @grant GM_registerMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
const enabled = GM_getValue("enabled", true);
if (enabled) {
// 第一层:样式预隐藏,页面渲染前生效
GM_addStyle(`.ad-banner, [class*="advert"] { display: none !important; }`);
// 第二层:DOM 变动监听,清掉异步插入的节点
new MutationObserver(() => {
document.querySelectorAll(".ad-lazy").forEach(el => el.remove());
}).observe(document.documentElement, { childList: true, subtree: true });
}
// 第三层:菜单开关,改完刷新生效
GM_registerMenuCommand(enabled ? "暂时停用去广告" : "恢复去广告", () => {
GM_setValue("enabled", !enabled);
location.reload();
});
注意 enabled 是脚本启动时读的一次性值,切换后靠 reload 应用。要「不刷新即时生效」就得把样式节点动态增删,复杂度上一个台阶——多数场景不值得。
调试这三个案例的通用手法
脚本「跑了但没效果」时的排查三板斧:
- 确认选择器命中:在目标页 Console 里手敲
document.querySelector("你的选择器"),返回 null 就是选择器错——这是八成故障的根因; - 确认脚本时机:
@run-at document-start时document.body可能还是 null,操作 DOM 前先判空或等 DOMContentLoaded; - 确认没有冲突:同页面装了多个改样力的脚本时(比如两个暗黑模式),互相覆盖 filter 或样式,面板里逐个停用做二分。
调试期间建议临时把 @match 收窄到单个测试页面,避免全站弹日志干扰你。定位完成后恢复原匹配范围。
把案例变成自己的模板库
三个案例分别对应三类改造模板:样式注入型(去广告、暗黑)、交互模拟型(自动展开)、状态管理型(带开关与记忆)。真实需求九成落在这三类里。建议把三份代码存成编辑器片段,新需求先判断属于哪一类,从对应模板改起,起手效率完全不同。改模板时最容易错的就是选择器与 URL 模式,正则不熟的话见 正则实战;本地管理脚本工程见 HBuilderX 效率技巧。
三案例的模板归类
| 案例 | 模板类型 | 核心 API / 技巧 | 难点 |
|---|---|---|---|
| 去广告 | 样式注入型 | GM_addStyle、MutationObserver | 动态插入的广告 |
| 自动展开 | 交互模拟型 | el.click()、样式覆写 | 反推页面内部逻辑 |
| 暗黑模式 | 状态管理型 | filter 反转、GM 存储 + 菜单 | 图片二次反转 |
把每个案例往对应模板里归档后,新需求「改样式、点按钮、换皮肤」基本都能套用现成骨架,起手速度完全不同。
本章由 WorkBuddy 原创整理,API 行为依据 Chrome 扩展官方文档(Manifest V3)。
