如何撰寫 Adblock Plus 過濾規則

translated and rewritten by coolcd

過濾規則撰寫入門

對於偶爾才會自己寫過濾規則的人,看過這個部份描述的過濾規則寫法,應該就夠用了。

基本過濾規則

最簡單的過濾規則當然就是廣告圖片、廣告物件的網址,例如:http://example.com/ads/banner123.gif。但因為某些網頁開啟的廣告圖片網址可能是用指令碼隨機選取,每次插入的廣告圖片網址都不一樣,例如:banner123.gif 中的 123 可能是隨機數字,所以阻擋完整的圖片網址幫助很有限,通常我們比較需要適用範圍較大的過濾規則,例如 http://example.com/ads/banner*.gif 或 http://example.com/ads/*。

注意:使用萬用字元時要小心不要它取代太多字元。例如:http://example.com/* 雖然可以擋住 http:example.com/banner123.gif,但也會擋掉 http://example.com/ 底下的所有東西,例如:http://example.com/index.html。

例外規則

有時你可能會發現-某個過濾規則平時擋廣告擋得很好,但在某些情況下,會擋到不該擋的東西。假如你不希望移除這條過濾規則,但也不希望它擋到不該擋的東西,此時,你需要的就是-例外規則。

例外規則的功能就是-讓你定義在某些情況,不要套用某些過濾規則。例如:假如你有一條過濾規則 adv,這會擋掉所有含有 adv 的網址,包括你不想擋的 http://example.com/advice.html。這時你就可以設一條例外規則 @@advice。例外規則的寫法與過濾規則完全一樣,只不過前面多加兩個 @ 符號,以便讓 Adblock Plus 知道這是例外規則。

事實上,「例外」的範圍可以很大。例如:「@@|http://example.com」代表在瀏覽所有 http://example.com 底下的頁面時,都不要使用 Adblock Plus 的過濾規則,也就等於是將 http://example.com 加入白名單的意思。在這裡 http 前方的管線符號(|)代表「字串邊界」的意思,後面會再介紹。假如使用 @@http:// 或 @@https://,就會將所有以 http:// 或 https:// 開頭的網址都列入白名單,也就是說你的 Adblock Plus 等於是白開了。

註解(comment)

任何以驚嘆號(!)開頭的規則,都被視為註解。在過濾規則的視窗中,仍然會顯示這些文字,但會用灰色的字來顯示,而不是黑色。 Adblock Plus 在判斷規則時,會忽略這些開頭是驚嘆號的規則,所以我們可以寫下任何我們想寫的東西,例如:我們可以在某條複雜難懂的規則上面寫下這條規則是做什麼用的,也可以註解某條過濾條件的作者是誰、是哪一個版本。

進階功能

這個部份描述的功能比較進階,通常只有 power users 與維護過濾清單的作者才會看,一般使用者可以跳過沒關係。

比對網址開頭/結尾

Adblock Plus 處理過濾規則時,通常會自己假設在過濾規則的開頭與結尾都有一個萬用字元,也就是說,「ad」與「*ad*」效果是一樣的。通常這並不會帶來問題,但有時你可能想要設定可以抓到「以 xx 開頭」、或「以 xx 結尾」的網址的過濾規則,例如:你想要阻擋所有的 Flash 檔(以 swf 結尾的網址),如果你加入一條規則「swf」,擋到的將不只是以 swf 結尾的網址,只要網址中包含 swf 這個字,都會被阻擋,例如:http://www.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 而不會擋到包含字串 baddomain.example 的其他網域,例如: http://gooddomain.example/analyze?http://baddomain.example。

指定過濾規則選項 (filter options)

Adblock Plus 讓你可以指定某些選項(option)來改變某條過濾規則的行為。指定選項時,在過濾規則後面加個錢號($)分隔,再指定選項,一條規則可以指定多個選項,選項與選項之間用逗號(,)分隔。舉例來說:

