// ==UserScript== // @name 哔哩哔哩广告全面屏蔽 // @version 1.0 // @description 移除评论区横幅广告,并隐藏推荐流中带“广告”标识的视频卡片 // @author Assistant // @match *://*.bilibili.com/* // @icon https://www.bilibili.com/favicon.ico // @grant none // @run-at document-end // ==/UserScript== (function() { 'use strict'; // -------------------- 配置 -------------------- const LEFT_AD_SELECTOR = 'div.ad-report.strip-ad.left-banner'; // 评论区横幅广告选择器 const HIDE_MARKER = 'data-ad-hidden'; // 视频卡片隐藏标记 // -------------------- 1. CSS 立即隐藏左侧广告(避免闪现)-------------------- const style = document.createElement('style'); style.textContent = `${LEFT_AD_SELECTOR} { display: none !important; }`; document.head.appendChild(style); // -------------------- 2. 移除评论区横幅广告(动态删除)-------------------- function removeLeftAd() { document.querySelectorAll(LEFT_AD_SELECTOR).forEach(ad => ad.remove()); } // -------------------- 3. 隐藏带广告标识的视频卡片 -------------------- function isAdVideoCard(card) { // 查找卡片内的广告标识元素 const adLabel = card.querySelector('.bili-video-card__stats--text'); if (adLabel) { const text = adLabel.textContent.trim(); return /广告|推广|AD/i.test(text); } return false; } function hideAdVideoCard(card) { if (card.getAttribute(HIDE_MARKER) === 'true') return; card.style.display = 'none'; card.setAttribute(HIDE_MARKER, 'true'); } function hideVideoAdsInContainer(container) { if (!container) return; // 只在包含视频卡片的地方查找,提升性能 const cards = container.querySelectorAll('.bili-video-card'); cards.forEach(card => { if (card.getAttribute(HIDE_MARKER) !== 'true' && isAdVideoCard(card)) { hideAdVideoCard(card); } }); } // -------------------- 4. 统一处理新增节点(同时处理两种广告)-------------------- function processNewNode(node) { if (node.nodeType !== Node.ELEMENT_NODE) return; // 处理评论区横幅广告(全局扫描新增节点及其子节点) if (node.matches && node.matches(LEFT_AD_SELECTOR)) { node.remove(); } else { const leftAds = node.querySelectorAll(LEFT_AD_SELECTOR); leftAds.forEach(ad => ad.remove()); } // 处理视频广告卡片 hideVideoAdsInContainer(node); } // 全量扫描一次(页面初始加载时使用) function fullScanAndClean() { removeLeftAd(); // 移除评论区横幅广告 hideVideoAdsInContainer(document.body); // 隐藏所有广告视频卡片 } // -------------------- 5. 监听动态内容变化(滚动加载、路由切换等)-------------------- const observer = new MutationObserver(mutations => { let needFullScan = false; for (const mutation of mutations) { if (mutation.type === 'childList' && mutation.addedNodes.length) { // 遍历所有新增节点,分别处理 mutation.addedNodes.forEach(node => processNewNode(node)); needFullScan = true; } } // 简单防抖:如果有新增节点,再执行一次全量清理(确保遗漏的广告被处理) if (needFullScan) { // 延迟执行避免与直接删除冲突 setTimeout(() => { removeLeftAd(); hideVideoAdsInContainer(document.body); }, 50); } }); // 监听整个 body if (document.body) { observer.observe(document.body, { childList: true, subtree: true }); } else { window.addEventListener('DOMContentLoaded', () => { observer.observe(document.body, { childList: true, subtree: true }); }); } // -------------------- 6. SPA 路由变化额外保障(URL hash 或 history 变化)-------------------- let lastUrl = location.href; const urlObserver = new MutationObserver(() => { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(() => { fullScanAndClean(); }, 200); } }); urlObserver.observe(document, { subtree: true, childList: true }); // -------------------- 7. 启动时执行一次全面清理 -------------------- fullScanAndClean(); console.log('[哔哩哔哩广告屏蔽] 已启动,横幅广告 & 推荐流广告视频均已屏蔽'); })();