B站综合屏蔽插件

综合屏蔽管理:智能广告拦截、分类过滤、直播屏蔽、精准关键词过滤、推荐卡片删除

// ==UserScript==
// @name         B站综合屏蔽插件
// @namespace    http://tampermonkey.net/
// @version      4.2
// @description  综合屏蔽管理:智能广告拦截、分类过滤、直播屏蔽、精准关键词过滤、推荐卡片删除
// @author       YourName
// @match        *://www.bilibili.com/*
// @exclude      *://www.bilibili.com/video/*
// @icon         https://www.bilibili.com/favicon.ico
// @grant        GM_setValue
// @grant        GM_getValue 
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 全局配置系统
    const CONFIG = {
        video: {
            enabled: GM_getValue('videoEnabled', true),
            blacklist: GM_getValue('videoBlacklist', [])
        },
        category: {
            enabled: GM_getValue('categoryEnabled', true),
            blacklist: GM_getValue('categoryBlacklist', [
                '番剧', '直播', '国创', '综艺',
                '课堂', '电影', '电视剧', '纪录片',"漫画",
            ])
        },
        ad: GM_getValue('adEnabled', true),
        live: GM_getValue('liveEnabled', true),
        card: {
            enabled: GM_getValue('cardEnabled', true),
            targetFeature: '.vui_icon.bili-video-card__stats--icon'
        }
    };

    // 广告屏蔽模块 -------------------------------------------------
    const adKeywords = ['广告', 'Sponsored', '推广'];
    const adSelectors = [
        '.bili-video-card__stats--text',
        '.feed-card',
        '[data-report*="ad_card"]',
        '.bili-ad-card',
        '[ad-id]'
    ];

    function isAdElement(element) {
        return adKeywords.some(keyword =>
            element.textContent.includes(keyword) ||
            element.getAttribute('data-report')?.includes('ad') ||
            element.closest('[class*="ad"], [class*="Ad"]')
        );
    }

    function removeAd(element) {
        if (!CONFIG.ad) return;
        const adContainer = element.closest('.feed-card, .bili-video-card, .bili-grid') || element;
        if (adContainer) {
            adContainer.remove();
        }
    }

    function blockAds() {
        if (!CONFIG.ad) return;
        adSelectors.forEach(selector => {
            document.querySelectorAll(selector).forEach(element => {
                if (isAdElement(element)) removeAd(element);
            });
        });
    }

    // 分类屏蔽模块 -------------------------------------------------
    function blockCategories() {
        if (!CONFIG.category.enabled) return;

        document.querySelectorAll('.floor-single-card').forEach(card => {
            const categoryElement = card.querySelector('.floor-title');
            if (!categoryElement) return;

            const category = categoryElement.textContent.trim();
            const shouldBlock = CONFIG.category.blacklist.some(keyword =>
                category.includes(keyword)
            );

            if (shouldBlock) {
                card.remove();
            }
        });
    }

    // 视频关键词屏蔽模块 --------------------------------------------
    function blockVideos() {
        if (!CONFIG.video.enabled) return;

        document.querySelectorAll('.bili-video-card').forEach(video => {
            const title = video.querySelector('.bili-video-card__info--tit')?.textContent.trim() || '';
            const author = video.querySelector('.bili-video-card__info--author')?.textContent.trim() || '';

            const shouldBlock = CONFIG.video.blacklist.some(keyword =>
                title.includes(keyword) || author.includes(keyword)
            );

            if (shouldBlock) {
                video.remove();
            }
        });
    }

    // 直播屏蔽模块 -------------------------------------------------
    function blockLive() {
        if (!CONFIG.live) return;
        document.querySelectorAll('.live-card, .bili-live-card').forEach(card => {
            card.remove();
        });
    }

    // 推荐卡片屏蔽模块 -----------------------------------------------
    function blockRecommendCards() {
        if (!CONFIG.card.enabled) return;

        document.querySelectorAll(CONFIG.card.targetFeature).forEach(svg => {
            const card = svg.closest('.bili-video-card.is-rcmd');
            if (card) {
                card.remove();
            }
        });
    }

    // 主控制面板 -------------------------------------------------
    function createMainPanel() {
        const panel = document.createElement('div');
        panel.innerHTML = `
            <style>
                .master-panel {
                    position: fixed;
                    left: 50%;
                    top: 50%;
                    transform: translate(-50%, -50%);
                    background: rgba(255,255,255,0.98);
                    border-radius: 12px;
                    box-shadow: 0 8px 24px rgba(0,0,0,0.15);
                    padding: 20px;
                    width: 360px;
                    z-index: 10000;
                    backdrop-filter: blur(8px);
                }
                .panel-header {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    margin-bottom: 15px;
                }
                .close-btn {
                    cursor: pointer;
                    font-size: 20px;
                    color: #666;
                }
                .switch-item {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    margin: 12px 0;
                }
                .manage-btn {
                    color: #00a1d6;
                    cursor: pointer;
                    margin-left: 10px;
                }
                .switch {
                    position: relative;
                    display: inline-block;
                    width: 40px;
                    height: 20px;
                }
                .switch input {
                    opacity: 0;
                    width: 0;
                    height: 0;
                }
                .slider {
                    position: absolute;
                    cursor: pointer;
                    top: 0;
                    left: 0;
                    right: 0;
                    bottom: 0;
                    background-color: #ccc;
                    transition: .4s;
                    border-radius: 20px;
                }
                .slider:before {
                    position: absolute;
                    content: "";
                    height: 16px;
                    width: 16px;
                    left: 2px;
                    bottom: 2px;
                    background-color: white;
                    transition: .4s;
                    border-radius: 50%;
                }
                input:checked + .slider {
                    background-color: #00a1d6;
                }
                input:checked + .slider:before {
                    transform: translateX(20px);
                }
            </style>
            <div class="master-panel">
                <div class="panel-header">
                    <h3>智能屏蔽控制中心</h3>
                    <div class="close-btn">×</div>
                </div>
                <div class="switch-item">
                    <span>视频关键词屏蔽</span>
                    <div>
                        <label class="switch">
                            <input type="checkbox" ${CONFIG.video.enabled ? 'checked' : ''}>
                            <span class="slider"></span>
                        </label>
                        <span class="manage-btn" data-type="video">管理</span>
                    </div>
                </div>
                <div class="switch-item">
                    <span>分类屏蔽</span>
                    <div>
                        <label class="switch">
                            <input type="checkbox" ${CONFIG.category.enabled ? 'checked' : ''}>
                            <span class="slider"></span>
                        </label>
                        <span class="manage-btn" data-type="category">管理</span>
                    </div>
                </div>
                <div class="switch-item">
                    <span>广告屏蔽</span>
                    <label class="switch">
                        <input type="checkbox" ${CONFIG.ad ? 'checked' : ''}>
                        <span class="slider"></span>
                    </label>
                </div>
                <div class="switch-item">
                    <span>直播推荐屏蔽</span>
                    <label class="switch">
                        <input type="checkbox" ${CONFIG.live ? 'checked' : ''}>
                        <span class="slider"></span>
                    </label>
                </div>
                <div class="switch-item">
                    <span>推荐卡片屏蔽</span>
                    <label class="switch">
                        <input type="checkbox" ${CONFIG.card.enabled ? 'checked' : ''}>
                        <span class="slider"></span>
                    </label>
                </div>
            </div>
        `;

        panel.querySelectorAll('input[type="checkbox"]').forEach(checkbox => {
            checkbox.addEventListener('change', e => {
                const parentText = e.target.closest('.switch-item').querySelector('span').textContent;
                if (parentText.includes('视频关键词')) {
                    CONFIG.video.enabled = e.target.checked;
                    GM_setValue('videoEnabled', e.target.checked);
                    blockVideos();
                } else if (parentText.includes('分类')) {
                    CONFIG.category.enabled = e.target.checked;
                    GM_setValue('categoryEnabled', e.target.checked);
                    blockCategories();
                } else if (parentText.includes('广告')) {
                    CONFIG.ad = e.target.checked;
                    GM_setValue('adEnabled', e.target.checked);
                    blockAds();
                } else if (parentText.includes('直播')) {
                    CONFIG.live = e.target.checked;
                    GM_setValue('liveEnabled', e.target.checked);
                    blockLive();
                } else if (parentText.includes('推荐卡片')) {
                    CONFIG.card.enabled = e.target.checked;
                    GM_setValue('cardEnabled', e.target.checked);
                    blockRecommendCards();
                }
            });
        });

        panel.querySelectorAll('.manage-btn').forEach(btn => {
            btn.addEventListener('click', (e) => {
                e.stopPropagation();
                showManagementPanel(btn.dataset.type);
            });
        });

        panel.querySelector('.close-btn').addEventListener('click', () => {
            panel.style.display = 'none';
        });

        return panel;
    }

    // 关键词管理面板 -------------------------------------------------
    function showVideoPanel() {
        const panel = document.createElement('div');
        panel.innerHTML = `
            <style>
                .keyword-panel {
                    position: fixed;
                    left: 50%;
                    top: 50%;
                    transform: translate(-50%, -50%);
                    background: rgba(255,255,255,0.98);
                    border-radius: 12px;
                    box-shadow: 0 8px 24px rgba(0,0,0,0.15);
                    padding: 20px;
                    width: 400px;
                    z-index: 10001;
                    backdrop-filter: blur(8px);
                }
                .keyword-input-group {
                    display: flex;
                    gap: 10px;
                    margin-bottom: 15px;
                }
                .keyword-list {
                    max-height: 300px;
                    overflow-y: auto;
                    border-top: 1px solid #eee;
                }
            </style>
            <div class="keyword-panel">
                <div class="panel-header">
                    <h3 style="margin:0">视频关键词管理</h3>
                    <button class="close-btn">×</button>
                </div>
                <div class="stats">当前屏蔽关键词:<span id="keyword-count">${CONFIG.video.blacklist.length}</span> 个</div>
                <div class="keyword-input-group">
                    <input type="text" placeholder="输入要屏蔽的关键词" style="flex:1;padding:8px;">
                    <button class="add-btn" style="padding:8px 15px;background:#00a1d6;color:white;border:none;border-radius:4px;">
                        添加
                    </button>
                </div>
                <div class="keyword-list"></div>
            </div>
        `;

        const closeBtn = panel.querySelector('.close-btn');
        const input = panel.querySelector('input');
        const addBtn = panel.querySelector('.add-btn');
        const keywordList = panel.querySelector('.keyword-list');
        const countSpan = panel.querySelector('#keyword-count');

        function updateList() {
            keywordList.innerHTML = CONFIG.video.blacklist.map(word => `
                <div style="display:flex; justify-content:space-between; padding:8px; border-bottom:1px solid #eee;">
                    <span>${word}</span>
                    <button data-word="${word}" style="color:#ff6666;background:none;border:none;cursor:pointer;">
                        删除
                    </button>
                </div>
            `).join('');

            keywordList.querySelectorAll('button').forEach(btn => {
                btn.addEventListener('click', () => {
                    CONFIG.video.blacklist = CONFIG.video.blacklist.filter(w => w !== btn.dataset.word);
                    GM_setValue('videoBlacklist', CONFIG.video.blacklist);
                    countSpan.textContent = CONFIG.video.blacklist.length;
                    updateList();
                    blockVideos();
                });
            });
        }

        addBtn.addEventListener('click', () => {
            const keyword = input.value.trim();
            if (keyword && !CONFIG.video.blacklist.includes(keyword)) {
                CONFIG.video.blacklist.push(keyword);
                GM_setValue('videoBlacklist', CONFIG.video.blacklist);
                input.value = '';
                countSpan.textContent = CONFIG.video.blacklist.length;
                updateList();
                blockVideos();
            }
        });

        input.addEventListener('keypress', e => {
            if (e.key === 'Enter') addBtn.click();
        });

        closeBtn.addEventListener('click', () => {
            document.body.removeChild(panel);
        });

        updateList();
        document.body.appendChild(panel);
    }

    // 分类管理面板 -------------------------------------------------
    function showCategoryPanel() {
        const panel = document.createElement('div');
        panel.innerHTML = `
            <style>
                .category-panel {
                    position: fixed;
                    left: 50%;
                    top: 50%;
                    transform: translate(-50%, -50%);
                    background: rgba(255,255,255,0.98);
                    border-radius: 12px;
                    box-shadow: 0 8px 24px rgba(0,0,0,0.15);
                    padding: 20px;
                    width: 400px;
                    z-index: 10001;
                    backdrop-filter: blur(8px);
                }
                .category-input-group {
                    display: flex;
                    gap: 10px;
                    margin-bottom: 15px;
                }
                .category-list {
                    max-height: 300px;
                    overflow-y: auto;
                    border-top: 1px solid #eee;
                }
            </style>
            <div class="category-panel">
                <div class="panel-header">
                    <h3 style="margin:0">分类屏蔽管理</h3>
                    <button class="close-btn">×</button>
                </div>
                <div class="stats">当前屏蔽分类:<span id="category-count">${CONFIG.category.blacklist.length}</span> 个</div>
                <div class="category-input-group">
                    <input type="text" placeholder="输入要屏蔽的分类" style="flex:1;padding:8px;">
                    <button class="add-btn" style="padding:8px 15px;background:#00a1d6;color:white;border:none;border-radius:4px;">
                        添加
                    </button>
                </div>
                <div class="category-list"></div>
            </div>
        `;

        const closeBtn = panel.querySelector('.close-btn');
        const input = panel.querySelector('input');
        const addBtn = panel.querySelector('.add-btn');
        const categoryList = panel.querySelector('.category-list');
        const countSpan = panel.querySelector('#category-count');

        function updateList() {
            categoryList.innerHTML = CONFIG.category.blacklist.map(cat => `
                <div style="display:flex; justify-content:space-between; padding:8px; border-bottom:1px solid #eee;">
                    <span>${cat}</span>
                    <button data-cat="${cat}" style="color:#ff6666;background:none;border:none;cursor:pointer;">
                        删除
                    </button>
                </div>
            `).join('');

            categoryList.querySelectorAll('button').forEach(btn => {
                btn.addEventListener('click', () => {
                    CONFIG.category.blacklist = CONFIG.category.blacklist.filter(c => c !== btn.dataset.cat);
                    GM_setValue('categoryBlacklist', CONFIG.category.blacklist);
                    countSpan.textContent = CONFIG.category.blacklist.length;
                    updateList();
                    blockCategories();
                });
            });
        }

        addBtn.addEventListener('click', () => {
            const category = input.value.trim();
            if (category && !CONFIG.category.blacklist.includes(category)) {
                CONFIG.category.blacklist.push(category);
                GM_setValue('categoryBlacklist', CONFIG.category.blacklist);
                input.value = '';
                countSpan.textContent = CONFIG.category.blacklist.length;
                updateList();
                blockCategories();
            }
        });

        input.addEventListener('keypress', e => {
            if (e.key === 'Enter') addBtn.click();
        });

        closeBtn.addEventListener('click', () => {
            document.body.removeChild(panel);
        });

        updateList();
        document.body.appendChild(panel);
    }

    // 管理面板路由 -------------------------------------------------
    function showManagementPanel(type) {
        if (type === 'video') {
            showVideoPanel();
        } else if (type === 'category') {
            showCategoryPanel();
        }
    }

    // 初始化逻辑 -------------------------------------------------
    const observer = new MutationObserver(() => {
        blockAds();
        blockCategories();
        blockVideos();
        blockLive();
        blockRecommendCards();
    });

    // 浮动按钮
    const floatBtn = document.createElement('div');
    floatBtn.innerHTML = `
        <style>
            .master-float-btn {
                position: fixed;
                left: 30px;
                bottom: 100px;
                background: #00a1d6;
                color: white;
                padding: 12px 20px;
                border-radius: 25px;
                z-index: 9999;
                cursor: pointer;
                box-shadow: 0 4px 12px rgba(0,0,0,0.2);
                transition: transform 0.2s;
            }
            .master-float-btn:hover {
                transform: scale(1.05);
            }
        </style>
        <div class="master-float-btn">🛡️ 屏蔽控制</div>
    `;
    document.body.appendChild(floatBtn);

    // 主控制面板
    const mainPanel = createMainPanel();
    document.body.appendChild(mainPanel);
    mainPanel.style.display = 'none';

    floatBtn.querySelector('.master-float-btn').addEventListener('click', () => {
        mainPanel.style.display = mainPanel.style.display === 'none' ? 'block' : 'none';
    });

    // 启动监听
    observer.observe(document.body, { childList: true, subtree: true });
    setInterval(() => {
        blockAds();
        blockRecommendCards();
    }, 500);

    // 初始执行
    blockAds();
    blockCategories();
    blockVideos();
    blockLive();
    blockRecommendCards();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址