#去除知乎中“盐选”付费故事

添加油猴脚本,去除知乎中"盐选"付费故事

javascript 复制代码
// ==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 使用的详细解释:
  1. MutationObserver 的作用
    MutationObserver 提供了一种高效的方式来监听 DOM 变化,而无需轮询或依赖定时器。在你的脚本中,它用于检测知乎页面中新增的 DOM 节点(例如新加载的推荐卡片),并检查这些节点是否包含"盐选"相关内容,以便隐藏对应的卡片。
  2. 脚本中 MutationObserver 的使用
    以下是脚本中 MutationObserver 的具体实现和步骤:
    a. 创建 MutationObserver 实例
javascript 复制代码
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. 配置观察器

javascript 复制代码
const observerConfig = {
    childList: true,
    subtree: true,
    attributes: false
};

observerConfig:定义观察器的监听范围和类型:

childList: true:监听目标节点及其子节点的添加或删除。

subtree: true:监听目标节点的所有后代节点(不仅是直接子节点)。

attributes: false:不监听属性变化(因为脚本只关心节点增删)。

这种配置确保脚本能捕捉页面中任何位置的新增节点(如动态加载的推荐卡片)。

c. 启动观察

javascript 复制代码
observer.observe(document.documentElement, observerConfig);

observer.observe(target, config):开始观察指定的目标节点。

目标节点:document.documentElement(即 元素),覆盖整个页面。

配置:使用 observerConfig,监听整个 DOM 树的节点变化。

  1. 为什么使用 MutationObserver

知乎页面是动态加载的,推荐卡片可能在页面滚动或刷新时通过 JavaScript 插入 DOM。如果只在页面加载时检查(initialCheck),会漏掉后续加载的内容。MutationObserver 的优势在于:

实时性:它能立即响应 DOM 变化,无需手动轮询。

高效性:相比定时器(如 setInterval),它只在 DOM 实际变化时触发,性能更好。

全面性:通过 subtree: true,可以监控整个页面,包括深层嵌套的动态内容。

  1. 脚本中 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) 检查页面加载时已存在的卡片。

  1. 代码中的优化点

节点类型检查:脚本通过 node.nodeType === Node.ELEMENT_NODE 过滤非元素节点(如文本节点),提高效率。

选择器检查:checkNode 使用 matches 和 querySelectorAll,确保只处理符合条件的元素。

去重逻辑:通过 hideCard 函数统一卡片移除逻辑,避免重复代码。

  1. 可能的改进

性能优化:如果页面变化频繁,可以限制观察范围(例如只观察某个容器如 div.Topstory-container),减少不必要的检查。

断开观察:在某些场景下(例如页面切换),可以通过 observer.disconnect() 停止观察以释放资源。

错误处理:添加 try-catch 块处理 DOM 操作中的潜在异常。

  1. 总结

MutationObserver 在脚本中用于实时监控知乎页面中的 DOM 变化,捕获动态加载的推荐卡片,并检查是否包含"盐选"相关内容。通过配置 childList 和 subtree,它能高效地覆盖整个页面,确保新插入的卡片被及时处理。结合初始检查,脚本实现了对静态和动态内容的全面覆盖,完美适配知乎的动态加载场景。

相关推荐
BillKu1 小时前
Vue3 + TypeScript中provide和inject的用法示例
javascript·vue.js·typescript
培根芝士1 小时前
Electron打包支持多语言
前端·javascript·electron
Baoing_1 小时前
Next.js项目生成sitemap.xml站点地图
xml·开发语言·javascript
沉默是金~2 小时前
Vue+Notification 自定义消息通知组件 支持数据分页 实时更新
javascript·vue.js·elementui
ohMyGod_1232 小时前
React-useRef
前端·javascript·react.js
每一天,每一步2 小时前
AI语音助手 React 组件使用js-audio-recorder实现,将获取到的语音转成base64发送给后端,后端接口返回文本内容
前端·javascript·react.js
上趣工作室2 小时前
vue3专题1------父组件中更改子组件的属性
前端·javascript·vue.js
getapi2 小时前
flutter app实现分辨率自适应的图片资源加载
前端·javascript·flutter
—Qeyser3 小时前
用 Deepseek 写的html油耗计算器
前端·javascript·css·html·css3·deepseek