*/ads/*$script,match-case

這裡的 */ads/* 是過濾規則,$ 是過濾規則與選項的分隔符號,script 與 match-case 則是我們指定的選項。

以下是目前支援的選項:

  1. 類型選項(Type option):用以決定過濾規則(或例外規則)要用於哪一種類型的元素,可以指定多種類型。可以指定的類型包括:

    1. script:透過 HTML 的 script 標籤載入的外部指令碼。
    2. image:一般圖片,通常由 HTML 的 img 標籤所載入。
    3. background:背景圖片,通常用 CSS 指定。
    4. stylesheet:外部 CSS 樣式表檔案。
    5. object:由瀏覽器的外掛(plugins)處理的內容,例如 Flash 或 Java。
    6. xbl: XBL bindings (通常由 -moz-binding CSS property 所載入),需要 Firefox 3 或更新的版本才支援。
    7. ping: link pings,需要 Firefox 3 或更新的版本才支援。
    8. xmlhttprequest: 由 XMLHttpRequest object 發出的要求 (requests),需要 Firefox 3 或更新的版本才支援。
    9. object-subrequest: 由 plugins (如 flash) 發出的要求 (requests),需要 Firefox 3 或更新的版本才支援。
    10. dtd: 由 XML documents 所載入的 DTD 檔,需要 Firefox 3 或更新的版本才支援。
    11. subdocument:內嵌的頁面,通常用框架的方式內嵌。
    12. document:網頁本身(只有「例外規則」適用)
    13. other:其他類型的要求(request)。(在 Firefox 2,這包含了 XBL bindings, XMLHttpRequests 或其他 Object 要求的資料。)
  2. 反類型選項(Inverse type option):指定過濾規則不適用的對象。可以指定的類型包括:~script, ~image, ~background, ~stylesheet, ~object, ~xbl,~ping,~xmlhttprequest,~object-subrequest,~dtd, ~subdocument, ~document, ~other。
  3. third-party/~third-party 選項:這兩個選項可限制過濾規則適用的 requests 來源。如果指定了 third-party 的選項,過濾規則只會套用於目前看的頁面之外的來源所發出的要求(request)。而 ~third-party 則會限制過濾規則僅適用於 與目前觀看網頁相同的來源 所發出的要求(requests)。
  4. domain=xxx.com 選項:這個選項意指,僅將過濾規則套用於等號後面所指定的網域。以這個例子而言,就是 xxx.com。如要指定多個網域,可用管線符號 ("|") 分隔,例如:domain=xxx.com|xxx.net。如此,過濾規則將會對 xxx.com 與 xxx.net 這兩個網域有作用。如果,在網域前加上"~",就代表不要將過濾規則套用到這個網域,例如:domain=~xxx.com 意指:adblock plus 應將過濾規則套用到任何網頁,但 xxx.com 的網頁除外。如果是:domain=xxx.com|~foo.xxx.com,就代表:應將過濾規則套用到 xxx.com,但 foo.xxx.com 底下的網頁除外。
  5. match-case 選項:這是指定大小寫是否視為不同的選項。指定此選項時,過濾規則只作用於大小寫完全符合的網址。例如:「*/BannerAd.gif$match-case」會擋掉 http://example.com/BannerAd.gif 但不會擋掉 http://example.com/bannerad.gif。
  6. collapse 選項:這是告訴 Adblock Plus 是否清除佔用空間的選項,在過濾規則後指定這個選項,會蓋過 Adblock Plus 選項中的設定。若在過濾規則後加上「$collapse」,代表會把這項過濾規則阻擋到的物件所佔用的空間釋放出來,讓其他元素使用,若加上「$~collapse」則相反。

使用正規表達式 (regular expression)

如果你想要更精密地控制過濾規則,可以使用「正規表達式」。例如:「/banner\d+/」會抓到 banner123 與 banner321,但不會抓到 banners。你可以看 Core JavaScript 1.5 Reference:Global Objects:RegExp 來學習如何撰寫正規表達式。

注意:你不應該為了加速過濾清單的處理而使用正規表達式。你可能聽過類似的說法,但其實那已經過時了。從 Adblock Plus 0.7 開始,對於基本過濾規則(basic filter)的處理,已經比正規表達式還要快了。

元素隱藏:基本規則

有時你可能會發覺無法阻擋某些網告,因為那些廣告內嵌於網頁文字之中。如果看原始碼的話,可能發現這樣的語法:

<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>

因為你必須下載網頁內容,所以你也會下載到其中你所不想看到的的廣告。對於這種情況,你可以做的就是-把這些廣告藏起來,這樣你就不會看到那些廣告了。這也就是元素隱藏(Element Hiding)這項功能的目的。

上面這段原始碼中的第一則廣告是在一個擁有 class 屬性為「textad」的 div 元素內,用「#div(textad)」可以把它給隱藏起來。你也可以用相同的方式改由ID屬性來隱藏元素,例如:「#div(sponsorad)」會隱藏上面原始碼中的第二則廣告。你也可以不必指定元素名稱,用「#*(sponsorad)」也可以。你也可以僅指定要阻擋的元素名稱,例如:「#textad」可以阻擋第三則廣告。

那麼,你該如何知道,要把什麼東西納入元素隱藏的規則呢?你有兩個選擇,一是直接看網頁的原始碼,並自行找出廣告所在;或者用 DOM Inspector(Firefox 使用者必須在安裝 Firefox 時選「自訂安裝」並將相關選項打勾,Firefox 才會安裝 DOM Inspector)。要能夠順利使用此功能,你需要有 HTML 的基礎。

