SonicBot

如何撰写 Adblock Plus 广告过滤规则
当前的 Adblock Plus 版本允许您通过许多不同的方法来优化过滤规则。本文档就是告诉您如何做。声明:这里给...
扫描右侧二维码阅读全文
04
2018/11

如何撰写 Adblock Plus 广告过滤规则

当前的 Adblock Plus 版本允许您通过许多不同的方法来优化过滤规则。本文档就是告诉您如何做。

声明:这里给出的过滤规则只是示例,不一定能直接使用。

AdBlock Plus 过滤规则介绍

本章节描述的过滤规则属性,对偶尔才写过滤规则的用户来说足矣。

基本过滤规则

最简单的过滤规则当然就是您想阻挡的横幅广告地址,但是这些地址常常会在您每次打开页面时改变。例如: http://example.com/ads/banner123.gif,其中 123 是一个随机数字。在这里阻挡整个图片地址是没用的,您需要创建一条更通用的过滤规则 —— 如 http://example.com/ads/banner.gif。或者更为通用一些的,如 http://example.com/ads/

注:不要使用通配符来代替过多的字符。过滤规则 http://example.com/* 固然可以阻挡所有的横幅广告, 但也会阻挡 example.com 下其它一些您想看的内容。

定义例外规则

有时您可能会发现某个过滤规则平时挡广告挡得很好,但在某些情况下,会阻挡一些不该挡的内容。您不想移除这条过滤规则,但也不希望它阻挡不该挡的内容。

这就是例外规则的好处——它们允许您定义过滤规则不被使用的情况。例如,您不满意过滤规则 adv 阻挡了 http://example.com/advice.html,您就可以定义一条例外规则 @@advice 。 例外规则和过滤规则没什么两样,您可以使用通配符或正则表达式。您只需在规则前添加 @@ 来声明这是一个例外规则。

Exception rules can do more. If you specify $document option you will get an exception for the entire page. For example, if your exception rule is @@||example.com^$document and you open some page from example.com — Adblock Plus will be entirely disabled on this page and nothing will be blocked.

匹配网址开头/结尾

通常 Adblock Plus 处理过滤规则时,会自己假设在过滤规则的开头与结尾都有一个通配符,例如,过滤规则 ad 和 ad 是一样。 正常情况下这没什么问题,但有时您可能想要定义可以匹配以网址开头或结尾的过滤规则。例如,您想要阻挡所有的 Flash,但如果您添加过滤规则 swf 地址 http://example.com/swf/index.html 同样也将被阻挡。

这个问题的解决方法:使用管线符号(|)来表示地址的最前端或最末端。例如这条过滤规则 swf| 会阻挡 http://example.com/annoyingflash.swf 但不会阻挡 http://example.com/swf/index.html。这条过滤规则 |http://baddomain.example/ 会阻挡 http://baddomain.example/banner.gif 但不会阻挡 http://gooddomain.example/analyze?http://baddomain.example。

有时您想阻挡 http://example.com/banner.gif 以及 https://example.com/banner.gifhttp://www.example.com/banner.gif。这时只需在过滤规则的域名前面加上两个管线符号(||):||example.com/banner.gif 将会阻挡上面的地址而不会阻挡 http://badexample.com/banner.gif 或者 http://gooddomain.example/analyze?http://example.com/banner.gif(需要 Adblock Plus 1.1 或更高版本)。

标记分隔符

通常您需要接受过滤规则的任何分隔符。例如,您可能写这样一个规则阻挡 http://example.com/http://example.com:8000/ 但不能阻挡 http://example.com.ar/。在这里,符号(^)用作一个分隔符。 http://example.com^(需要 Adblock Plus 1.1 或更高版本)。

分隔符可以是除了字母、数字或者 _ - . % 之外的任何字符。 这个地址的结尾也是作为一个分隔符,下面的例子中所有的分隔符以红色标记出: http://example.com:8000/foo.bar?a=12&b=%D1%82%D0%B5%D1%81%D1%82。所以这个地址可以通过这些过滤规则过滤 ^example.com^ 或 ^%D1%82%D0%B5%D1%81%D1%82^ 或 ^foo.bar^ 。

