// ==UserScript== // @name 哔哩哔哩广告全面屏蔽 // @namespace https://github.com/yourname/bilibili-ad-blocker-enhanced // @version 1.3 // @description 屏蔽左侧横幅广告、推荐流广告视频、小型广告卡片(.video-card-ad-small),完全避开评论区 // @author Assistant // @match *://*.bilibili.com/* // @icon https://www.bilibili.com/favicon.ico // @grant none // @run-at document-end // ==/UserScript== (function() { 'use strict'; // ---------- 广告选择器 ---------- // 1. 左侧横幅广告 const LEFT_BANNER_AD_SELECTOR = 'div.left-container div.ad-report.strip-ad.left-banner, ' + '.bili-header__left-area .ad-report.strip-ad.left-banner'; // 2. 小型广告卡片(如右侧、底部的小广告) const SMALL_AD_CARD_SELECTOR = '.video-card-ad-small'; // 3. 推荐流容器(用于屏蔽其中的广告视频卡片) const FEED_CONTAINER_SELECTOR = '.bili-feed4, .feed-list, .bili-video-card-list, ' + '.recommend-container, .video-page-special'; // 评论区根容器(脚本不会处理这些容器内的任何元素) const COMMENT_ROOT_SELECTOR = '#comment-area, .comment-list-holder, .reply-list, ' + '.comment-container, .comment-list, .bili-comment'; const HIDE_MARKER = 'data-ad-hidden'; // ---------- 工具函数:判断元素是否在评论区内部 ---------- function isInsideCommentArea(element) { if (!element) return false; let node = element; while (node && node !== document.body) { if (node.nodeType === Node.ELEMENT_NODE && node.matches && node.matches(COMMENT_ROOT_SELECTOR)) { return true; } node = node.parentElement; } return false; } // ---------- 1. 屏蔽左侧横幅广告 ---------- function removeLeftBannerAd() { const ads = document.querySelectorAll(LEFT_BANNER_AD_SELECTOR); ads.forEach(ad => { if (!isInsideCommentArea(ad)) { ad.remove(); console.log('[广告屏蔽] 已移除左侧横幅广告', ad); } }); } // ---------- 2. 屏蔽小型广告卡片(.video-card-ad-small) ---------- function hideSmallAdCards() { const smallCards = document.querySelectorAll(SMALL_AD_CARD_SELECTOR); smallCards.forEach(card => { if (!isInsideCommentArea(card) && card.getAttribute(HIDE_MARKER) !== 'true') { card.style.display = 'none'; card.setAttribute(HIDE_MARKER, 'true'); console.log('[广告屏蔽] 已隐藏小型广告卡片', card); } }); } // ---------- 3. 屏蔽推荐流中的广告视频卡片(带“广告”文字) ---------- function isAdVideoCard(card) { const adLabel = card.querySelector('.bili-video-card__stats--text'); if (adLabel && /广告|推广|AD/i.test(adLabel.textContent.trim())) { return true; } return false; } function hideAdVideoCard(card) { if (card.getAttribute(HIDE_MARKER) === 'true') return; card.style.display = 'none'; card.setAttribute(HIDE_MARKER, 'true'); console.log('[广告屏蔽] 已隐藏广告视频卡片', card); } function hideVideoAdsInRecommended() { const containers = document.querySelectorAll(FEED_CONTAINER_SELECTOR); containers.forEach(container => { if (isInsideCommentArea(container)) return; const cards = container.querySelectorAll('.bili-video-card'); cards.forEach(card => { if (!isInsideCommentArea(card) && isAdVideoCard(card)) { hideAdVideoCard(card); } }); }); } // ---------- 统一清理入口 ---------- function fullClean() { removeLeftBannerAd(); hideSmallAdCards(); hideVideoAdsInRecommended(); } // ---------- 处理动态新增节点 ---------- function processNewNode(node) { if (node.nodeType !== Node.ELEMENT_NODE) return; if (isInsideCommentArea(node)) return; // 检查左侧广告 if (node.matches && node.matches(LEFT_BANNER_AD_SELECTOR)) { node.remove(); console.log('[广告屏蔽] 动态移除左侧广告', node); } else { const bannerAds = node.querySelectorAll(LEFT_BANNER_AD_SELECTOR); bannerAds.forEach(ad => { if (!isInsideCommentArea(ad)) { ad.remove(); console.log('[广告屏蔽] 动态移除子节点左侧广告', ad); } }); } // 检查小型广告卡片 if (node.matches && node.matches(SMALL_AD_CARD_SELECTOR)) { if (!isInsideCommentArea(node) && node.getAttribute(HIDE_MARKER) !== 'true') { node.style.display = 'none'; node.setAttribute(HIDE_MARKER, 'true'); console.log('[广告屏蔽] 动态隐藏小型广告卡片', node); } } else { const smallCards = node.querySelectorAll(SMALL_AD_CARD_SELECTOR); smallCards.forEach(card => { if (!isInsideCommentArea(card) && card.getAttribute(HIDE_MARKER) !== 'true') { card.style.display = 'none'; card.setAttribute(HIDE_MARKER, 'true'); console.log('[广告屏蔽] 动态隐藏子节点小型广告卡片', card); } }); } // 检查视频广告卡片(仅当新增节点是推荐流容器或其子节点包含推荐流容器) let needScanVideo = false; if (node.matches && node.matches(FEED_CONTAINER_SELECTOR)) { needScanVideo = true; } else if (node.querySelector && node.querySelector(FEED_CONTAINER_SELECTOR)) { needScanVideo = true; } if (needScanVideo) { setTimeout(() => hideVideoAdsInRecommended(), 50); } } // ---------- MutationObserver 监听页面变化 ---------- const observer = new MutationObserver(mutations => { let hasAddedNodes = false; for (const mutation of mutations) { if (mutation.type === 'childList' && mutation.addedNodes.length) { mutation.addedNodes.forEach(node => processNewNode(node)); hasAddedNodes = true; } } if (hasAddedNodes) { // 二次清理,确保遗漏的广告被处理 setTimeout(() => { removeLeftBannerAd(); hideSmallAdCards(); hideVideoAdsInRecommended(); }, 100); } }); if (document.body) { observer.observe(document.body, { childList: true, subtree: true }); } else { window.addEventListener('DOMContentLoaded', () => { observer.observe(document.body, { childList: true, subtree: true }); }); } // ---------- SPA 路由变化辅助 ---------- let lastUrl = location.href; const urlObserver = new MutationObserver(() => { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(fullClean, 200); } }); urlObserver.observe(document, { subtree: true, childList: true }); // 启动清理 fullClean(); console.log('[哔哩哔哩广告屏蔽] 增强版已启动 | 左侧横幅 + 小型广告卡片 + 推荐流广告视频均已屏蔽,评论区完全不受影响'); })();