// ==UserScript== // @name 优化斗鱼web播放器 // @namespace https://www.liebev.site/monkey/better-douyu // @version 2.3.1 // @description douyu优化斗鱼web播放器(douyu.com),通过关闭直播间全屏时的背景虚化效果来解决闪屏卡顿的问题,屏蔽独立直播间的弹幕显示,移除文字水印,添加了一些快捷键。暴力隐藏页面元素,获得纯净观看体验 // @author LiebeV // @license MIT: Copyright (c) 2023-2025 LiebeV // @match https://www.douyu.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=douyu.com // @grant GM_registerMenuCommand // @grant GM_getValue // @grant GM_setValue // @downloadURL https://update.greasyfork.icu/scripts/461630/%E4%BC%98%E5%8C%96%E6%96%97%E9%B1%BCweb%E6%92%AD%E6%94%BE%E5%99%A8.user.js // @updateURL https://update.greasyfork.icu/scripts/461630/%E4%BC%98%E5%8C%96%E6%96%97%E9%B1%BCweb%E6%92%AD%E6%94%BE%E5%99%A8.meta.js // ==/UserScript== "use strict"; //更新日志,v2.3.1,提高了弹幕屏蔽css优先级 //**NOTE**:之于页面上其他不想要看到的东西,请搭配其他例如AdBlock之类的专业广告屏蔽器使用,本脚本仅提供暴力隐藏的功能 //**NOTE**:暴力隐藏无法撤销,请刷新网页以恢复 //已知问题,暴力重写导致的各种问题 //更新计划,无 // ********************一些有的没的的变量************************* const roomIds = GM_getValue("roomIds", []); const userRoomIds = roomIds; const listenerMap = new Map([ ["l", () => Danmu_control.rewrite_danmu_css()], ["u", () => Player_control.switch_full_mode()], ["w", () => Player_control.switch_wide_mode()], ["k", () => Force_hide.force_clean_hide()], ["m", () => Better_multi.better_multi_mode()], ]); const target_xpath = "/html/body/section/main/div[4]/div[1]/div[4]"; const TBN = "疑似金色悬停骑士团开播提醒:div.broadcastDiv-af5699/疑似周活跃榜提醒:div.DanmuEffectDom-container#douyu_room_normal_player_danmuDom>"; //
//
本房勇士团完成勇士团补给任务,获得1.2万流量卡(1天)X1,额外4500点战力点
//
//
最强勇士团礼物冠名主播过载十五岁的涛妹开播了!点击围观吧!
// ************************************************************** // 弹幕相关操作 class DanmuControl { constructor() { this.liebev = document.querySelector("#LiebeV"); } // 创建新的去背景虚化css(似乎现在只在某些分区保留了这个效果) with_danmu_css = () => { // 没有隐藏弹幕相关 return ` ._1Osm4fzGmcuRK9M8IVy3u6, .watermark-442a18, .is-ybHotDebate, .view-67255d.zoomIn-0f4645 { visibility: hidden !important; } .Barrage-main, .Barrage-topFloater, .comment-37342a { display: unset !important; } `; }; without_danmu_css = () => { // 隐藏了弹幕相关 return ` ._1Osm4fzGmcuRK9M8IVy3u6, .watermark-442a18, .is-ybHotDebate, .view-67255d.zoomIn-0f4645 { visibility: hidden !important; } .Barrage-main, .Barrage-topFloater, .comment-37342a { display: none !important; } `; }; /** * 将传入的 CSS 字符串解析后,直接以行内样式的方式应用到匹配到的元素上 * @param {string} cssText - 完整的 CSS 文本,例如:".foo{color:red !important} .bar{display:none !important}" */ applyInlineCss = (cssText) => { // 简易切分:先按 } 分割成多个规则片段 let ruleSegments = cssText.split("}"); ruleSegments.forEach(segment => { // 去掉首尾多余空白 segment = segment.trim(); if (!segment) return; // 再按 { 分割,前半部分是选择器(可能逗号分隔多组),后半部分是具体样式 let [selectorPart, stylePart] = segment.split("{"); if (!selectorPart || !stylePart) return; // 处理选择器,可能是多选择器逗号分隔 let selectors = selectorPart.split(","); // 处理style声明,可能有多条用 ; 分隔 let styleStr = stylePart.trim().replace(/;$/, ""); let styleArr = styleStr.split(";"); // 存储解析后的 [属性, 值, 是否important] let styleList = []; styleArr.forEach(s => { s = s.trim(); if (!s) return; // 以冒号切分 let [prop, val] = s.split(":"); if (!prop || !val) return; prop = prop.trim(); val = val.trim(); // 如果带了 !important 标记,就分离出来 let important = false; if (val.includes("!important")) { important = true; // 去除 !important val = val.replace(/!important\s*/i, "").trim(); } styleList.push({ prop, val, important }); }); // 将解析好的样式列表应用到匹配的每个元素的行内样式上 selectors.forEach(sel => { sel = sel.trim(); if (!sel) return; // querySelectorAll 找到该选择器对应的所有元素 let elements = document.querySelectorAll(sel); elements.forEach(el => { styleList.forEach(styleObj => { // 这里利用 style.setProperty(prop, val, priority) 来支持 !important el.style.setProperty(styleObj.prop, styleObj.val, styleObj.important ? "important" : ""); }); }); }); }); }; // 插入新的css(现改为调用 applyInlineCss,以提升优先级到行内样式) update_css = (tobe_css) => { // 可以保留或移除原有