banner
Leo

Leo的恒河沙

一个活跃于在珠三角和长三角的商业顾问/跨境电商专家/投资人/技术宅/骑行爱好者/两条边牧及一堆小野猫的王/已婚;欢迎订阅,日常更新经过我筛选的适合精读的文章,横跨商业经济情感技术等板块,总之就是我感兴趣的一切

2024-02-23-用廣告攔截器隱藏干擾元素:常用思路和語法介紹 | 少數派會員 π+Prime

用廣告攔截器隱藏干擾元素:常用思路和語法介紹 | 少數派會員 π+Prime#

#Omnivore

針對屏蔽網頁上干擾元素的需求,本文介紹了廣告攔截器中「修飾規則」的基本原理,以及其中元素選擇器部分的常用製作思路。


引言#

在如今群魔亂舞的網絡內容生態下,廣告攔截器幾乎已經從一種可選項變成了必需品;沒有廣告攔截的瀏覽體驗幾乎是不可接受的。

不過,僅靠安裝一個廣告攔截器,並不足以實現令人滿意的效果。廣告攔截器依賴的規則集 —— 本質上是要攔截或隱藏的元素列表 —— 都是由社區維護的,質量參差不齊;即使人氣較高的規則,也會隨著時間推移積累很多冗餘和錯誤。如果貪多求全、囫圇啟用,很容易拖累性能、導致誤傷。

什麼內容應當被屏蔽也是一個非常主觀的判斷。有些視覺干擾較小、出現頻率不高、不涉及隱私追蹤的廣告,其實是可以接受的,也是給獨立、小規模網站提供力所能及支持的一種方式。(這也是 Better AdsAcceptable Ads 等項目的主張,儘管兩者都因與廣告商存在利益往來受到批判。)

相反,有些嚴格意義上不是「廣告」的元素,同樣具有浪費資源、佔用注意力的危害,例如側邊欄裡惹眼的推薦窗格、強行穿插在文章中的自動播放視頻、郵件訂閱請求,等等。

因此,完全符合自己要求的規則集其實是很難找到現成的。即使是 Fanboy’s Annoyance ListAdGuard Annoyances Filter 等針對「惱人」元素的規則集,也只相對保守地覆蓋了有一定流量和人氣的網站上一小部分的干擾元素。要真正取得理想的效果,自己動手是免不了的。

不過,廣告攔截器官方文檔(例如 uBlock OriginAdGuard)中的說明一般比較晦澀,初上手時看起來可能有些門檻。為此,本文將從入門角度,介紹一些常用思路和對應語法,希望能幫助讀者上手寫出自己需要的規則。

(** 注:** 市面上廣告攔截器很多,品質良莠不齊,規則語法各有差異。如無特別說明,後文示例均以綜合口碑最好的 uBlock Origin 為準。如果所用瀏覽器不受支持,AdGuard 也可一用,兩者語法大體上是兼容的。)

基礎鋪墊#

在動手寫規則之前,首先應當了解廣告攔截器使用的規則主要分為兩類:

  • 基礎規則(basic rules),也稱攔截規則(blocking rules)。這種規則是針對特定文件地址的,目的是讓顯示廣告所需的數據無法加載。因此,更適合用來屏蔽 URL 特徵明顯(例如文件名或路徑有固定規律)的廣告資源文件、跟蹤腳本等;也只有這種規則能起到保護隱私的作用。
  • 修飾規則(cosmetic rules),也稱隱藏規則(hiding rules)。這種規則是針對特定頁面元素的,目的是將頁面上廣告所在部分隱藏起來。因此,更適合屏蔽不易通過 URL 特徵加以區分、但在頁面上的出現位置有規律的元素;也經常用作普通規則的補充,隱藏無法加載的廣告部分在頁面上留下的空白。

(一些更複雜的規則,例如注入自定義 CSS 樣式或 JavaScript 腳本的規則,是部分攔截器自行實現的,通用性不足,本文暫不討論。)

就本文討論的屏蔽干擾元素場景而言,由於這類元素大多同時包含了文本和媒體文件,位置上也常與主體內容穿插排列,用攔截規則來屏蔽既不方便也不現實,因此主要用得上的是修飾規則,追求一個「眼不見心不煩」。因此,下面也將以修飾規則為重點來介紹。

修飾規則的一般格式如下:

example.org##selector

