b站屏蔽增强器

根据用户名、uid、视频关键词、言论关键词和视频时长进行屏蔽和精简处理(详情看脚本主页描述),

目前为 2023-03-08 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name b站屏蔽增强器
  3. // @namespace http://tampermonkey.net/
  4. // @license MIT
  5. // @version 1.0.4
  6. // @description 根据用户名、uid、视频关键词、言论关键词和视频时长进行屏蔽和精简处理(详情看脚本主页描述),
  7. // @author byhgz
  8. // @exclude *://message.bilibili.com/pages/nav/header_sync
  9. // @match https://www.bilibili.com/v/channel/*?tab=multiple
  10. // @match *://search.bilibili.com/*
  11. // @match *://www.bilibili.com/v/channel/*
  12. // @match *://message.bilibili.com/*
  13. // @match *://www.bilibili.com/read/*
  14. // @match *://www.bilibili.com/v/topic/detail/?topic_id=*
  15. // @match *://t.bilibili.com/*
  16. // @match *://space.bilibili.com/*
  17. // @match *://www.bilibili.com/video/*
  18. // @match *://live.bilibili.com/*
  19. // @match https://www.bilibili.com/
  20. // @icon https://static.hdslb.com/images/favicon.ico
  21. // @grant none
  22. // ==/UserScript==
  23.  
  24. /**
  25. * 用户名黑名单模式
  26. * 提示越靠前的优先匹配
  27. * 例子,我想要屏蔽用户名叫张三的,内容两边加上“,如下所示
  28. * ["张三"]
  29. * 如追加在后面添加即可
  30. * ["张三","李四"]
  31. * @type {string[]} 元素类型为字符串
  32. */
  33. const userNameArr = [];
  34. /**
  35. * 用户uid黑名单模式
  36. * 提示越靠前的优先匹配
  37. * 比如我想要想要根据某个用户的UID进行屏蔽,则填写纯数字即可,不用加UID,如:
  38. * [114514]
  39. * 多个就
  40. * [114514,1433223]
  41. * @type {number[]}
  42. */
  43. const userUIDArr = [442010132, 76525078, 225219967, 3493106108337121, 432029920, 522828809, 15361927, 1514545, 1463474700, 473602930, 360222848, 34478056, 443966044, 365370701,
  44. 204223199, 108634479, 358982641, 1767883966, 9320658, 17342567, 485654692, 396597257, 365286131, 1373727295, 28705497, 69863283, 1273154216, 25193763, 45904574, 4119763,
  45. 436925164, 2080706333, 18149131, 137366696, 678222997, 321483542, 166415666, 3991821, 10965947, 2112669666, 516973583, 18746429, 18207363, 1758985928, 324638729, 97777331,
  46. 3461562092226886, 267309707, 1486867541, 1354324997, 381282127, 677946461, 34706053, 454731473, 1549857739, 648386152, 1543151814, 313692620, 498139921, 250473047, 551208674,
  47. 355864845, 403099700, 310049630, 396088710, 816408, 244830863, 1849036165, 433761998, 407470895, 494905797, 15290294, 492714942, 1508604210, 1059098601, 1057671967, 108145926,
  48. 17016234, 35374392, 347017348, 33069452, 510854520, 376257755, 14934048, 570365721, 247006155, 3812, 1153772186, 296539, 2117160, 1428464, 421706, 281239563, 27537451, 29660334,
  49. 412930970, 26823187, 5216704, 448091880, 17460940, 1261836580, 174945001, 182976969, 426820673, 490592134, 198402204, 1281412061, 65976968, 40648072, 141151718, 1992255481, 11624471,
  50. 1754181364, 196384402, 66367787, 128154158, 169545694, 5357279, 1152060393, 2038765, 3688216, 111220485, 6976808, 2346313, 28236100, 18227521, 440750397, 33309913, 280697705,
  51. 209324033, 488235430, 356479827, 1670897182, 177701043, 37652547, 125580767, 514090617, 50649550, 163969773, 509539484, 272571655, 473638012, 455144859, 34569089, 648428269,
  52. 43681957, 1715662667, 479377752, 238366138, 12475509, 29346851, 321253774, 89615638, 891858, 1301805267, 3529427, 243818176, 171384131, 11587623, 480266307, 450546148, 486810195,
  53. 430440081, 1242975719, 28263772, 507566, 22017278, 26287223, 245666267, 260548595, 180078002, 158597892, 363168957, 160905064, 35918416, 2073698, 54887854, 2785997, 441304288,
  54. 453875195, 304367432, 665571562, 359776394, 236691671, 435301455, 693055791, 1579905799, 617472671, 627472210, 1664466071, 188817014, 43417886, 177362409, 290792970, 167486665,
  55. 52675587, 308174482, 286366141, 115496626, 516585427, 7407869, 21971309, 168618448, 163524651, 162007026, 300630871, 89015953, 10155123, 1360533588, 73149130, 8284785, 34774578,
  56. 14493378, 58242864, 282462500, 35989854, 252953029, 9015499, 38269762, 45048267, 87369426, 3222715, 397883721, 324460860, 7856986, 161782912, 38377537, 433207409, 497415994, 26366366,
  57. 68559, 326499679, 398977139, 401000486, 45320548, 10479363, 393196002, 382806584, 284141005, 355076532, 525007481, 396438095, 396773226, 49771321, 360978058, 393471511, 381431441,
  58. 3493087556930157, 27534330, 401742377, 29668335, 17065080, 101157782, 3493144377166772, 363264911, 27825218, 511045567, 16683163];
  59.  
  60. /**
  61. * 视频标题or专栏标题关键词
  62. * 关键词小写,会有方法对内容中的字母转成小写的
  63. * 提示越靠前的优先匹配
  64. * 说明:比如某个视频有个张三关键词,你想要屏蔽张三关键词的旧如下所示例子,添加关键的地方即可,如果有多个就,按照下面例子中添加,即可,如果有两个类似的,靠左边的优先匹配到
  65. * @type {string[]}
  66. */
  67. const titleArr = ["感觉不如", "对标原神", "原神", "米哈游", "腾讯", "薄纱", "空大佐", "抄袭", "崩坏", "崩三", "塔塔开"];
  68. /**
  69. * 评论关键词
  70. * 关键词小写,会有方法对内容中的字母转成小写的
  71. * 提示越靠前的优先匹配
  72. * 同理跟上面标题关键词一样,只不过作用地方是在评论
  73. * @type {string[]}
  74. */
  75. const commentOnKeyArr = ["感觉不如", "有趣", "原神", "幻塔", "差不多的了", "你说得对", "op", "百万", "腾讯", "网易", "米哈游", "薄纱", "卫兵", "空大佐", "抄袭", "崩坏", "崩三", "塔塔开"];
  76.  
  77. /**
  78. * 专栏关键词
  79. * 关键词小写,会有方法对内容中的字母转成小写的
  80. * 提示越靠前的优先匹配
  81. * 同理跟上面标题关键词一样,只不过作用地方是在评论
  82. * @type {string[]}
  83. */
  84. const contentColumnKeyArr = ["抄袭"];
  85. /**
  86. * 粉丝牌
  87. * 根据粉丝牌屏蔽
  88. * 提示越靠前的优先匹配
  89. * @type {string[]}
  90. */
  91. const fanCardKeyArr = [];
  92.  
  93. /**
  94. *设置时长最小值,单位秒
  95. * 设置为 0,则不需要根据视频时长过滤
  96. * 说明,比如我先过滤60秒以内的视频,即60以内的视频都会被屏蔽掉,限定允许出现的最小时长
  97. * 可以这样填写
  98. * 5*60
  99. * 上面例子意思就是5分钟,同理想要6分钟就6*60,想要精确控制到秒就填写对应秒数即可
  100. * @type {number}
  101. */
  102. const filterSMin = 0;
  103.  
  104. /**
  105. * 设置时长最大值,单位秒
  106. * 设置为 0,则不需要根据视频时长过滤
  107. * 说明,允许出现的最大视频时长,超出该时长的都会被屏蔽掉,限定允许出现的最大时长
  108. * 可以这样填写
  109. * 5*60
  110. * 上面例子意思就是5分钟,同理想要6分钟就6*60,想要精确控制到秒就填写对应秒数即可
  111. * @type {number}
  112. */
  113. const filterSMax = 0;
  114.  
  115. //是否屏蔽首页=左侧大图的轮播图,反之false
  116. const homePicBool = true;
  117. //是否屏蔽首页右侧悬浮的按钮,其中包含反馈,内测等等之类的,反之false
  118. const paletteButtionBool = true;
  119.  
  120.  
  121. /**
  122. *直播间的相关配置信息
  123. */
  124. const liveData = {
  125. //是否移除直播间底部的全部信息,包括动态和主播公告和简介及荣誉
  126. bottomElement: true,
  127. //移除直播间顶部的信息(包括顶部标题栏)
  128. topElement: false,
  129. //是否移除直播间底部的的简介和主播荣誉
  130. bottomIntroduction: false,
  131. //是否移除直播间的主播公告布局
  132. container: false,
  133. /**
  134. * 是否屏蔽直播间底部动态
  135. */
  136. liveFeed: false
  137. }
  138.  
  139.  
  140. /**
  141. * 是否正在执行清理首页中的零散的直播间元素函数
  142. * @type {boolean}
  143. */
  144. let boolShieldMainlive = false;
  145.  
  146. /**
  147. * 保准页面加载了本脚本之后只会触发一次该判断
  148. * 用于搜索页面的专栏按钮监听。且只会加载一次
  149. * @type {boolean}
  150. */
  151. let searchColumnBool = false;
  152.  
  153.  
  154. /**
  155. * 获取当前网页的url
  156. * @returns {string}
  157. */
  158. function getWindowUrl() {
  159.  
  160. return window.location.href;
  161. }
  162.  
  163. /**
  164. * 根据用户提供的网页元素和对应的数组及key,判断数组里是否包含key元素本身,进行屏蔽元素
  165. * @param element
  166. * @param arr 数组
  167. * @param key 唯一key
  168. * @returns {boolean}
  169. */
  170. function shieldArrKey(element, arr, key) {
  171. if (arr.includes(key)) {
  172. element.remove();
  173. return true;
  174. }
  175. return false;
  176. }
  177.  
  178. /**
  179. * 根据用户uid屏蔽元素
  180. * @param element 网页元素
  181. * @param uid 用户uid
  182. * @returns {boolean}
  183. */
  184. function shieldUID(element, uid) {
  185. return shieldArrKey(element, userUIDArr, uid);
  186. }
  187.  
  188. /**
  189. *根据用户名屏蔽元素
  190. * @param element 网页元素
  191. * @param name 用户名
  192. * @returns {boolean}
  193. */
  194. function shieldName(element, name) {
  195. return shieldArrKey(element, userNameArr, name);
  196. }
  197.  
  198. /**
  199. * 根据用户提供的字符串集合,与指定内容进行比较屏蔽
  200. * @param element 网页元素
  201. * @param arr 字符串数组
  202. * @param content 内容
  203. * @returns {null|String}
  204. */
  205. function shieldArrContent(element, arr, content) {
  206. for (let str of arr) {
  207. if (content.toLowerCase().includes(str)) {//将内容中的字母转成小写进行比较
  208. element.remove();
  209. return str;
  210. }
  211. }
  212. return null;
  213. }
  214.  
  215. /**
  216. * 根据用户言论屏蔽元素
  217. * @param element 网页元素
  218. * @param content 用户的言论
  219. * @returns {string|null}
  220. */
  221. function shieldContent(element, content) {
  222. return shieldArrContent(element, commentOnKeyArr, content);
  223. }
  224.  
  225. /**
  226. * 根据用户专栏内容关键词屏蔽元素
  227. * @param element 网页元素
  228. * @param content 专栏内容关键词
  229. * @returns {string|null}
  230. */
  231. function shieldColumnContent(element, content) {
  232. return shieldArrContent(element, contentColumnKeyArr, content);
  233. }
  234.  
  235. /**
  236. * 根据标题屏蔽元素
  237. * @param element 网页元素
  238. * @param title 标题
  239. * @returns {string|null}
  240. */
  241. function shieldTitle(element, title) {
  242. for (let str of titleArr) {
  243. if (title.toLowerCase().includes(str)) {//将内容中的字母转成小写进行比较
  244. element.remove();
  245. return str;
  246. }
  247. }
  248. return null;
  249. }
  250.  
  251. /**
  252. * 根据用户粉丝牌进行屏蔽
  253. * @param element 网页元素
  254. * @param key
  255. * @returns {boolean}
  256. */
  257. function shieldFanCard(element, key) {
  258. return shieldArrKey(element, fanCardKeyArr, key);
  259. }
  260.  
  261. /**
  262. * 限制可展示的视频时长最小值,低于该值的都屏蔽
  263. * 根据视频时长,过滤指定时长内的视频
  264. * @param element 网页元素
  265. * @param {Number}key 秒数
  266. * @returns {boolean}
  267. */
  268. function shieldMinFilterS(element, key) {
  269. if (filterSMin > key) {
  270. element.remove();
  271. return true;
  272. }
  273. return false;
  274. }
  275.  
  276. /**
  277. * 限制可暂时的视频时长最大值,高于该值的都屏蔽
  278. * @param element
  279. * @param {Number}key 秒数
  280. */
  281. function shieldMaxFilterS(element, key) {
  282. if (filterSMax === 0 || filterSMax < filterSMin) {//如果最大值为0,则不需要执行了,和当最小值大于最大值也不执行
  283. return false;
  284. }
  285. if (filterSMax < key) {
  286. element.remove();
  287. return true;
  288. }
  289. return false;
  290. }
  291.  
  292.  
  293. /**
  294. * 分割时分秒字符串
  295. * @param time
  296. * @returns {{s: number, h: number, m: number}|{s: number, m: number}}
  297. */
  298. function splitTimeHMS(time) {
  299. const split = time.split(":");
  300. if (split.length === 2) {//说明时长是在60分钟以内
  301. const tempM = parseInt(split[0]);//分
  302. const tempS = parseInt(split[1]);//秒
  303. return {
  304. m: tempM,
  305. s: tempS
  306. };
  307. } else {//说明时长是在一小时以上的
  308. const tempH = parseInt(split[0]);//时
  309. const tempM = parseInt(split[0]);//分
  310. const tempS = parseInt(split[1]);//秒
  311. return {
  312. h: tempH,
  313. m: tempM,
  314. s: tempS
  315. };
  316. }
  317. }
  318.  
  319. /**
  320. * 根据字符串的时分秒转成秒
  321. * @param {String} time 时分秒字符串
  322. * @returns {Number} 总秒
  323. */
  324. function getTimeTotalSeconds(time) {
  325. const demoTime = splitTimeHMS(time);
  326. if (demoTime.h === undefined) {//表示时长没有时
  327. if (demoTime.m === 0) {//时长低于60秒
  328. return demoTime.s;
  329. }
  330. return demoTime.m * 60 + demoTime.s;//求出剩下的分和秒的总秒
  331. }
  332. if (demoTime.h === 0) {//说明时长仅仅只有60分钟以内
  333. if (demoTime.m === 0) {//时长低于60秒
  334. return demoTime.s;
  335. }
  336. return demoTime.m * 60 + demoTime.s;//求出剩下的分和秒的总秒
  337. }
  338. //一小时有60分钟,一分钟有60秒,所以,
  339. return demoTime.h * 60 * 60 + demoTime.s;
  340. }
  341.  
  342. /**
  343. *结合版-根据用户名和uid针对性屏蔽元素
  344. * @param element 网页元素
  345. * @param name 用户名
  346. * @param uid 用户uid
  347. * @returns {string|null}
  348. */
  349. function shieldNameOrUID(element, name, uid) {
  350. if (shieldUID(element, uid)) {
  351. return "uid";
  352. }
  353. if (shieldName(element, name)) {
  354. return "name";
  355. }
  356. return null;
  357. }
  358.  
  359. /**
  360. * 执行并打印相关屏蔽信息
  361. * @param element 网页元素
  362. * @param name 用户名
  363. * @param uid uid
  364. * @returns {boolean}
  365. */
  366. function startPrintShieldNameOrUID(element, name, uid) {
  367. const userShield = shieldNameOrUID(element, name, uid);
  368. if (userShield !== null) {
  369. if (userShield === "uid") {
  370. console.log("已通过uid=【" + uid + "】屏蔽黑名单用户【" + name + "】");
  371. return true;
  372. }
  373. console.log("已通过用户名屏蔽指定黑名单用户【" + name + "】");
  374. return true;
  375. }
  376. return false;
  377. }
  378.  
  379. /**
  380. * 针对言论内容根据name和uid进行屏蔽并打印消息
  381. * @param element 网页元素
  382. * @param name 用户名
  383. * @param uid 用户uid
  384. * @param content 言论内容
  385. * @returns {boolean}
  386. */
  387. function startPrintShieldNameOrUIDOrContent(element, name, uid, content) {
  388. if (startPrintShieldNameOrUID(element, name, uid)) {
  389. return true;
  390. }
  391. const key = shieldContent(element, content);
  392. if (key != null) {
  393. console.log("已通过言论关键词【" + key + "】屏蔽用户【" + name + "】 原言论=" + content);
  394. return true;
  395. }
  396. return false;
  397. }
  398.  
  399. function startPrintShieldTitle(element, arr, title, name) {
  400. const key = shieldArrContent(element, titleArr, title);
  401. if (key != null) {
  402. console.log("已通过标题关键词【" + key + "】屏蔽用户【" + name + "】");
  403. return true;
  404. }
  405. return false;
  406. }
  407.  
  408. /**
  409. * 执行并打印屏蔽专栏信息
  410. * @param element 网页元素
  411. * @param name 用户名
  412. * @param uid uid
  413. * @param content 专栏内容
  414. * @param title 专栏标题
  415. * @returns {boolean}
  416. */
  417. function startPrintshieldcolumn(element, name, uid, content, title) {
  418. if (startPrintShieldNameOrUID(element, name, uid)) {
  419. return true;
  420. }
  421. const key = shieldColumnContent(element, content);
  422. if (key !== null) {
  423. console.log("已通过专栏内容关键词【" + key + "】屏蔽用户【" + name + "】 原专栏内容=" + content);
  424. return true;
  425. }
  426. return !!(startPrintShieldTitle(element, titleArr, title, name));
  427. }
  428.  
  429. /**
  430. * 屏蔽视频元素
  431. * 针对用户名、用户uid,视频标题
  432. * @param element 对应的视频元素
  433. * @param {String}name 用户名
  434. * @param {Number}uid 用户uid
  435. * @param {String}title 视频标题
  436. * @param {String}videoTime 视频时间
  437. * @returns {boolean} 是否执行完
  438. */
  439. function shieldVideo_userName_uid_title(element, name, uid, title, videoTime) {
  440. let nameOrUID = shieldNameOrUID(element, name, uid);
  441. if (nameOrUID != null) {
  442. if (nameOrUID === "uid") {
  443. console.log("已通过id=【" + uid + "】屏蔽黑名单用户【" + name + "】 视频=" + title);
  444. return true;
  445. }
  446. console.log("已通过用户名屏蔽指定黑名单用户【" + name + "】 视频=" + title);
  447. return true;
  448. }
  449. const videoTitle = shieldTitle(element, title);
  450. if (videoTitle != null) {
  451. console.log("已通过视频标题关键词=【" + videoTitle + "】 屏蔽用户【" + name + "】 视频=" + title);
  452. }
  453. const timeTotalSeconds = getTimeTotalSeconds(videoTime);
  454. if (shieldMinFilterS(element, timeTotalSeconds)) {
  455. console.log("已通过视频时长过滤时长小于=【" + filterSMin + "】秒的视频 视频=【" + title + "】");
  456. return true;
  457. }
  458. if (shieldMaxFilterS(element, timeTotalSeconds)) {
  459. console.log("已通过视频时长过滤时长大于=【" + filterSMax + "】秒的视频 视频=【" + title + "】");
  460. return true;
  461. }
  462. return false;
  463. }
  464.  
  465. /**
  466. * 频道
  467. * 隐藏对应元素的视频
  468. * @param vdoc 视频列表
  469. * @returns {boolean}
  470. */
  471. function startExtracted(vdoc) {
  472. let temp = false;
  473. for (const element of vdoc) {
  474. //用户名
  475. const upName = element.getElementsByClassName("up-name__text")[0].textContent;
  476. //视频标题
  477. let videoName = element.getElementsByClassName("video-name")[0].textContent;
  478. //空间地址
  479. const upSpatialAddress = element.getElementsByClassName("up-name")[0].getAttribute("href");
  480. const videoTime = element.getElementsByClassName("play-duraiton")[0].textContent;
  481. const lastIndexOf = upSpatialAddress.lastIndexOf("/") + 1;
  482. const id = parseInt(upSpatialAddress.substring(lastIndexOf));
  483. temp = shieldVideo_userName_uid_title(element, upName, id, videoName, videoTime);
  484. }
  485. return temp;
  486. }
  487.  
  488. /**
  489. * 屏蔽首页对应的视频
  490. * @param {String} str
  491. */
  492. function startShieldMainVideo(str) {
  493. const interval = setInterval(() => {
  494. let list = document.getElementsByClassName(str);
  495. if (list.length === 0) {
  496. return;
  497. }
  498. while (true) {
  499. const tempLength = list.length;
  500. for (let v of list) {
  501. let videoInfo, title, upName, upSpatialAddress, videoTime;//可以一排定义
  502. try {
  503. videoInfo = v.getElementsByClassName("bili-video-card__info--right")[0];
  504. //视频标题
  505. title = videoInfo.getElementsByClassName("bili-video-card__info--tit")[0].getAttribute("title");
  506. //用户名
  507. upName = videoInfo.getElementsByClassName("bili-video-card__info--author")[0].getAttribute("title");
  508. //用户空间地址
  509. upSpatialAddress = videoInfo.getElementsByClassName("bili-video-card__info--owner")[0].getAttribute("href");
  510. videoTime = v.getElementsByClassName("bili-video-card__stats__duration")[0].textContent;//视频的时间
  511. } catch (e) {
  512. v.remove();
  513. console.log("获取元素中,获取失败,下一行是该值的html");
  514. console.log(v)
  515. continue;
  516. }
  517. let id = parseInt(upSpatialAddress.substring(upSpatialAddress.lastIndexOf("/") + 1));
  518. if (isNaN(id)) {
  519. v.remove();
  520. console.log("检测到不是正常视频样式,故删除该元素");
  521. continue;
  522. }
  523. shieldVideo_userName_uid_title(v, upName, id, title, videoTime);
  524. }
  525. list = document.getElementsByClassName(str);//删除完对应元素之后再检测一次,如果没有了就结束循环并结束定时器
  526. if (list.length !== tempLength) {//如果执行完之后关键元素长度还是没有变化,说明不需要在执行了
  527. continue;
  528. }
  529. clearInterval(interval);
  530. return;
  531. }
  532. }, 1000);
  533. }
  534.  
  535. /**
  536. * 屏蔽首页顶部推荐视频
  537. */
  538. function startShieldMainVideoTop() {
  539. startShieldMainVideo("feed-card");
  540. }
  541.  
  542. /**
  543. * 点击播放器的宽屏按钮
  544. */
  545. function click_playerCtrlWhid() {
  546. const interval = setInterval(() => {
  547. try {
  548. document.getElementsByClassName("bpx-player-ctrl-btn bpx-player-ctrl-wide")[0].click()
  549. console.log("已自动点击播放器的宽屏")
  550. clearInterval(interval);
  551. } catch (e) {
  552. }
  553. }, 1000);
  554. }
  555.  
  556. /**
  557. * 删除消息中心的回复我的规则
  558. */
  559. function delMessageReply() {
  560. const list = document.getElementsByClassName("reply-item");
  561. for (let v of list) {
  562. const info = v.getElementsByClassName("name-field")[0];
  563. const name = info.textContent;//用户名
  564. const indess = info.getElementsByTagName("a")[0].getAttribute("href");
  565. const uid = parseInt(indess.substring(indess.lastIndexOf("/") + 1));
  566. const content = v.getElementsByClassName("text string")[0].textContent;//消息内容
  567. startPrintShieldNameOrUIDOrContent(v, name, uid, content);
  568. }
  569. }
  570.  
  571. /**
  572. * 删除消息中的艾特我的规则
  573. */
  574. function delMessageAT() {
  575. for (let v of document.getElementsByClassName("at-item")) {
  576. const userInfo = v.getElementsByClassName("name-field")[0].getElementsByTagName("a")[0];
  577. const href = userInfo.getAttribute("href");
  578. const userName = userInfo.textContent;
  579. const uid = parseInt(href.substring(href.lastIndexOf("/") + 1));
  580. const content = v.getElementsByClassName("content-list")[0].textContent;
  581. startPrintShieldNameOrUIDOrContent(v, userName, uid, content);
  582. }
  583. }
  584.  
  585.  
  586. /**
  587. * 针对视频播放页的相关方法
  588. */
  589. const delVideo = {
  590. rightFixdNav: function () { //移除播放页右侧的部分悬浮按钮-【新版反馈】【回到旧版】
  591. let tempIndex = 0;
  592. const interval = setInterval(() => {
  593. if (++tempIndex === 2) {
  594. clearInterval(interval);
  595. }
  596. try {
  597. const fixed_Nav = document.getElementsByClassName("fixed-nav")[0];
  598. if (fixed_Nav) {
  599. fixed_Nav.remove();
  600. }
  601. } catch (e) {
  602. }
  603. }, 2000);
  604. },
  605. rightFixed_nav_ex: function () {//移除播放页右侧的部分悬浮按钮
  606. let tempIndex = 0;
  607. const interval = setInterval(() => {
  608. if (++tempIndex === 2) {
  609. clearInterval(interval);
  610. }
  611. try {
  612. const float_nav_exp = document.getElementsByClassName("float-nav-exp")[0];
  613. if (float_nav_exp) {
  614. float_nav_exp.getElementsByClassName("item mini")[0].remove();//删除右侧的小窗按钮
  615. float_nav_exp.getElementsByTagName("a")[0].remove();//删除右侧的反馈按钮
  616. }
  617. } catch (e) {
  618. }
  619. }, 2000);
  620. },
  621. lListRightTopGameAD: function () {//移除播放页右上角的游戏推广
  622. const tempVar = document.getElementsByClassName("video-page-game-card-small")[0];
  623. if (tempVar) {
  624. tempVar.remove();
  625. console.log("移除播放页右上角的游戏推广")
  626. }
  627. },
  628. listRightTopOtherAD: function () {//移除播放页右上角的其他推广
  629. let index = 0;
  630. const interval = setInterval(() => {
  631. if (++index === 2) {
  632. clearInterval(interval);
  633. }
  634. const tempVar = document.getElementsByClassName("video-page-special-card-small")[0];
  635. if (tempVar) {
  636. tempVar.remove();
  637. console.log("移除播放页右上角的其他推广")
  638. }
  639. }, 2000);
  640. },
  641. listRightTopAD: function () {//移除播放页右上角的广告
  642. let index = 0;
  643. const interval = setInterval(() => {
  644. if (++index === 2) {
  645. clearInterval(interval);
  646. }
  647. const vcd = document.getElementsByClassName("vcd")[0];
  648. if (vcd) {
  649. vcd.remove();
  650. console.log("已移除右上角的广告")
  651. }
  652. }, 2000);
  653. }, commentArea: function () {
  654. let index = 0;
  655. const interval = setInterval(() => {
  656. if (++index === 2) {
  657. clearInterval(interval);
  658. }
  659. const ad = document.getElementById("bannerAd");
  660. if (ad) {
  661. ad.remove();
  662. }
  663. }, 2000);
  664. },
  665. rightBottomBanner: function () {//删除右下角的活动推广
  666. const id = document.getElementById("right-bottom-banner");
  667. if (id) {
  668. id.remove();
  669. console.log("删除右下角的活动推广")
  670. }
  671. },
  672. rightListBottonLive: function () {//删除右下角的直播推广
  673. const interval = setInterval(() => {
  674. const className = document.getElementsByClassName("pop-live-small-mode part-undefined")[0];
  675. if (className) {
  676. className.remove();
  677. console.log("删除右下角的直播推广")
  678. clearInterval(interval)
  679. }
  680. }, 2000);
  681. }
  682. }
  683.  
  684. //针对于直播间顶部的屏蔽处理
  685. function delLiveTopElement() {
  686. if (liveData.topElement) {
  687. document.getElementsByClassName("link-navbar-ctnr z-link-navbar w-100 p-fixed p-zero ts-dot-4 z-navbar contain-optimize")
  688. console.log("已移除直播间顶部的信息(包括顶部标题栏)")
  689. return;
  690. }
  691. }
  692.  
  693. //针对于直播间底部的屏蔽处理
  694. function delLiveBottomElement() {
  695. document.getElementById("link-footer-vm").remove();
  696. console.log("已移除底部的页脚信息")
  697. if (liveData.bottomElement) {
  698. document.getElementById("sections-vm").remove();
  699. console.log("已移除直播间底部的全部信息")
  700. return;
  701. }
  702. if (liveData.bottomIntroduction) {
  703. document.getElementsByClassName("section-block f-clear z-section-blocks")[0].getElementsByClassName("left-container")[0].remove();
  704. console.log("已移除直播间底部的的简介和主播荣誉")
  705. } else {
  706. if (liveData.liveFeed) {
  707. const interval = setInterval(() => {
  708. try {
  709. document.getElementsByClassName("room-feed")[0].remove();
  710. clearInterval(interval)
  711. console.log("已移除页面底部动态部分")
  712. } catch (e) {
  713. }
  714. }, 2500);
  715. }
  716. }
  717. if (liveData.container) {
  718. document.getElementsByClassName("right-container")[0].remove();
  719. console.log("已移除直播间的主播公告")
  720. }
  721. }
  722.  
  723.  
  724. /**
  725. * 屏蔽直播间对应的言论
  726. * 暂时测试打印下效果
  727. */
  728. function delDemo() {
  729. const chatItems = document.getElementById("chat-items");
  730. const list = chatItems.getElementsByClassName("chat-item danmaku-item");
  731. for (let v of list) {
  732. const userName = v.getAttribute("data-uname");
  733. const uid = parseInt(v.getAttribute("data-uid"));
  734. const content = v.getAttribute("data-danmaku");
  735. let fansMeda = "这是个个性粉丝牌子";
  736. try {
  737. fansMeda = v.getElementsByClassName("fans-medal-content")[0].textContent;
  738. } catch (e) {
  739. }
  740. if (!startPrintShieldNameOrUIDOrContent(v, userName, uid, content)) {
  741. if (shieldFanCard(v, fansMeda)) {
  742. console.log("已通过粉丝牌【" + fansMeda + "】屏蔽用户【" + userName + "】 言论=" + content);
  743. }
  744. }
  745. }
  746. }
  747.  
  748. /**
  749. * 针对视频播放页右侧的视频进行过滤处理
  750. */
  751. function delVideoRightVideo() {
  752. for (let e of document.getElementsByClassName("video-page-card-small")) {//获取右侧的页面的视频列表
  753. const videoInfo = e.getElementsByClassName("info")[0];
  754. //用户名
  755. const name = videoInfo.getElementsByClassName("name")[0].textContent;
  756. //视频标题
  757. const videoTitle = videoInfo.getElementsByClassName("title")[0].textContent;
  758. //用户空间地址
  759. const upSpatialAddress = e.getElementsByClassName("upname")[0].getElementsByTagName("a")[0].getAttribute("href");
  760. const id = parseInt(upSpatialAddress.substring(upSpatialAddress.lastIndexOf("com/") + 4, upSpatialAddress.length - 1));
  761. let videoTime = undefined;
  762. try {
  763. videoTime = e.getElementsByClassName("duration")[0].textContent;
  764. } catch (e) {
  765. console.log("获取视频时长错误,出现异常错误=" + e)
  766. }
  767. shieldVideo_userName_uid_title(e, name, id, videoTitle, videoTime);
  768. }
  769. }
  770.  
  771.  
  772. /**
  773. * 清理首页零散无用的推送,如个别直播推送,综艺,赛事等,零散的掺杂在视频列表中
  774. */
  775. function startShieldMainAFloorSingle() {
  776. const interval = setInterval(() => {
  777. let list = document.getElementsByClassName("floor-single-card");
  778. if (list.length === 0) {
  779. return;
  780. }
  781. while (true) {
  782. for (let v of list) {
  783. v.remove();
  784. }
  785. list = document.getElementsByClassName("floor-single-card");//删除完对应元素之后再检测一次,如果没有了就结束循环并结束定时器
  786. if (list.length === 0) {
  787. console.log("清理首页零散无用的推送")
  788. clearInterval(interval);
  789. return;
  790. }
  791. }
  792. }, 1000);
  793. }
  794.  
  795. /**
  796. * 清理首页中的零散的直播间元素
  797. */
  798. function startShieldMainlive() {
  799. if (boolShieldMainlive === true) {//避免同一时间多个执行!,只能执行完一个再执行下一个,反之其他统统拒绝
  800. return;
  801. }
  802. boolShieldMainlive = true;
  803. const interval = setInterval(() => {
  804. const list = document.getElementsByClassName("bili-live-card is-rcmd");
  805. if (list.length === 0) {
  806. return;
  807. }
  808. for (let v of list) {
  809. v.remove();
  810. }
  811. console.log("已清理零散的直播元素");
  812. clearInterval(interval);
  813. boolShieldMainlive = false;
  814. }, 500);
  815. }
  816.  
  817. /***
  818. * 屏蔽首页左侧的轮播大图
  819. */
  820. function startShieldMainLeftPic() {
  821. if (homePicBool) {
  822. const interval = setInterval(() => {
  823. try {
  824. document.getElementsByClassName("recommended-swipe grid-anchor")[0].style.display = "none"
  825. console.log("执行了屏蔽首页轮播图")
  826. clearInterval(interval);
  827. } catch (e) {
  828. }
  829. }, 1000);
  830. }
  831. }
  832.  
  833. /**
  834. * 针对b站话题
  835. */
  836. function deltopIC() {
  837. for (let v of document.getElementsByClassName("list__topic-card")) {
  838. const info = v.getElementsByClassName("bili-dyn-content__orig")[0];
  839. const name = v.getElementsByClassName("bili-dyn-title")[0].textContent.trim();
  840. const uid = parseInt(v.getElementsByClassName("bili-dyn-item__following")[0].getAttribute("data-mid"));
  841. if (info.getElementsByClassName("bili-dyn-content__orig__desc").length === 1) {
  842. const content = info.textContent;
  843. startPrintShieldNameOrUIDOrContent(v, name, uid, content);
  844. continue;
  845. }//如果内容是视频样式
  846. const videoInfo = info.getElementsByClassName("bili-dyn-card-video")[0];
  847. const videoTime = videoInfo.getElementsByClassName("bili-dyn-card-video__duration")[0].textContent;
  848. const title = videoInfo.getElementsByClassName("bili-dyn-card-video__title bili-ellipsis")[0].textContent;
  849. shieldVideo_userName_uid_title(v, name, uid, title, videoTime);
  850. }
  851. }
  852.  
  853.  
  854. /**
  855. * 根据规则删除专栏和动态的评论区
  856. * 针对于专栏和动态内容下面的评论区
  857. */
  858. function delDReplay() {
  859. const list = document.getElementsByClassName("list-item reply-wrap");
  860. for (let v of list) {
  861. const userInfo = v.getElementsByClassName("user")[0];//楼主信息
  862. const userName = userInfo.getElementsByClassName("name")[0].textContent;//楼主用户名
  863. const uid = parseInt(userInfo.getElementsByTagName("a")[0].getAttribute("data-usercard-mid"));//楼主UID
  864. const userContent = v.getElementsByClassName("text")[0].textContent;//内容
  865. const replyItem = v.getElementsByClassName("reply-box")[0].getElementsByClassName("reply-item reply-wrap");//楼层成员
  866. if (startPrintShieldNameOrUIDOrContent(v, userName, uid, userContent)) {
  867. continue;
  868. }
  869. for (let j of replyItem) {
  870. const replyInfo = j.getElementsByClassName("user")[0];//楼层成员info信息
  871. const replayName = replyInfo.getElementsByClassName("name")[0].textContent;
  872. const replayUid = parseInt(replyInfo.getElementsByClassName("name")[0].getAttribute("data-usercard-mid"));
  873. const replayContent = replyInfo.getElementsByTagName("span")[0].textContent;
  874. startPrintShieldNameOrUIDOrContent(j, replayName, replayUid, replayContent);
  875. }
  876. }
  877. }
  878.  
  879. /**
  880. * 删除搜索页面的视频元素
  881. * @param videoList
  882. */
  883. function searchRules(videoList) {
  884. for (let v of videoList) {
  885. let info = v.getElementsByClassName("bili-video-card__info--right")[0];
  886. let userInfo = info.getElementsByClassName("bili-video-card__info--owner")[0];
  887. //用户名
  888. let name = userInfo.getElementsByClassName("bili-video-card__info--author")[0].textContent;
  889. //视频标题
  890. let title = info.getElementsByClassName("bili-video-card__info--tit")[0].getAttribute("title");
  891. //用户空间地址
  892. let upSpatialAddress = userInfo.getAttribute("href");
  893. if (!upSpatialAddress.startsWith("//space.bilibili.com/")) {
  894. console.log("检测到不是正常视频内容,故隐藏该元素")
  895. //如果获取的类型不符合规则则结束本轮
  896. v.parentNode.remove();
  897. continue;
  898. }
  899. const videoTime = v.getElementsByClassName("bili-video-card__stats__duration")[0].textContent;//视频的时间
  900. let id = parseInt(upSpatialAddress.substring(upSpatialAddress.lastIndexOf("/") + 1));
  901. shieldVideo_userName_uid_title(v.parentNode, name, id, title, videoTime);
  902. }
  903. }
  904.  
  905. function perf_observer(list, observer) {
  906. const entries = performance.getEntriesByType('resource');
  907. const windowUrl = getWindowUrl();
  908. for (let entry of entries) {
  909. const url = entry.name;
  910. const initiatorType = entry.initiatorType;
  911. if (initiatorType === "img" || initiatorType === "css" || initiatorType === "link" || initiatorType === "beacon") {
  912. continue;
  913. }
  914. //只要json类的
  915. if (url.includes("api.bilibili.com/x/web-interface/web/channel")) {
  916. //针对于频道界面的综合视频和频道界面的精选视频
  917. frequencyChannelRules();
  918. channelListRules();
  919. continue;
  920. }
  921. if (url.includes("https://api.bilibili.com/x/v2/reply/main?csrf=") ||
  922. url.includes("api.bilibili.com/x/v2/reply/reply?csrf=") &&
  923. windowUrl.includes("https://www.bilibili.com/video")) {
  924. //如果是视频播放页的话,且接收到评论的相应请求
  925. for (let v of document.getElementsByClassName("reply-item")) {//针对于评论区
  926. const userInfo = v.getElementsByClassName("user-info")[0];
  927. const userName = userInfo.getElementsByClassName("user-name")[0].textContent;
  928. const userID = userInfo.getElementsByClassName("user-name")[0].getAttribute("data-user-id")
  929. const root = v.getElementsByClassName("reply-content")[0].parentNode.textContent;//楼主评论
  930. const subReplyList = v.getElementsByClassName("sub-reply-list")[0];//楼主下面的评论区
  931. if (startPrintShieldNameOrUIDOrContent(v, userName, userID, root)) {
  932. continue;
  933. }
  934. for (let j of subReplyList.getElementsByClassName("sub-reply-item")) {
  935. const subUserName = j.getElementsByClassName("sub-user-name")[0].textContent;
  936. const subUserID = j.getElementsByClassName("sub-user-name")[0].getAttribute("data-user-id")
  937. const subContent = j.getElementsByClassName("reply-content-container sub-reply-content")[0].textContent;
  938. startPrintShieldNameOrUIDOrContent(j, subUserName, subUserID, subContent);
  939. }
  940. }
  941. continue;
  942. }
  943. if (url.includes("api.bilibili.com/x/web-interface/wbi/index/top/feed/rcmd?y_num=5&fresh_type=3&feed_version=V8&fresh_idx_1h=2&fetch_row=1&fresh_idx=2&brush=0&homepage_ver=1&ps=10&last_y_num=5&outside_trigger=&w_rid=")) {
  944. //首页带有换一换一栏的视频列表
  945. startShieldMainVideoTop();
  946. console.log("首页带有换一换一栏的视频列表")
  947. continue;
  948. }
  949. if (url.includes("api.bilibili.com/x/web-interface/wbi/index/top/feed/rcmd?y_num=4&fresh_type=4&feed_version=V8&fresh_idx_1h=")) {//首页换一换推送下面的视频
  950. startShieldMainVideo("bili-video-card is-rcmd");
  951. startShieldMainAFloorSingle();
  952. startShieldMainlive();
  953. continue;
  954.  
  955. }
  956. if (url.includes("api.bilibili.com/x/web-show/wbi/res/locs?pf=")) {//首页赛事相关
  957. startShieldMainAFloorSingle();
  958. continue;
  959. }
  960. if (url.includes("api.bilibili.com/x/msgfeed/reply?platform=") || url.includes("api.bilibili.com/x/msgfeed/reply?id=")) {//第一次加载对应json信息和后续添加的json信息
  961. delMessageReply();
  962. continue;
  963. }
  964. if (url.includes("api.bilibili.com/x/article/metas?ids=")) {
  965. searchColumn();
  966. continue;
  967. }
  968. if (url.includes("api.bilibili.com/x/msgfeed/at?build=")) {//消息中心的 @我的
  969. delMessageAT();
  970. continue;
  971. }
  972.  
  973. //后面一个条件限制为仅仅是专栏页面的该api,消息中心的api疑似也是这个,后续在测试看下
  974. if (url.includes("api.bilibili.com/x/v2/reply/main?callback=jQuery") || url.includes("api.bilibili.com/x/v2/reply/reply?callback=jQuery")) {
  975. if (windowUrl.includes("www.bilibili.com/read")) {
  976. delDReplay();
  977. continue;
  978. }
  979. if (windowUrl.includes("t.bilibili.com")) {
  980. console.log("接收到了动态的评论区api")
  981. delDReplay();
  982. continue;
  983. }
  984. if (windowUrl.includes("www.bilibili.com/v/topic/detail/?topic_id=")) {//话题界面的楼层评论
  985. console.log("话题界面的api")
  986. }
  987. }
  988. if (url.includes("app.bilibili.com/x/topic/web/details/cards?topic_id=") && windowUrl.includes("www.bilibili.com/v/topic/detail/?topic_id=")) {//话题页面数据加载
  989. deltopIC();
  990. }
  991.  
  992. if (url.includes("api.bilibili.com/x/web-interface/wbi/index/top/feed/rcmd?y_num=")) {//该api应该是首页可通过换一换是推荐下面的视频内容
  993. console.log("不确定api链接!")
  994. }
  995. }
  996. }
  997.  
  998. /**
  999. * 频道排行榜规则
  1000. */
  1001. function channelListRules() {
  1002. let list = document.getElementsByClassName("rank-video-card");
  1003. if (list.length !== 0 && startExtracted(list)) {
  1004. console.log("已检测到频道综合的排行榜")
  1005. }
  1006. }
  1007.  
  1008. /**
  1009. * 频道精选视频等其他视频规则
  1010. * 已针对个别情况没有删除对应元素,做了个循环处理
  1011. */
  1012. function frequencyChannelRules() {
  1013. //针对频道中的精选视频和在综合排行榜下面的视频
  1014. //let index = 0;
  1015. while (true) {
  1016. const list = document.getElementsByClassName("video-card");
  1017. const tempLength = list.length;
  1018. if (tempLength === 0) {
  1019. break;
  1020. }
  1021. //console.log("执行第" + index + "轮检测")
  1022. startExtracted(list)
  1023. if (list.length === tempLength) {
  1024. console.log("页面元素没有变化了,故退出循环")
  1025. break;
  1026. }
  1027. }
  1028. }
  1029.  
  1030. /**
  1031. * 根据规则屏蔽搜索专栏项目
  1032. */
  1033. function searchColumn() {
  1034. const list = document.getElementsByClassName("col_6 mb_x40");
  1035. for (let v of list) {
  1036. const userInfo = v.getElementsByClassName("flex_start flex_inline text3")[0];
  1037. const title = v.getElementsByClassName("text1")[0].textContent;
  1038. const textContent = v.getElementsByClassName("atc-desc b_text text_ellipsis_2l text3 fs_5")[0].textContent;//搜索专栏中的预览部分
  1039. const userName = userInfo.textContent;
  1040. const upSpatialAddress = userInfo.getAttribute("href");
  1041. let id = parseInt(upSpatialAddress.substring(upSpatialAddress.lastIndexOf("/") + 1));
  1042. startPrintshieldcolumn(v, userName, id, textContent, title);
  1043. }
  1044. }
  1045.  
  1046. /**
  1047. * 根据网页url指定不同的逻辑
  1048. * @param href{String} url链接
  1049. */
  1050. function ruleList(href) {
  1051. if (href.includes("https://search.bilibili.com/all") || href.includes("search.bilibili.com/video")) {//搜索页面-综合-搜索界面-视频
  1052. const interval = setInterval(() => {
  1053. while (true) {
  1054. const list = document.getElementsByClassName("bili-video-card");
  1055. const tempListLength = list.length;
  1056. if (tempListLength === 0) {
  1057. break;
  1058. }
  1059. try {//删除搜索到的精确结果元素
  1060. document.getElementsByClassName("activity-game-list i_wrapper search-all-list")[0].remove();
  1061. console.log("删除搜索到的精确结果元素")
  1062. } catch (e) {
  1063. }
  1064. try {//删除搜索到的精确用户结果元素
  1065. document.getElementsByClassName("user-list search-all-list")[0].remove();
  1066. console.log("删除搜索到的精确用户结果元素")
  1067. } catch (e) {
  1068. }
  1069. searchRules(list);
  1070. if (tempListLength === list.length) {
  1071. clearInterval(interval);
  1072. console.log("页面元素没有变化,故退出循环")
  1073. break;
  1074. }
  1075. }
  1076. }, 500);
  1077. }
  1078. if (href.includes("https://www.bilibili.com/video")) {//如果是视频播放页的话
  1079. document.getElementById("reco_list").addEventListener("DOMSubtreeModified", () => {
  1080. setTimeout(() => {
  1081. delVideoRightVideo();
  1082. }, 1500);
  1083. });
  1084. setTimeout(() => {
  1085. document.getElementsByClassName("rec-footer")[0].addEventListener("click", () => {
  1086. console.log("用户点击了右侧的展开")
  1087. delVideoRightVideo();
  1088. })
  1089. }, 3000);
  1090. try {
  1091. delVideo.rightFixdNav();
  1092. delVideo.rightFixed_nav_ex();
  1093. delVideo.lListRightTopGameAD();
  1094. delVideo.listRightTopOtherAD();
  1095. delVideo.listRightTopAD();
  1096. delVideo.commentArea();
  1097. setTimeout(() => {
  1098. delVideo.rightListBottonLive();
  1099. delVideo.rightBottomBanner();
  1100. }, 3500);
  1101. } catch (e) {
  1102. console.log("屏蔽信息错误!!!!!!!!!!!!!!!")
  1103. }
  1104. //click_playerCtrlWhid();
  1105. }
  1106. if (href.includes("message.bilibili.com/#/at") || href.includes("message.bilibili.com/?spm_id_from=..0.0#/at")) {//消息中心-艾特我的
  1107. delMessageAT();
  1108. return;
  1109. }
  1110. if (href.includes("message.bilibili.com/#/reply") || href.includes("message.bilibili.com/?spm_id_from=..0.0#/reply")) {
  1111. delMessageReply();
  1112. return;
  1113. }
  1114. if (href.search("www.bilibili.com/v/channel/.*?tab=.*") !== -1) {//频道 匹配到频道的精选列表,和综合的普通列表
  1115. frequencyChannelRules();
  1116. }
  1117.  
  1118. }
  1119.  
  1120. (function () {
  1121. 'use strict';
  1122. let href = getWindowUrl();
  1123. console.log("当前网页url= " + href);
  1124. //监听网络变化
  1125. const observer = new PerformanceObserver(perf_observer);
  1126. observer.observe({entryTypes: ['resource']});
  1127.  
  1128. ruleList(href)//正常加载网页时执行
  1129.  
  1130. setInterval(function () {//每秒监听网页中的url
  1131. const tempUrl = getWindowUrl();
  1132. if (href === tempUrl) {//没有变化就结束本轮
  1133. return;
  1134. }//有变化就执行对应事件
  1135. console.log("页面url发生变化了,原=" + href + " 现=" + tempUrl);
  1136. href = tempUrl;//更新url
  1137. ruleList(href);//网页url发生变化时执行
  1138. }, 1000);
  1139.  
  1140.  
  1141. if (href.includes("//live.bilibili.com/")) {
  1142. delLiveTopElement();
  1143. delLiveBottomElement();
  1144. try {
  1145. document.getElementById("chat-items").addEventListener("DOMSubtreeModified", () => {
  1146. delDemo();
  1147. });
  1148. console.log("定义了监听器=chat-items")
  1149. } catch (e) {
  1150. console.log("测试,没找着id")
  1151. }
  1152. }
  1153. if (href.includes("search.bilibili.com") && searchColumnBool === false) {
  1154. try {
  1155. document.getElementById("biliMainFooter").remove();
  1156. document.getElementsByClassName("side-buttons flex_col_end p_absolute")[0].remove();
  1157. console.log("已删除搜索底部信息和右侧悬浮按钮")
  1158. } catch (e) {
  1159. }
  1160. searchColumnBool = true;
  1161. const interval = setInterval(() => {
  1162. try {
  1163. document.getElementsByClassName("vui_tabs--nav-link")[5].addEventListener("click", () => {//监听用户点击了专栏选项卡
  1164. setTimeout(() => {
  1165. console.log("用户点击了专栏")
  1166. searchColumn();
  1167. }, 500);
  1168. });
  1169. clearInterval(interval);
  1170. } catch (e) {
  1171. }
  1172. }, 1000);
  1173. }
  1174.  
  1175.  
  1176. if (href.includes("www.bilibili.com/v/topic/detail/?topic_id=")) {//话题
  1177. deltopIC();
  1178. }
  1179.  
  1180. if (href === "https://www.bilibili.com/") { //首页
  1181. startShieldMainLeftPic();
  1182. if (paletteButtionBool) {
  1183. setTimeout(() => {
  1184. document.getElementsByClassName("palette-button-wrap")[0].style.display = "none";
  1185. }, 2000);
  1186. }
  1187. //document.getElementById("bili-header-banner-img").remove()//删除首页顶部的图片
  1188. document.getElementsByClassName("left-entry")[0].style.visibility = "hidden"//删除首页左上角的导航栏,并继续占位
  1189. document.getElementsByClassName("banner-link")[0].remove();//删除首页顶部图片的跳转链接
  1190. startShieldMainAFloorSingle();
  1191. startShieldMainVideoTop();
  1192. }
  1193. })();
  1194. /**
  1195. 精简处理的地方有:
  1196. 搜索页面右侧悬浮按钮(貌似是新版的,没留意)
  1197. 搜索页面底部信息
  1198. 视频播放界面右侧个别悬浮按钮
  1199. */
  1200.  
  1201. /*****
  1202. * 原本想写多一个处理从首页进去的的动态页面的评论区的,不知道为什么捕获不到那个api链接,如果捕获到了或许可以比较好处理写,用定时器一直监听也是比较麻烦,以后如果有机会或者,找到方法了在尝试解决把
  1203. * 对其部分上述代码先放在注释这边先,以后有缘再处理
  1204. * 其中关键api放这:
  1205. * api.bilibili.com/x/v2/reply/main?callback=
  1206. * api.bilibili.com/x/polymer/web-dynamic/v1/feed/all?host_mid=
  1207. function dynamicCommentsf(v) {//动态评论区
  1208. const userInfo = v.getElementsByClassName("user")[0].getElementsByTagName("a")[0];//用户信息
  1209. const userUID = userInfo.getAttribute("data-usercard-mid");//用户UID
  1210. const userName = userInfo.text;//用户名
  1211. }
  1212. for (let v of document.getElementsByClassName("comment-list has-limit")[0].getElementsByClassName("con")) {
  1213. dynamicCommentsf(v);
  1214. const userContent = v.getElementsByClassName("text")[0].textContent;//楼主的言论
  1215. console.log(userContent)
  1216. for (let j of v.getElementsByClassName("reply-item reply-wrap")) {//楼主下面的评论
  1217. dynamicCommentsf(j)
  1218. const subContent = j.getElementsByClassName("text-con")[0].textContent;
  1219. //console.log(subContent);
  1220. }
  1221. }
  1222.  
  1223.  
  1224. //设置页面元素监听点击事件
  1225. document.getElementsByClassName("feed-roll-btn")[0].addEventListener("click", () => {
  1226. setTimeout(() => {
  1227. startShieldMainVideoTop();
  1228. console.log("用户点击了换一换")
  1229. }, 500);
  1230. });
  1231.  
  1232.  
  1233.  
  1234. 获取用户所有关注的思路:
  1235. 不确定js有没有相关可以发起请求的库,以java的为例,请求带上cookie,和referer,
  1236. 且用该api发起请求
  1237. https://api.bilibili.com/x/relation/followings?vmid=UID号&pn=页数,从1开始&ps=20&order=desc&order_type=attention&jsonp=jsonp&callback=__jp5
  1238. 其中referer值=https://space.bilibili.com/用户UID/fans/follow
  1239. 正常情况就可以得到内容了,根据总的关注数量,除以20,且除余就得出需要循环获取多少次了页数
  1240.  
  1241. 新计划
  1242. 根据规则屏蔽直播间的用户
  1243.  
  1244.  
  1245.  
  1246. 这里写一下,避免下次还得用搜索引擎查找,目前已知match的网址规则可以这样填写,就匹配到了 *://message.bilibili.com/*
  1247.  
  1248. */
  1249.  

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址