Greasy Fork

Greasy Fork is available in English.

微博知乎B站小红书关键词屏蔽器

屏蔽微博、知乎、小红书、B站含关键词的内容

当前为 2025-07-20 提交的版本,查看 最新版本

// ==UserScript==
// @name         微博知乎B站小红书关键词屏蔽器
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  屏蔽微博、知乎、小红书、B站含关键词的内容
// @author       KasenRi
// @match        https://www.zhihu.com/
// @match        https://www.xiaohongshu.com/*
// @match        https://www.bilibili.com/
// @match        https://www.bilibili.com/?*
// @match        https://www.bilibili.com/v/*
// @match        https://search.bilibili.com/*
// @match        https://weibo.com/*
// @match        https://www.weibo.com/*
// @match        https://s.weibo.com/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// @license      MIT
// ==/UserScript==

/*
 * 开源Fork声明 / Open Source Fork Declaration
 * 
 * 本脚本基于以下原始作品二次开发而成:
 * This script is forked and merged from the following original works:
 * 
 * 1. 知乎屏蔽词修改器
 *    作者/Author: 三无用户
 *    来源/Source: https://www.zhihu.com/question/1920892831981106398/answer/1928760410783343183
 *    
 * 2. 微博/B站/小红书屏蔽器
 *    作者/Author: Andante  
 *    来源/Source: https://www.zhihu.com/question/1920892831981106398/answer/1929126813218631948
 *    
 * 感谢原作者的贡献!
 * Thanks to the original authors for their contributions!
 * 
 * 本脚本采用MIT许可证开源
 * This script is open-sourced under MIT License
 */

