您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
屏蔽首页广告及推广视频
// ==UserScript== // @name bilibili屏蔽首页推广 // @namespace https://github.com/strange-qwq/bilibili_blocks_homepage_ad // @version 1.0.0.20250419 // @description 屏蔽首页广告及推广视频 // @author QWQ // @match https://www.bilibili.com/ // @grant none // ==/UserScript== const hiddenDivClassName = 'hidden-div'; const hookApi = '/wbi/index/top/feed/rcmd'; let replaceEle = null; const originalXHR = window.XMLHttpRequest; const originalFetch = window.fetch; (function () { 'use strict'; // 方式一:Hook请求响应 hookHTTP(); // 由于请求可能在hook之前执行,所以此处需要手动隐藏一次,如果有大佬知道怎么优化,欢迎PR setTimeout(hiddenAdEl, 1000); // 方式二:替换广告盒子显示(缺点:如果在定时器中运行,滑动时其它视频会频繁出现位移现象,所以未启用) // setInterval(hiddenAdEl, 5000); })(); /** * Hook 函数 */ function hookHTTP() { window.XMLHttpRequest = function() { const xhr = new originalXHR(); // 重写open方法记录请求信息 const originalOpen = xhr.open; xhr.open = function(method, url) { this._requestUrl = url; originalOpen.apply(this, arguments); }; // 重写send方法拦截响应 const originalSend = xhr.send; xhr.send = function(body) { const self = this; this.addEventListener('readystatechange', function() { if (self.readyState === 4 && self.status === 200) { try { // 检查目标接口 if (this._requestUrl.includes(hookApi)) { const modifiedData = modifyResponse(JSON.parse(self.responseText)); Object.defineProperty(self, 'responseText', { writable: true, value: JSON.stringify(modifiedData) }); } } catch (e) { console.error('Response parse error:', e); } } }); originalSend.apply(this, arguments); }; return xhr; }; window.fetch = function(input, init) { return originalFetch.apply(this, arguments).then(response => { if (typeof input === 'string' && input.includes(hookApi)) { // 克隆响应以便修改 const clonedResponse = response.clone(); return clonedResponse.json().then(data => { const modifiedData = modifyResponse(data); return new Response( JSON.stringify(modifiedData), { headers: response.headers, status: response.status, statusText: response.statusText } ); }).catch(e => { console.error('Fetch response parse error:', e); return response; }); } return response; }); }; } /** * 过滤广告响应 */ function modifyResponse (data) { data.data.item = data.data.item.filter((it) => { if (it.goto === 'ad') return false; return true; }) return data; } /** * 隐藏广告盒子 * - 该函数有两种隐藏方式,你可以通过修改以下注释来切换运行方式 * - 方式一:隐藏广告盒子(缺点:如果在定时器中运行,滑动时其它视频会频繁出现位移现象) * - 方式二:遮挡广告盒子(缺点:不太好看) */ function hiddenAdEl() { let black = Array.from(document.querySelectorAll('.bili-video-card.is-rcmd')).filter((it) => Array.from(it.querySelectorAll('.bili-video-card__stats--text')).some((i) => { if (i.innerText === '广告') return true; return false; }) ); black.forEach((it) => { if (Array.from(it.parentElement.classList).includes('feed-card')) { black.push(it.parentElement); } }); black.push(...Array.from(document.querySelectorAll('.bili-video-card.is-rcmd:has(.vui_icon.bili-video-card__stats--icon)'))); // black = black.filter((it) => { // if (it.style.display === 'none') return false; // if (it.querySelector(hiddenDivClassName)) return false; // return true; // }); black.forEach((it) => { // it.style.display = 'none'; // it.appendChild(buildReplaceEle(it)); it.parentElement.removeChild(it); // console.log('hidden element =>', it); }); black = []; } /** * 构造广告盒子遮挡 */ function buildReplaceEle(el) { if (el) { el.style.opacity = 0.1; el.style.position = 'relative'; } if (replaceEle) { return replaceEle; } replaceEle = document.createElement('div'); replaceEle.classList.add(hiddenDivClassName); replaceEle.style.top = 0; replaceEle.style.left = 0; replaceEle.style.width = '100%'; replaceEle.style.height = '100%'; replaceEle.style.display = 'flex'; replaceEle.style.zIndex = Infinity; replaceEle.style.borderRadius = '12px'; replaceEle.style.position = 'absolute'; replaceEle.style.alignItems = 'center'; replaceEle.style.justifyContent = 'center'; const span = document.createElement('span'); span.innerText = '广告'; span.style.color = '#999999'; span.style.fontSize = '16px'; replaceEle.appendChild(span); // replaceEle.style.background = 'rgba(0, 0, 0, 0.5)'; return replaceEle; }