其中,分隔符 ## 之前的是規則針對的域名,之後的部分就是要屏蔽元素的表達式。

如何指定要屏蔽的元素呢?這主要是通過 CSS 選擇器(CSS selector)來表達的。


插曲:CSS 選擇器簡介

如果你不熟悉 CSS 是什麼及其工作機制,這是一個簡單版的解釋:網頁的外觀是由「內容」和「樣式」兩個部分共同決定的。例如,網頁上「有什麼字」是內容問題,「用什麼字體」是樣式問題;「顯示什麼圖片」是內容問題,「圖片的尺寸和動效」是樣式問題;等等。

CSS 就是將樣式應用於內容的一套語法規則。選擇器是這套規則的一部分,其功能就是確定「要裝飾哪些內容」。選擇的依據可能是 ——

  1. 元素類型,例如一級標題 h1、圖片 img 等;
  2. class(類),可以理解為用於歸類一組相關元素的自定義「標籤」;
  3. id(標識符),可以理解為用於識別特定元素的專屬自定義名稱;
  4. 元素的任意屬性,例如鏈接指向的特定網址 a[href="https://example.com"]
  5. 元素的特定狀態,例如鼠標懸浮其上的元素 :hover、第一個下級元素 :first-child
  6. 頁面上具有可識別特徵、但代碼層面並無對應元素的局部,例如緊鄰某個元素之後的位置 ::after,段落中的第一個字符(::first-letter);或者
  7. 上述的結合。

可見,CSS 選擇器為指定網頁上的元素提供了充足的工具。又因為它是所有瀏覽器都支持的通用語法,借用 CSS 選擇器來指定要屏蔽的範圍就是很合理的選擇了。


因此,要寫出能屏蔽特定干擾元素的修飾規則,本質上就是要找出能選中相關元素的 CSS 選擇器。事實上,修飾規則的基本工作原理,就是向當前頁面注入一條針對選中元素的樣式 display: none !important,指的是「使該元素不顯示,忽略所有相反規定」。

怎麼找呢?為了便於用戶自定義修飾規則,大多數廣告攔截插件都會提供一種「選擇並屏蔽」功能。例如,下圖是 uBlock Origin 的「元素選擇器」模式,可以在頁面上點擊右鍵選擇 Block element,或者在插件窗口中點擊滴管形按鈕打開。

image

在元素選擇器模式下,用鼠標點擊頁面上想要屏蔽的部分,uBlock Origin 就會自動記錄其對應的 CSS 選擇器,並加入到規則列表中。(左右兩個滑塊分別用於微調選擇範圍的「深度」和「廣度」,你可以把它們分別想象成控制抓娃娃機中抓手的高低位置和開合幅度。)

這看起來挺方便,然而在當下,這麼做越來越難以獲得令人滿意的結果。顯然,要讓修飾規則充分發揮效果,其選擇器的寫法必須足夠有「代表性」;只針對當前頁面有效的規則是沒什麼意義的。這正是元素選擇器的缺陷所在:它往往只會機械地複製所選元素的屬性,其結果往往是上圖中那種晦澀冗雜的規則。

這些「廢話規則」的成因和問題將在後文具體說明,但不難從直觀上感到它們把範圍劃得過於「具體」了,從而失去了代表性。

相比依賴於廣告攔截器過於機械的元素選擇工具,本文更推薦使用瀏覽器自帶 DevTools(開發者工具)中的檢查器功能。你可以在網頁空白處點擊右鍵選擇 Inspect(或 Inspect Element、檢查元素等類似菜單項)或按 F12 打開它(Safari 需先手動啟用)。

image

檢查器界面的主體是當前頁面中所有元素的樹狀結構(DOM)。點擊左上角的箭頭按鈕(Safari 為右上角的靶形按鈕),可以從頁面中高亮選擇元素,並在 DOM 中定位到其位置。

在這些鋪墊的基礎上,下面就介紹幾種常用的干擾元素屏蔽規則定製思路。

按 class、id 或其他屬性的值屏蔽元素#

前面提過,class 和 id 分別類似於網頁元素的「分類標籤」和「專屬名稱」,因此對於識別和定位網頁元素意義重大。在干擾元素屏蔽的語境下,匹配 class 和 id 也通常是編寫屏蔽規則最高效的方式。

按 class 和 id 的值屏蔽元素的語法分別是:

.value
#value

其中 value 為 class 或 id 的值。

至於選擇什麼值來匹配,一般而言可以關注 ad(廣告)、promo(推廣)、popup(彈出)、cta(call to action,操作引導)等與功能相關的關鍵詞,以及 video(視頻)、banner(橫幅)、carousel(輪播圖片)等與形態、格式相關的關鍵詞。

相反,一般不要考慮 row-span-2(指「占據網格佈局中的 2 行高」)、col-md-6(指「在中等以上尺寸設備上占據網格的 6 列寬」)這樣的名稱。這些名稱是使用 Tailwind、Bootstrap 等 CSS 框架的產物,其功能是指定元素在頁面網格中的佈局,用它們來定位元素既不夠有針對性,也很容易隨著網站的版面微調而失效。

下面舉個例子。下圖所示的 9to5Mac 頁面中,文末植入的「相關視頻」是一種典型的非常自私的設計,僅僅為了引流而占據了大量網頁空間,對於用戶毫無價值。通過檢查器可以看到,這個視頻位於一個 div 元素中,其 class 名稱為非常直白的 article__youtube-video

image

因此,對應的屏蔽規則就是:

9to5mac.com##.article__youtube-video

類似地,可以用下面的規則屏蔽評論區:

9to5mac.com###comments

(注意這裡有三個 #,其中前兩個是分隔符,第三個是 id 選擇器的標誌。)

但這只是最簡單的情況。在更多情況下,你看到的 class 名稱可能是像下面這樣的:

image

這裡,儘管可以從類名中的 offer 字樣判斷出這就是廣告橫幅對應的 class,但如果你直接將完整的類名寫成規則,很可能沒過多久就會發現它失效了。

這是因為,上述類名末尾的 __LvD17 是使用網頁開發框架編譯所產生的隨機字符串,會隨著網站版本的更新不斷改變。不過,這麼做的目的並不是和用戶「躲貓貓」,故意讓用戶難以屏蔽,而是為了避免手工命名 class 導致的操作繁瑣、名稱相互「打架」等問題,在大型站點開發中屬於主流做法。當然,其副作用就是降低了網頁代碼的可讀性,也變相提高了屏蔽元素的難度。

但辦法還是有的,因為 CSS 選擇器可以匹配屬性值的片段(子字符串),具體如下所示:

語法含義
[class^=value]選中類名的開頭為 value 的元素
[class$=value]選中類名的結尾為 value 的元素
[class*=value]選中類名中任意位置包含 value 的元素

(在上述語法結尾的括號之前加一個字母 i,即 [class^=value i] 等等,可以讓匹配變成大小寫不敏感。)

因此,使用 [class^=inlineoffer](匹配開頭)或者 [class*=inline-img-offer-container](匹配中間部分)都可以選中上面的廣告橫幅。至於用哪個更好,沒有標準答案,應當結合嘗試結果做個案判斷。一般而言,越長的名稱意味著越具體,好處是可以避免誤傷;但也可能增加編寫規則的工作量,需要多條規則才能屏蔽乾淨本可以「一網打盡」的同類。

這裡,考慮到較短的 inlineoffer(字面意思是「行內廣告」)無論如何都是干擾元素,不用擔心誤傷,再測試發現確實有效後就可以選用。

此外,如上所述,class 和 id 只是兩種地位特殊的 HTML 元素屬性,本節中提及的選擇器語法也適用於其他任何屬性。例如,在下圖所示的 The Economist 頁面上,右側的廣告元素可以通過自定義屬性 data-test-id 的值識別出來。

image

因此,可以使用如下的規則來屏蔽:

www.economist.com##[data-test-id="right-hand-rail-ads"]

經驗上,其他有助於識別干擾元素的屬性還有 data-ad-typedata-ad-zonerolesrcaria-label 等,留意觀察一般都能發現規律。

根據位置特徵屏蔽元素#

儘管通過 class、id 和屬性選擇器已經能有效應對很多屏蔽需求,但這些選擇器依賴於找出屬性值中的規律,而這並不總是可行的。有些場合,干擾元素的屬性特徵並不明顯,但出現的位置比較固定。這時,關係選擇器(combinators)—— 根據層級和位置關係選擇元素 —— 就是更好的選擇。

閱讀信息

全文字數 5451 字

閱讀本文共需 9 分鐘

字號選擇

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。