注意:元素隱藏規則與普通過濾規則的工作方式有很大的差別。元素隱藏規則不支援萬用字元、不支援阻擋次數統計(hit count)、且會忽略例外規則。

元素隱藏:限定只在特定網域使用規則

通常你只想要隱藏特定網站的特定廣告,而不希望規則會作用於其他網站。例如:「#*(sponsor)」可能會把某些網站的有效代碼也隱藏了。但如果你把隱藏規則寫成「example.com#*(sponsor)」,這規則就只會作用在 http://example.com/ 與 http://something.example.com/,但不作用在 http://example.org/。你也可以指定多個網域-只要用逗號(,)分隔即可,例如:「domain1.example,domain2.example,domain3.example#*(sponsor)」。

注意:由於元素隱藏實作方式的關係,你只可以將隱藏規則限制於完整的網域名稱(Full domain name),你不能使用網址的其他部份,也不可用 domain 代表 domain.example,domain.test。

注意:有限制網域的元素隱藏規則也可用來隱藏瀏覽器的使用介面。例如:「browser#menuitem(javascriptConsole)」會隱藏 Firefox 工具選單內的 JavaScript Console 選項。

元素隱藏:屬性選取符 (selectors)

有時後廣告沒有 ID 屬性,也沒有 class 屬性,這時你就需要使用其他屬性來隱藏這些廣告,例如:「#table(width=80%)」可以隱藏擁有 width 屬性值為80%的表格元素。你也可以用「*=」、「^=」或「$=」來增加指定屬性值時的彈性。「#div(title*=adv)」會隱藏所有具有title屬性、屬性值包含字串「adv」的div元素。「#div(title^=adv)(title$=ert)」會隱藏具有title屬性、且title屬性以字串「adv」開頭、以字串「ert」結尾的 div 元素。如上所見,我們可以設定多種條件,例如:「table(width=80%)(bgcolor=white)」會隱藏寬度設為80%、背景為白色的表格元素。

元素隱藏:使用 CSS 選取符

如果用上述依屬性選取元素方式仍然不夠用,你甚至可以使用 CSS 選取符!例如:下規則會隱藏任何跟在 class 屬性為「adheader」的 div 元素後的任何東西:「##div.adheader + *」。兩個井號(#)代表這條元素隱藏規則要以 CSS 選取符來詮釋(這個例子使用到的是adjacent sibling selector)。

注意:這個功能是給進階使用者使用的,Adblock Plus 無法檢查選取符的語法是否正確,如果你使用無效的 CSS 語法,你可能會破壞其他你已經有的過濾規則,建議使用 JavaScript Console 檢查是否有 CSS 錯誤。

相容性 (Adblock 與 Adblock Plus 的版本差異)

  1. 這份文件描述的過濾規則寫法適用於 Adblock Plus 0.7 時你所。如果你正在整理過濾規則清單,打算將它分享給大家,最好同時考慮其他的 Adblock Plus 版本與 Adblock。這裡僅列出簡短的差異概況:
  2. 比對網址開頭/結尾:僅是用於 Adblock Plus 0.6.1.2 與之後的版本。
  3. 例外規則:在 Adblock 0.5 與 Adblock Plus 0.5 例外規則只對單一項目有作用,而不是整頁。完整頁面的例外規則是使用不同方式定義的。注意:第一個支援例外規則的 Adblock 版本是 0.5.3.40。
  4. 註解:Adblock 0.5 與 Adblock Plus 0.7 版以前,會把註解當成真的過濾規則處理,但這並沒有讓過濾規則清單的作者停止使用井號作為註解,這些規則有時會跟網頁上的任何東西比對,導致比對速度變得非常慢。
  5. 過濾規則選項:只在 Adblock Plus 0.7.1 之後才支援;collapse 選項必需 Adblock Plus 0.7.5 才支援;third-party 選項要 Adblock Plus 1.0 才支援;domain 選項則要 Adblock Plus 1.0.1 才支援。
  6. 元素隱藏:在 Adblock Plus 0.6.1 時加入此功能,但只支援一些基本的規則。屬性選取符、CSS 選取符與限制規則僅做用於特定網域的功能是 Adblock Plus 0.7 才有的。Adblock Plus 0.5 有個功能叫「DIV blocking」,它的目的跟元素隱藏是一樣的,儘管語法類似(故意的),但實際上作法是完全不一樣的,也因此 DIV blocking 的過濾規則與元素隱藏的規則彼此間要轉換是很不容易的。

參考資料

Adblock Plus: Writing Adblock Plus filters