(function() {
    'use strict';

    // 统一的屏蔽关键词列表
    const BLOCK_KEYWORDS = [
        '男','女','父亲','母亲','大龄剩女','男性','女性','coser','儿子','体育生',
        '女儿','迪士尼','盲盒','奶茶','COSER','漫展','小孩','结婚','生娃','华为',
        '大龄女','大妈','单亲','女生','美女','女神','小姐姐','男子','女演员',
        '健身房','JK','身材','985','211','小米','妈','妈妈','生物爹','原生家庭',
        '今日俄罗斯'
    ];

    // 获取当前网站类型
    function getCurrentSite() {
        const hostname = window.location.hostname;
        if (hostname.includes('zhihu.com')) return 'zhihu';
        if (hostname.includes('xiaohongshu.com')) return 'xiaohongshu';
        if (hostname.includes('bilibili.com')) return 'bilibili';
        if (hostname.includes('weibo.com')) return 'weibo';
        return 'unknown';
    }

    // 网站特定的配置
    const siteConfigs = {
        zhihu: {
            containerSelector: '.ContentItem',
            titleSelector: '.ContentItem-title a',
            logPrefix: '已屏蔽知乎问题'
        },
        xiaohongshu: {
            containerSelector: 'section.note-item',
            titleSelector: 'a.title, .title',
            logPrefix: '已屏蔽小红书内容'
        },
        bilibili: {
            containerSelector: '.bili-feed-card, .bili-video-card',
            titleSelector: '.bili-video-card__info--tit, .bili-video-card__info--tit a, .bili-video-card__wrap .bili-video-card__info--tit',
            logPrefix: '已屏蔽B站内容'
        },
        weibo: {
            containerSelector: '.wbpro-scroller-item',
            titleSelector: '.wbpro-feed-content .detail_wbtext_4CRf9',
            logPrefix: '已屏蔽微博内容'
        }
    };

    // 处理单个内容元素
    function processContentElement(element, config) {
        const site = getCurrentSite();
        
        // B站特殊处理:检测反屏蔽提示并删除
        if (site === 'bilibili') {
            // 检测反屏蔽box:有"bili-video-card is-rcmd"但没有"enable-no-interest"
            if (element.classList.contains('bili-video-card') && 
                element.classList.contains('is-rcmd') && 
                !element.classList.contains('enable-no-interest')) {
                
                // 查找上级容器并删除
                let targetContainer = element.closest('.feed-card') || element.closest('.bili-feed-card');
                
                if (targetContainer) {
                    targetContainer.remove();
                    console.log(`${config.logPrefix}: 反屏蔽提示 (删除整个容器)`);
                } else {
                    element.remove();
                    console.log(`${config.logPrefix}: 反屏蔽提示 (删除元素)`);
                }
                return;
            }
        }
        
        const titleElement = element.querySelector(config.titleSelector);
        let title = '';
        
        if (titleElement) {
            title = titleElement.textContent.trim();
        } else {
            // 兜底查找整个元素文本
            title = element.textContent.trim();
        }
        
        // 检查是否包含屏蔽关键词
        if (BLOCK_KEYWORDS.some(keyword => title.includes(keyword))) {
            let containerRemoved = false;
            
            // 针对不同网站的特殊处理:删除整个容器
            if (site === 'zhihu') {
                // 向上查找Card容器
                let cardElement = element.closest('.Card.TopstoryItem.TopstoryItem-isRecommend');
                if (cardElement) {
                    cardElement.remove();
                    console.log(`${config.logPrefix}: ${title} (删除整个卡片)`);
                    containerRemoved = true;
                }
            } else if (site === 'bilibili') {
                // 向上查找B站容器,同时检测feed-card和bili-feed-card
                let feedCardElement = element.closest('.feed-card') || element.closest('.bili-feed-card');
                if (feedCardElement) {
                    feedCardElement.remove();
                    console.log(`${config.logPrefix}: ${title} (删除整个B站容器)`);
                    containerRemoved = true;
                }
            } else if (site === 'xiaohongshu') {
                // 向上查找note-item容器
                let noteItemElement = element.closest('.note-item');
                if (noteItemElement) {
                    noteItemElement.remove();
                    console.log(`${config.logPrefix}: ${title} (删除整个note-item)`);
                    containerRemoved = true;
                }
            }
            
            // 如果没找到特定容器或其他网站,使用原来的隐藏方式
            if (!containerRemoved) {
                element.style.display = 'none';
                console.log(`${config.logPrefix}: ${title} (隐藏元素)`);
            }
        }
    }

    // 处理所有内容元素
    function processAllContent() {
        const site = getCurrentSite();
        const config = siteConfigs[site];
        
        if (!config) {
            console.log('未支持的网站:', window.location.hostname);
            return;
        }
        
        document.querySelectorAll(config.containerSelector).forEach(element => {
            processContentElement(element, config);
        });
    }

    // 防抖处理函数
    function debounce(func, wait) {
        let timeout;
        return function(...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func(...args), wait);
        };
    }

    const debouncedProcessAllContent = debounce(processAllContent, 500);

    // 初始化处理
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', processAllContent);
    } else {
        processAllContent();
    }
    window.addEventListener('load', processAllContent);

    // 监听DOM变化
    const observer = new MutationObserver(mutations => {
        const site = getCurrentSite();
        const config = siteConfigs[site];
        if (!config) return;
        
        let shouldProcess = false;
        mutations.forEach(mutation => {
            if (mutation.addedNodes.length) {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1) {
                        if (node.matches && node.matches(config.containerSelector)) {
                            processContentElement(node, config);
                        } else if (node.querySelectorAll) {
                            const elements = node.querySelectorAll(config.containerSelector);
                            if (elements.length > 0) {
                                shouldProcess = true;
                                elements.forEach(element => processContentElement(element, config));
                            }
                        }
                    }
                });
            }
        });
        
        if (shouldProcess) debouncedProcessAllContent();
    });

    observer.observe(document.body, { childList: true, subtree: true });

    // 滚动事件监听
    let scrollTimeout;
    window.addEventListener('scroll', () => {
        clearTimeout(scrollTimeout);
        scrollTimeout = setTimeout(debouncedProcessAllContent, 1000);
    }, { passive: true });

    // 定时扫描
    setInterval(processAllContent, 5000);

    console.log(`四平台关键词屏蔽器已启动,当前网站: ${getCurrentSite()}`);
})();