添加油猴腳本,去除知乎中“鹽選”付費故事
// ==UserScript==
// @name 鹽選內容隱藏腳本
// @namespace http://tampermonkey.net/
// @version 0.2
// @description 自動隱藏含有“鹽選專欄”或“鹽選”文字的回答卡片
// @author YourName
// @match *://*.zhihu.com/*
// @grant none
// ==/UserScript==(function() {'use strict';// 配置const observerConfig = {childList: true,subtree: true,attributes: false};// 目標元素選擇器和條件const targets = [{selector: 'div.KfeCollection-OrdinaryLabel-content',keyword: '鹽選專欄'},{selector: 'p.KfeCollection-IntroCard-contentName-newStyle-pc',keyword: '鹽選'}];const ancestorSelector = 'div.Card.TopstoryItem.TopstoryItem-isRecommend';// 隱藏卡片的通用函數const hideCard = (element) => {const ancestor = element.closest(ancestorSelector);if (ancestor) {ancestor.remove();}};// 檢查節點并隱藏匹配的卡片const checkNode = (node) => {targets.forEach(target => {if (node.matches(target.selector) && node.textContent.includes(target.keyword)) {hideCard(node);}Array.from(node.querySelectorAll(target.selector)).forEach(element => {if (element.textContent.includes(target.keyword)) {hideCard(element);}});});};// 創建MutationObserver實例const observer = new MutationObserver(mutations => {mutations.forEach(mutation => {mutation.addedNodes.forEach(node => {if (node.nodeType === Node.ELEMENT_NODE) {checkNode(node);}});});});// 初始檢查已存在的內容const initialCheck = () => {targets.forEach(target => {document.querySelectorAll(target.selector).forEach(element => {if (element.textContent.includes(target.keyword)) {hideCard(element);}});});};// 啟動觀察器observer.observe(document.documentElement, observerConfig);// 頁面加載時執行初始檢查window.addEventListener('load', initialCheck);
})();
二、附加解釋
MutationObserver 是一個用于監聽 DOM 樹變化的 JavaScript API。它允許你實時檢測網頁中元素的變化(如添加、刪除節點或屬性修改),非常適合處理動態加載的內容,比如知乎頁面中通過 AJAX 加載的推薦卡片。以下是對腳本中 MutationObserver 使用的詳細解釋:
- MutationObserver 的作用
MutationObserver 提供了一種高效的方式來監聽 DOM 變化,而無需輪詢或依賴定時器。在你的腳本中,它用于檢測知乎頁面中新增的 DOM 節點(例如新加載的推薦卡片),并檢查這些節點是否包含“鹽選”相關內容,以便隱藏對應的卡片。 - 腳本中 MutationObserver 的使用
以下是腳本中 MutationObserver 的具體實現和步驟:
a. 創建 MutationObserver 實例
const observer = new MutationObserver(mutations => {mutations.forEach(mutation => {mutation.addedNodes.forEach(node => {if (node.nodeType === Node.ELEMENT_NODE) {checkNode(node);}});});
});
new MutationObserver(callback):創建一個觀察者實例,callback 是一個函數,當 DOM 發生變化時會被調用。
回調函數:接收 mutations 參數(一個 MutationRecord 數組),每個 MutationRecord 描述一次 DOM 變化。
處理邏輯:
遍歷 mutations 中的每個變化。
檢查 mutation.addedNodes(新增的節點列表)。
只處理元素節點(node.nodeType === Node.ELEMENT_NODE),忽略文本節點等。
對每個新增元素調用 checkNode 函數,檢查是否需要隱藏卡片。
b. 配置觀察器
const observerConfig = {childList: true,subtree: true,attributes: false
};
observerConfig:定義觀察器的監聽范圍和類型:
childList: true:監聽目標節點及其子節點的添加或刪除。
subtree: true:監聽目標節點的所有后代節點(不僅是直接子節點)。
attributes: false:不監聽屬性變化(因為腳本只關心節點增刪)。
這種配置確保腳本能捕捉頁面中任何位置的新增節點(如動態加載的推薦卡片)。
c. 啟動觀察
observer.observe(document.documentElement, observerConfig);
observer.observe(target, config):開始觀察指定的目標節點。
目標節點:document.documentElement(即 元素),覆蓋整個頁面。
配置:使用 observerConfig,監聽整個 DOM 樹的節點變化。
3. 為什么使用 MutationObserver
知乎頁面是動態加載的,推薦卡片可能在頁面滾動或刷新時通過 JavaScript 插入 DOM。如果只在頁面加載時檢查(initialCheck),會漏掉后續加載的內容。MutationObserver 的優勢在于:
實時性:它能立即響應 DOM 變化,無需手動輪詢。
高效性:相比定時器(如 setInterval),它只在 DOM 實際變化時觸發,性能更好。
全面性:通過 subtree: true,可以監控整個頁面,包括深層嵌套的動態內容。
4. 腳本中 MutationObserver 的工作流程
初始化:
創建 MutationObserver 實例,定義當 DOM 變化時檢查新增節點的邏輯。
配置為監聽整個 DOM 樹的節點增刪。
啟動:
開始觀察 元素,監控頁面中任何新增節點。
處理變化:
當頁面加載新內容(例如滾動時插入新卡片),MutationObserver 檢測到 addedNodes。
對每個新增元素節點調用 checkNode,檢查是否匹配目標選擇器(div.KfeCollection-OrdinaryLabel-content 或 p.KfeCollection-IntroCard-contentName-newStyle-pc)和關鍵字(“鹽選專欄”或“鹽選”)。
如果匹配,找到祖先卡片(div.Card.TopstoryItem.TopstoryItem-isRecommend)并移除。
初始檢查補充:
由于 MutationObserver 只監聽變化,腳本還通過 window.addEventListener(‘load’, initialCheck) 檢查頁面加載時已存在的卡片。
5. 代碼中的優化點
節點類型檢查:腳本通過 node.nodeType === Node.ELEMENT_NODE 過濾非元素節點(如文本節點),提高效率。
選擇器檢查:checkNode 使用 matches 和 querySelectorAll,確保只處理符合條件的元素。
去重邏輯:通過 hideCard 函數統一卡片移除邏輯,避免重復代碼。
6. 可能的改進
性能優化:如果頁面變化頻繁,可以限制觀察范圍(例如只觀察某個容器如 div.Topstory-container),減少不必要的檢查。
斷開觀察:在某些場景下(例如頁面切換),可以通過 observer.disconnect() 停止觀察以釋放資源。
錯誤處理:添加 try-catch 塊處理 DOM 操作中的潛在異常。
7. 總結
MutationObserver 在腳本中用于實時監控知乎頁面中的 DOM 變化,捕獲動態加載的推薦卡片,并檢查是否包含“鹽選”相關內容。通過配置 childList 和 subtree,它能高效地覆蓋整個頁面,確保新插入的卡片被及時處理。結合初始檢查,腳本實現了對靜態和動態內容的全面覆蓋,完美適配知乎的動態加載場景。