注释

任何以感叹号 (!) 开始的规则,都被视为注释。在过滤规则的列表中,仍然会显示这些规则,但会用灰色的字来显示,而不是黑色。Adblock Plus 在判断规则时,会忽略这些注释,所以我们可以写下任何我们想写的东西。您可以在一条规则上面写下这条规则是做什么用的。也可以在过滤列表的上方写上作者信息(大多数过滤列表的作者已经这样做了)。

特殊注释

特殊注释只在下载的过滤规则列表中生效,在自定义列表中无效。 Special comments must be given at the top of the filter list right below the header. 它们可以为该过滤规则列表设置许多参数:

! Homepage: http://example.com/

此注释表明哪个网页是该过滤规则列表的首页。

! Title: FooList

此注释为该过滤规则列表设置一个固定的标题。 如果此注释存在,用户不能再更改该标题。

! Expires: 5 days

此注释设置该过滤规则列表的更新间隔,指定的值为天数(例如5 days)或者小时数(例如8 hours)。 可以提供1小时至14天之间的值。 注意:更新并不一定会在指定的间隔到达时发生。 实际的更新时间会稍微随机化并取决于一些额外因素,以减少服务器负载。

! Redirect: http://example.com/list.txt

此注释表明该过滤规则列表已被转移到一个新的下载地址。 Adblock Plus 将忽略此注释后的任何文件内容并立即尝试从新的地址下载。 如果成功,过滤规则列表的地址将按此设置被更新。 如果新的地址与当前地址相同,此注释将被忽略,并意味着它可以作为该过滤规则列表的“权威”地址使用。

! Version: 1234

此注释定义过滤规则列表的数字版本。 此版本号将显示在问题报告中,并且可以用于验证报告指向的是否是过滤规则列表的当前版本。

进阶功能

本章节描述的特性通常只有高级用户和维护过滤列表的作者才会看。普通用户可跳过。

指定过滤规则选项

Adblock Plus 允许您指定某些选项来改变某条规则的行为。您列举这些选项的时候将它们放在美元符号 ($) 后面并用逗号 (,) 分割这些选项,放在过滤规则的最后面,例如:

