Tampermonkey脚本开发进阶:掌握@match规则的艺术与实战策略
你是否曾为同一个脚本需要适配多个网站而头疼?当脚本在CSDN、百度、B站等不同平台运行时,你希望它能“聪明”地识别当前环境,并执行对应的逻辑。这不仅仅是简单的功能开关,更是提升脚本健壮性、可维护性和用户体验的关键。今天,我们就深入探讨Tampermonkey脚本中@match规则的深层应用,特别是如何动态、精准地判断当前匹配的是哪条规则,并据此执行不同的策略。这不仅是技巧,更是一种架构思维。
对于中高级脚本开发者而言,理解并驾驭@match,意味着你的脚本能从“单点工具”进化为“自适应平台”。我们将从规则的本质讲起,逐步深入到动态匹配、策略分发、调试技巧以及复杂场景下的最佳实践,并提供可直接复用的实战代码。无论你是想优化现有脚本,还是构建一个全新的多站点适配工具,这篇文章都将为你提供清晰的路径和扎实的代码支撑。
1. 理解@match:不仅仅是URL过滤器
很多人将@match视为一个简单的URL匹配声明,写在元数据块里就完事了。但实际上,它是脚本与目标网站建立联系的“契约”,是脚本执行环境的精确描述符。深入理解其语法和匹配机制,是后续一切高级操作的基础。
@match规则遵循Chrome扩展的匹配模式语法,其核心是通配符的使用。*可以匹配任意长度的字符序列,而?则匹配单个字符。例如,*://*.example.com/*这个规则分解开来:
*://:匹配任何协议,如http://、https://、ftp://等。*.example.com:匹配example.com的任何子域名,如www.example.com、blog.example.com、api.example.com。/*:匹配该域名下的所有路径。
注意:
@match规则是大小写敏感的,且对URL的编码形式也有要求。一个常见的误区是试图用@match匹配URL的哈希部分(#之后的内容)或查询参数中的特定值,这是无法直接实现的,因为@match只匹配到URL的路径部分。
在实际开发中,我们常常需要为一个脚本定义多个@match规则,以覆盖功能相似但域名不同的网站群。例如,一个用于屏蔽评论区广告的脚本,可能需要同时匹配多个新闻和视频平台:
// ==UserScript==
// @name 智能评论净化器
// @namespace your-namespace
// @version 1.0
// @match *://*.zhihu.com/question/*
// @match *://*.bilibili.com/video/*
// @match *://*.weibo.com/*
// @match *://*.toutiao.com/article/*
// ==/UserScript==
仅仅定义规则还不够。当脚本在这些站点之一运行时,它如何知道自己正身处知乎、B站还是微博?这就需要我们能够在运行时获取并解析当前的匹配状态。
2. 运行时洞察:GM_info.script.matches 的威力
Tampermonkey 提供了一个强大的内置对象 GM_info,它包含了关于脚本本身和运行环境的丰富信息。其中,GM_info.script.matches 正是解决我们问题的钥匙。
这个属性返回一个数组,数组中的元素就是你在元数据块中按顺序定义的所有 @match 规则的字符串形式。关键点在于,这个数组的顺序与你定义的顺序完全一致。这为我们建立“规则索引”到“处理策略”的映射关系提供了可能。
让我们通过一个简单的例子来直观感受:
// ==UserScript==
// @name 多站点演示脚本
// @match *://*.csdn.net/*
// @match *://*.baidu.com/*
// @match *://*.bilibili.com/*
// ==/UserScript==
(function() {
'use strict';
console.log('当前脚本定义的所有匹配规则:');
console.log(GM_info.script.matches);
// 输出:["*://*.csdn.net/*", "*://*.baidu.com/*", "*://*.bilibili.com/*"]
console.log('当前页面URL:', window.location.href);
})();
如果你在 blog.csdn.net 上运行此脚本,控制台会打印出上述数组。但如何判断当前页面匹配的是数组中的第几条规则(索引0,1还是2)?这就需要我们将字符串形式的匹配规则,转换为可以用于测试当前URL的正则表达式。
2.1 从@match字符串到正则表达式
@match的语法并非标准的正则表达式,我们需要进行一次转换。核心是将@match中的通配符*和特殊字符进行转义。下面是一个健壮的转换函数:
/**
* 将Tampermonkey的@match规则字符串转换为正则表达式对象
* @param {string} matchRule - @match规则字符串,如 "*://*.example.com/*"
* @return {RegExp} 可用于测试URL的正则表达式
*/
function matchRuleToRegExp(matchRule) {
// 转义正则表达式中的特殊字符,但保留*和?的通配符含义
let pattern = matchRule
.replace(/[.+^${}()|[\]\\]/g, '\\$&') // 首先转义除了*和?之外的正则特殊字符
.replace(/\*/g, '.*') // 将*转换为.*
.replace(/\?/g, '.'); // 将?转换为.
// 确保匹配完整的URL。添加^和$锚点,并处理协议和域名的边界
// 注意:@match规则本身隐含了从URL开头匹配的语义
pat

&spm=1001.2101.3001.5002&articleId=153308114&d=1&t=3&u=73a0f438df5e431daacaec95946ad4f8)
212

被折叠的 条评论
为什么被折叠?



