// ==UserScript== // @name bilinovel // @namespace http://tampermonkey.net/ // @version 1.3 // @description 去除bilinovel检测到屏蔽后隐藏内容 // @author karl // @match https://www.bilinovel.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=bilinovel.com // @license GPLv3 // @downloadURL none // ==/UserScript== (function() { 'use strict'; // --- 函数:处理单个元素 --- // 封装处理逻辑,方便复用 function processElement(element) { if (element.classList.contains('adv-box')) { console.log('猴油脚本:处理元素,移除 adv-box 类并清除 display 样式。', element); // 从元素的类列表中移除 'adv-box' 类 element.classList.remove('adv-box'); } // 检查并移除内联的 display: none 样式 // 即使 adv-box 类已经被移除,也可能仍有 display: none if (element.style.display === 'none') { console.log('猴油脚本:发现内联 display:none,清除它。', element); // 将 display 设置为空字符串,让浏览器决定默认显示方式 element.style.display = ''; // 或者,如果你确定要移除整个 style 属性(如果只有 display:none) // element.removeAttribute('style'); // 但设置 display = '' 更安全,因为它不影响其他可能的内联样式 } } // --- 初始页面加载时处理 --- // 选择所有同时具有 'adv-box' 和 'contente' 类的元素 const initialElements = document.querySelectorAll('.adv-box.contente'); if (initialElements.length > 0) { console.log(`猴油脚本 (初始加载):发现 ${initialElements.length} 个匹配元素。`); initialElements.forEach(processElement); // 对每个找到的元素执行处理函数 } else { console.log('猴油脚本 (初始加载):未发现 .adv-box.contente 元素。'); } // --- 处理动态加载的内容 --- const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.addedNodes) { mutation.addedNodes.forEach(node => { // 确保是元素节点 if (node.nodeType === 1) { // 检查新添加的节点本身是否匹配 if (node.matches('.adv-box.contente')) { console.log('猴油脚本 (Observer):发现新添加的匹配元素。'); processElement(node); // 处理这个新节点 } // 检查新添加的节点内部是否包含匹配的元素 // 注意:这里选择器仍然用 .adv-box.contente,因为 processElement 会处理类和样式 const newInternalElements = node.querySelectorAll('.adv-box.contente'); if (newInternalElements.length > 0) { console.log(`猴油脚本 (Observer):发现 ${newInternalElements.length} 个新元素内部的匹配项。`); newInternalElements.forEach(processElement); // 处理这些内部元素 } // --- 新增检查:有时元素已存在但被动态添加了 'adv-box' 类或 'display:none' --- // 这个观察器主要监听节点添加,但有时类或样式是动态修改的。 // 如果需要监听属性变化(比如 style 或 class),需要调整 observer.observe 的配置 // 但对于 display:none,通常是和元素添加或类添加一起发生的,所以上面的检查可能足够。 // 如果元素已存在,只是 style 被设为 none,则需要 Attribute 监听(见下方说明) } }); } // --- 可选:监听属性变化 --- // 如果元素已经存在于页面上,只是 style 属性被动态设置为 "display: none;" // 或者 'adv-box' 类被动态添加,你需要监听 'attributes' /* if (mutation.type === 'attributes' && mutation.attributeName === 'style') { const targetElement = mutation.target; // 检查目标元素是否是我们关心的(有 contente 类,并且 style 变成了 display:none) if (targetElement.classList.contains('contente') && targetElement.style.display === 'none') { console.log('猴油脚本 (Observer - Attr):检测到 style="display:none;" 被添加到 .contente 元素。'); processElement(targetElement); // 尝试处理它(移除 adv-box 和 display:none) } } if (mutation.type === 'attributes' && mutation.attributeName === 'class') { const targetElement = mutation.target; // 检查目标元素是否是我们关心的(现在同时有了 adv-box 和 contente) if (targetElement.matches('.adv-box.contente')) { console.log('猴油脚本 (Observer - Attr):检测到 class="adv-box" 被添加到 .contente 元素。'); processElement(targetElement); } } */ }); }); // 配置观察器: // childList: true - 观察子节点的添加或删除 // subtree: true - 观察所有后代节点,而不仅仅是直接子节点 // --- 如果需要监听属性变化,取消下面的注释 --- // attributes: true, // attributeFilter: ['style', 'class'] // 只关心 style 和 class 属性的变化,提高效率 const observerConfig = { childList: true, subtree: true, // attributes: true, // 取消注释以监听属性变化 // attributeFilter: ['style', 'class'] // 可选,优化性能 }; observer.observe(document.body || document.documentElement, observerConfig); console.log('猴油脚本:初始化完成,开始监控页面变化。'); })();