*/ads/*$script,match-case
这里的 /ads/ 是真实的过滤规则 script 和 match-case 是其指定的选项。下面是目前支持的选项:

类型选项:判定过滤规则(或例外规则)过滤元素的类型。过滤规则可以指定多个类型选项来过滤指定的元素类型。可以指定的类型包括:
script —— 外部脚本,由 HTML script 标签加载
image —— 正常图片,通常由 HTML 的 img 标签所载入
stylesheet —— 外部 CSS 样式文件
object —— 由浏览器插件处理的内容,例如 Flash 或 Java
xmlhttprequest — requests started using the XMLHttpRequest object or fetch() API
object-subrequest —— 插件的请求,比如Flash
subdocument —— 内嵌的页面,通常通过 HTML 的框架方式内嵌
ping — requests started by or navigator.sendBeacon() (Adblock Plus 2.7.1 or higher required)
websocket — requests initiated via WebSocket object (Adblock Plus 2.8 or higher required)
webrtc — connections opened via RTCPeerConnection instances to ICE servers (Adblock Plus 1.13.3 for Chrome and Opera, 3.0 for Firefox, or higher required)
document —— 网页本身(只适用于 例外规则 )
elemhide —— 只适用于例外规则,类似于document 但是只禁用页面上的隐藏规则而不是所有规则(需要Adblock Plus 1.2 或更高版本)
generichide — for exception rules only, similar to elemhide but only disables generic element hiding rules on the page (Adblock Plus 2.6.12 or higher required)
genericblock — for exception rules only, just like generichide but disables generic blocking rules (Adblock Plus 2.6.12 or higher required)
popup — pages opened in a new tab or window
other —— 其他不在上面的类型的请求
The type options background, xbl and dtd are outdated and should no longer be used.
反转类型选项:指定过滤规则不应用的元素类型。可以指定的类型选项: ~script, ~image, ~stylesheet, ~object, ~xmlhttprequest, ~object-subrequest, ~subdocument, ~document, ~elemhide, ~other
third-party/first-party 请求限制:如果指定了 third-party 选项, 则过滤规则只适用于来源与当前正在浏览的页面的不同的请求。类似地,~third-party 适用于来源与当前浏览页面相同的请求。
域名限定:选项 domain=example.com 指过滤规则只适用于 "example.com" 下的页面 。多个域名可以用 "|" 分隔: 过滤规则 domain=example.com|example.net 将只适用于 "example.com" 或 "example.net" 的页面。如果一个域名是前面有"~",则该过滤规则不适用于这个域名的页面。例如: domain=~example.com 指过滤规则适用于除了 example.com 之外的任何域名的页面而 domain=example.com|~foo.example.com 限定了过滤规则适用于 "example.com" 但不包括 "foo.example.com" 。
Sitekey 限制:选项 sitekey=abcdsitekeydcba 意味着该过滤规则应该只在页面上提供了一个与过滤规则内含有的非常相似的(但没有 = 后缀的)公钥和一个可被验证的签名时应用。可以使用“|”作为分隔指定多个 sitekey:使用 sitekey=abcdsitekeydcba|bcdesitekeyedcb 作为过滤规则的选项时,将只会在页面提供了“abcdsitekeydcba”或者“bcdesitekeyedcb”的 sitekey 时应用。这类似于域名限制,但这允许单条过滤规则应用到相当多的域。注意,sitekey 限制需要服务器侧的修改。
Content Security Policies: The option csp=script-src: 'none' causes a Content Security Policy header of script-src: 'none' to be injected into HTTP responses for requested documents matching the filter — assuming that exception rules with the same option don't also match and that the document isn’t whitelisted. The Content Security Policy script-src: 'none' would in turn block all scripts — including inline — for the document. This filter option should generally be avoided, except as a last resort to counter advanced circumvention. (Adblock Plus 3.1 or higher required.)
match-case —— 使过滤规则只适用于匹配地址,例如:过滤规则 */BannerAd.gif$match-case 会阻挡
http://example.com/BannerAd.gif 但不会阻挡 http://example.com/bannerad.gif
collapse — 这个选项将覆盖全局"隐藏已屏蔽元素的占位符"选项,并确保过滤规则总是隐藏这些元素。类似地,~collapse 选项将确保过滤规则不隐藏这些元素。
donottrack —— 对有该选项的阻挡规则匹配到且有该选项的例外规则未匹配到的地址会发送一个 Do-Not-Track 头 (需要Adblock Plus 1.3.5 或更高版本)。 为了向后兼容,使用此选项时建议使用矛盾的组合类型选项,防止此规则在早期版本的 Adblock Plus 中阻挡任何东西: *$donottrack,image,~image
Rewrite the URL with the option rewrite=. You may want to create a regular expression filter to perform the rewrite operation. In that case, you can use $n in the rewrite argument, with n being a number between 1 and 100, to insert the n-th parenthesis submatch of the filter regular expression. Anything not explicitly matched by it will be added in the rewritten string. For example /(server\.com\/assets\/file.php)\?.*$/$rewrite=$1 will strip everything that comes after ".php" and redirects the request to the resulting URL. If there is no query string (i.e. no '?'), this filter won't match. The rewrite parameter has the same syntax as JavaScript’s String.prototype.replace(). The resulting URL must have the same origin; in case it is rewritten to a relative URL, the origin gets added back. Also, rewrite for scripts, subdocuments, objects, requests from within objects (like Flash) are not possible for security reason; even if explicitly stated by the filter. If both, a filter with/without $rewrite option matches, the behavior is undefined, i.e. the request might either be blocked or redirected. (Adblock Plus 3.2 or higher required.)
使用正则表达式
如果您想更好地控制您的过滤规则,什么匹配,什么不匹配,您可以使用正则表达式。例如过滤规则 /bannerd+/ 会匹配 banner123 和 banner321 而不会匹配 banners。 您可以查看正则表达式的文档来学习如何写正则表达式。

注: 由于性能原因,建议尽可能避免使用正则表达式。

元素隐藏

基本规则

有时您可能会发现无法阻挡某些内嵌在网页中的文字广告。如果查看源码的话,可能发现类似这样的代码:

<div class="textad">
Cheapest tofu, only here and now!
</div>
<div id="sponsorad">
Really cheap tofu, click here!
</div>
<textad>
Only here you get the best tofu!
</textad>

因为您必须下载页面的内容,所以您也必须下载这些广告。对于这种情况,您可以做的就是把这些广告藏起来,这样您就不会看到他们了。这也就是元素隐藏的意义所在。

上面代码中的第一则广告是在一个 class 属性为“textad”的 div 容器内。过滤规则 ##.textad 。 这里的 ## 表明这是一条元素隐藏规则,剩下的就是定义需要隐藏元素的选择器,同样的,您可以通过他们的 id 属性来隐藏 ###sponsorad 会隐藏第二个广告。您不需要指定元素的名称, 过滤规则 ##textad 同样也可以。您也可以仅指定要阻挡的元素名称来隐藏,例如:{4} 可以隐藏第三则广告。

在不查看页面源码的情况下,Element Hiding Helper 扩展 可以帮助选择正确的元素并写出相应的规则。基础的HTML知识还是很有用的。

注:元素隐藏规则与普通过滤规则的工作方式有很大的差别。元素隐藏规则不支持通配符。

限定在特定域名的规则

通常您只想要隐藏特定网站的特定广告,而不希望规则会作用于其他网站。例如,过滤规则 ##.sponsor 可能会把某些网站的有效代码也隐藏了。但如果你把它写成 example.com##.sponsor 就只会在 http://example.com/http://something.example.com/ 生效了,而不是 http://example.org/。 你也可以指定多个域名——只要用逗号(,)分隔即可:domain1.example,domain2.example,domain3.example##.sponsor 。

如果在域名之前有 "~",该过滤规则不适用于这个域名的页面(需要 AdBlock Plus 1.1或更高版本)。例如, ~example.com##.sponsor 将适用于除了 "example.com" 之外的域名,example.com,~foo.example.com##.sponsor 适用于 "example.com" 但不适用于 "foo.example.com" 子域名。

注:由于元素隐藏实现方式的关系,您只可以将隐藏规则限定在完整的域名。您不能使用网址的其他部份,也不可用 domain 代替 domain.example,domain.test 。

注: 限定域名的元素隐藏规则也可用来隐藏浏览器的使用界面。例如,过滤规则 browser##menuitem#javascriptConsole 会隐藏 Firefox 工具菜单中的 JavaScript 控制台。

属性选择符

一些广告隐藏起来并不容易——它们广告不仅没有 id 也没有 class 属性。您可以使用其他属性来隐藏,例如 ##table[width="80%"] 可以隐藏 width 属性值为 80% 的表格元素。 如果您不想指定属性的完整值,##div[title*="adv"] 会隐藏所有 title 属性包含 adv 字符的 div 元素。您还可以检查属性的开始和结束字符,例如 ##divtitle^="adv" 会隐藏 titile 属性以 adv 开始并且以 ert 结束的 div 元素。正如您所见,你可以使用多个条件 —— tablewidth="80%" 会匹配到 width 属性为 80%、bgcolor 属性为 white 的表格元素。

高级选择符

通常情况下,Firefox 支持的 CSS 选择器都可用于元素隐藏。例如:下面的过滤规则会隐藏 class 的属性为 adheader 的 div 元素相邻的元素: ##.adheader + *。完整的 CSS 列表请查看 W3C CSS 规范 (Firefox 目前并没有支持所有的选择器)。 Please keep in mind that browsers are slower to process these selectors than selectors based on class or id attribute only.

注:这个功能只是给高级用户使用的,您可以很舒服地通过 CSS 选择符去使用它。Adblock Plus 无法检查您添加的选择器的语法是否正确,如果您使用无效的 CSS 语法,可能会破坏其它已有的有效过滤规则。建议使用 JavaScript 控制台检查是否有 CSS 错误。

Extended CSS selectors (Adblock Plus specific)

Sometimes the standard CSS selectors aren't powerful enough to hide an advertisement. For those cases we have added some new selectors, namely :-abp-has(), :-abp-contains() and :-abp-properties() (requires Adblock Plus 1.13.3 or higher for Chrome and Opera).

When writing an element hiding filter that makes use of these extended selectors you must use the #?# syntax, e.g. example.com#?#selector. But it's important to note that doing so carries a performance impact, so do so sparingly and make sure those filters are specific to as few domains and elements as possible.

:-abp-properties()

:-abp-properties(properties) will select elements based upon stylesheet properties. For example :-abp-properties(width:300px;height:250px;) will select elements that have a corresponding CSS rule in a stylesheet which sets the width and height to the values 300px and 250px respectively. Property names are matched case-insensitively. Furthermore, wildcards can be used so that :-abp-properties(width:*px;height:250px;) will match any width specified in pixels and a height of 250 pixels.

You can also use regular expressions by surrounding the properties expression with "/". For example, :-abp-properties(/width:30[2-8]px;height:250px;/) will match widths between 302 and 308 pixels and a height of 250 pixels.

Note: The older syntax for the CSS property filters is deprecated and will be automatically converted to the new format . The syntax to select the style properties remain the same. For example, [-abp-properties='width:300px;height:250px;'] will be converted to :-abp-properties(width:300px;height:250px;).

:-abp-properties() will also select elements using the style properties found in their pseudo-elements, like ::before and ::after. For example, :-abp-properties(content:'Advertisment') will match elements where the string Advertisment is found in either their ::before or ::after pseudo element.

:-abp-has()

:-abp-has(selector) will select elements based on their content. For example :-abp-has(> div > a.advertiser) will select elements that contain as a direct descendant a <div> that contains an with the class advertiser. The inner selector can be relative to the element scope, and can use any of the pseudo-selectors, including :-abp-has() and will determine whether the selection will occur.

:-abp-contains()

:-abp-contains(text) will select elements based on their text content. For example, div.sidebar > span:-abp-contains(Advertisment) will select the <span> elements within a <div>, with a class of sidebar that contains the word "Advertisment". In practice, you'd want to combine this with a :-abp-has() to select the outer container — something like div.sidebar > div:-abp-has(span:-abp-contains(Advertisment)) to select the container that would contain an advertisement label.

例外规则

例外规则的作用是在特定域名中禁用已有的规则。 这对于那些与其他订阅组配合使用,且无法更改该订阅组的作者来说较为有用。 例如,如要让 ##.textad 规则禁用于 example.com,可以使用 example.com#@#.textad。 这条组合规则就等同于 ~example.com##.textad。 建议您仅在无法调整全局隐藏规则时才使用例外规则,否则请首选限定在特定域名的规则。 These exceptions will be applied to advanced pseudo-selector rules as well.

Generic / Specific filters

With the $generichide and $genericblock filter options the distinction between generic and specific filters becomes important.

We classify a filter to be specific if it matches one or more domains or matches a sitekey. If a filter has no domains specified (or only domain exceptions) and no sitekey then it counts as generic. For example, example.com##.textad is a specific filter, whereas both ##.textad and ~example.com##.textad are generic.

Note that with blocking rules the domain must be specified under the $domain option for them to be considered specific. For example, ||example.com^ is considered generic whereas */ads/*$domain=example.com is site-specific.

在服务器上实施 sitekey

若想完成一个采用 sitekey 限制的过滤规则,一个网页需要返回 Base64 编码的公钥版本和 Adblock Plus 可以验证的签名。目前来说,这需要在 HTTP 相应头中包含(X-Adblock-Key: abcdpublickeydcba_abcdsignaturedcba)及 document 的根标签中(<html data-adblockkey="abcdpublickeydcba_abcdsignaturedcba">)。

首先,您需要创建一个专用的 RSA 密钥(最好是 512 位以保证较低传输负担)和一个公钥的 DER 表示。

创建签名使用的数据是一个请求变量的连续列表(即 URI、Host 和 User Agent),分隔符是 NUL 字符,即“0”。举例来说:

/index.html?q=foo0www.example.com0Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:30.0) Gecko/20100101 Firefox/30.0
最后,使用 SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE 签名算法生成此字符串的签名(是使用 OpenSSL 时的默认值)。

Last modification:November 4th, 2018 at 10:50 pm

Leave a Comment