B站動態導航 (歸檔員自用)

能導航到指定日期的動態,僅對 https://space.bilibili.com/<你UID>/dynamic/ 作用,僅歸檔員自用。

  1. // ==UserScript==
  2. // @name B站動態導航 (歸檔員自用)
  3. // @namespace http://yuhang0000.github.io/
  4. // @version v1.8_2025-3-22
  5. // @description 能導航到指定日期的動態,僅對 https://space.bilibili.com/<你UID>/dynamic/ 作用,僅歸檔員自用。
  6. // @author 欲行肆灵
  7. // @match https://space.bilibili.com/*
  8. // @grant none
  9. // @license GPLv3
  10. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACnklEQVRYR+2XX0hTURzHv9edXVuNNaFhm+CLiBXh8qXaUGRBD+YCX8oSwerm34cG+RKxMGlILxMEwYxuTVCazxV7S8Q0eskUscboIWOzWpDWck5n9rDuzXO3dbu4raA+cGHn+/ve8/vew93ZGfBXolIRNPd40P/kAzrcXmi0OqlFFo1Whw63F/2TYTT3eKBSEaklPZV1TRia3xQv58ikohAarQ7OkUlqjsq6JqkNAFKnystTUePSCis6B31wt9YgGvlM1aRotDp0DvpQWmGl9DQrwEgFAABRs7jiGUuaJDA9BXfbCUS/LFO6QLrmgekp3DxnQ3x9jdKRLgDw68lShVDq/8HPAETNwlbfBkvtWRSVHsSOndotvu2zuhJBMDCHp4/uY2z0lrAaiQAFhUW4PPAQxfsOUTdli4VXL9Dbbsen90EGRM2ia/RZzpoLLPhn0F1/hMB2ujXnzQGguMwM26kWAou9gSrMTvjAOzkshRcpfbvoDUZwLh7lVTWiZrE3MOBnYiBqVhQd1aaMNxfQG4zoGw+J4/hajFDNAWStOZA8N2HzU+5OuUQ+QHlVDTgXDwDgnRxmJ3wSB41CP4Oh+U1KaTpA74594yHoDUYAiSV0VJuouhQ5v6Sf/AoIk0k/p0OhXz5AlpEPsBReFJ9k+eM7STUZhX75AHevXQTn4vFtYwP3ulqk5SQU+uVfwkyj+CXMMv8DEMTX16jfA73BmLRnZ4rde/ZS49WVCMGb+ecoMR8VxQs37oB3cr/zFVJEQWERznffprRgYI7B8cZLaLzaRxVyxXCPgwFh8xNHsjKztJ5V3vpncb3+8B86lPpn0NtWmziUChA1i2Nn2mE92QhTyX7ka3ZtuWX7xKJfEXr9ElMPhvHYO5DqT8q/yXdT6gC1Lkc+ZAAAAABJRU5ErkJggg==
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. window.areufind = 2333;
  17. window.areuskip = false;
  18. window.color_red = "color: #a5361c";
  19. window.color_blue = "color: #0f5290";
  20. window.color_lightblue = "color: #2c87b2";
  21.  
  22. //这是延时
  23. function delay(ms) {
  24. return new Promise(resolve => setTimeout(resolve, ms));
  25. }
  26.  
  27. //时间戳转换
  28. function timestamp(itemtime,now){
  29. if(itemtime.indexOf("刚刚") != -1){
  30. itemtime = now.valueOf()
  31. }
  32. else if(itemtime.indexOf("秒") != -1){
  33. itemtime = now.valueOf() - (itemtime.substring(0,itemtime.indexOf("秒")) * 1000);
  34. }
  35. else if(itemtime.indexOf("分钟") != -1){
  36. itemtime = now.valueOf() - (itemtime.substring(0,itemtime.indexOf("分钟")) * 60 * 1000);
  37. }
  38. else if(itemtime.indexOf("小时") != -1){
  39. itemtime = now.valueOf() - (itemtime.substring(0,itemtime.indexOf("小时")) * 60 * 60 * 1000);
  40. }
  41. else if(itemtime.indexOf("天") != -1){
  42. if(itemtime.indexOf("昨天") != -1){
  43. itemtime = now.valueOf() - now.getHours() * 60 * 60 * 1000;
  44. }
  45. else if(itemtime.indexOf("前天") != -1){
  46. itemtime = now.valueOf() - (now.getHours() * 60 * 60 * 1000) + 86400000;
  47. }
  48. else{
  49. itemtime = now.valueOf() - (now.getHours() * 60 * 60 * 1000) + itemtime.substring(0,itemtime.indexOf("天")) * 86400000;
  50. }
  51. }
  52. else{
  53. itemtime = itemtime.replace(/\//g, "-");
  54. itemtime = itemtime.replace(/年/g, "-");
  55. itemtime = itemtime.replace(/月/g, "-");
  56. //itemtime = itemtime.replace(/日/g, "");
  57. if(itemtime.indexOf("日") != -1){
  58. itemtime = itemtime.substring(0,itemtime.indexOf("日"))
  59. }
  60. if((itemtime.split("-").length - 1) == 1){
  61. itemtime = now.getFullYear() + "-" +itemtime;
  62. }
  63. let temptime = new Date(itemtime);
  64. itemtime = temptime.valueOf();
  65. }
  66. return itemtime;
  67. }
  68.  
  69. //找出荧幕目前所在的动态
  70. function finditem(item_num,two,now = null){
  71. try{
  72. let items = document.querySelector('.bili-dyn-list__items');
  73. let item = items.querySelectorAll('.bili-dyn-list__item');
  74. for(let btn of item){
  75. item_num = item_num + 1;
  76. //console.log(item_num + ": " +btn.getBoundingClientRect().top);
  77. if(btn.getBoundingClientRect().top > 0){
  78. if(item_num >= 1){
  79. item_num = item_num - 1;
  80. }
  81. //let itemtime = btn.querySelector('.bili-rich-text__content');
  82. //itemtime = itemtime.innerText;
  83. //console.log("> " + itemtime + " <");
  84. break;
  85. }
  86. }
  87. if(two == 2){
  88. console.log("%c从 " + (item_num + 1) + " 项开始遍历",window.color_blue);
  89. }
  90. else{
  91. console.log("%c截止到 " + (item_num + 1) + " 项结束",window.color_blue);
  92.  
  93. //转化时间戳
  94. item = items.children[item_num];
  95. //item.scrollIntoView();
  96. //window.scrollTo(0, window.scrollY - 70);
  97. let itemtime = item.querySelector('.bili-dyn-time');
  98. itemtime = itemtime.innerText;
  99. item_num = timestamp(itemtime,now);
  100. }
  101. //window.areufind = true;
  102. return item_num;
  103. }
  104. catch (err){
  105. console.log("%c###### 先别急, 页面尚未加载完 ######",window.color_red);
  106. //console.log(err);
  107. window.areufind = true;
  108. return null;
  109. }
  110. }
  111.  
  112. //实际运行的地方
  113. async function run(time,now,two = false,ddd){
  114.  
  115. let item_num = -1;
  116. let item_number = 0;
  117.  
  118. //妈的,再嵌套一个函数 - 遍历动态主函数
  119. async function checkitem(item,item_num){
  120. //如果存在
  121. item.scrollIntoView();
  122. window.scrollTo(0, window.scrollY - 70);
  123. item_number = item_number + 1;
  124.  
  125. //等待图片加载
  126. let itemimg = item.querySelectorAll('picture.b-img__inner');
  127. if(itemimg != undefined){
  128. for(let num of itemimg){
  129. //console.log("1 " + itemimg);
  130. let img1 = num.lastChild;
  131. //console.log("2 " + itemimg);
  132. let areuokimg = -1;
  133. if(img1.src.indexOf("none") != -1){
  134. console.log("# 跳过: " + img1.src);
  135. continue;
  136. }
  137. else{
  138. //img1.onerror = function() { areuokimg = false; };
  139. }
  140. while(img1.naturalWidth === 0 && window.areuskip != true){
  141. //忘记在这里写强制暂停了
  142. if(window.areufind == true){
  143. return;
  144. }
  145. if(img1.complete == true){
  146. console.log("%c# 图片加载失败: " + img1.src ,window.color_red);
  147. //areuokimg = -1;
  148. img1.src = img1.src;
  149. }
  150. else{
  151. console.log("# 等待图片加载: " + img1.src);
  152. }
  153. await delay(1000);
  154. }
  155. if(window.areuskip == true){
  156. window.areuskip = false;
  157. console.log("# 跳过: " + img1.src);
  158. continue;
  159. }
  160. }
  161. }
  162.  
  163. item_num = item_num + 1;
  164. return item_num;
  165. }
  166.  
  167. async function checknewitem(two){
  168. //检查是否到达世界的尽头
  169. let no_more = document.querySelector('.bili-dyn-list-no-more');
  170. let itemss = document.querySelector('.bili-dyn-list__items');
  171. //console.log(no_more);
  172. //console.log(itemss.length);
  173. if (no_more != undefined && itemss.length == undefined && two != 2) {
  174. console.log("%c# 你已经到达世界的尽头 #",window.color_red);
  175. console.log("%c完成!!!",window.color_blue);
  176. window.areufind = true;
  177. }
  178. else if (no_more != undefined && two == 2) {
  179. console.log("%c# 你已经到达世界的尽头 #",window.color_red);
  180. console.log("%c完成!!!",window.color_blue);
  181. window.areufind = true;
  182. }
  183. else if(window.areufind != true){
  184. //console.log("# 错误: \n" + err);
  185. console.log("%c# 遇到了一些错误, 尝试重试 #",window.color_red);
  186. await delay(1000);
  187. window.scrollTo(0, 0);
  188. window.scrollTo(0, document.documentElement.scrollHeight);
  189. }
  190. }
  191.  
  192. //首先判断当前DOM所在位置
  193. if(two == 2){
  194. item_num = finditem(item_num,two);
  195. if(item_num == null){
  196. return;
  197. }
  198. }
  199.  
  200. //主循环
  201. while(window.areufind != true){
  202. try{
  203. let items = document.querySelector('.bili-dyn-list__items');
  204. let item;
  205. if(two == true){
  206. item = items.firstChild;
  207. }
  208. else if(two == false){
  209. item = items.children[1];
  210. }
  211. //遍历操作在这里
  212. else if(two == 2){
  213. item = items.children[item_num];
  214. //console.log(item);
  215. if(item == undefined && window.areufind != true){
  216. while(item == undefined){
  217. console.log("%c# 遇到了一些错误, 尝试重试 #",window.color_red);
  218. window.scrollTo(0, 0);
  219. window.scrollTo(0, document.documentElement.scrollHeight);
  220. //window.scrollTo(0, document.documentElement.offsetHeight);
  221. //检查是否到底
  222. let no_more = document.querySelector(".bili-dyn-list-no-more");
  223. if(no_more != undefined) {
  224. window.areufind = true;
  225. break;
  226. }
  227. else{
  228. await delay(1000);
  229. item = items.children[item_num];
  230. //item_num = checkitem(item,item_num);
  231. }
  232. }
  233. if(item != undefined){
  234. item_num = await checkitem(item,item_num);
  235. }
  236. }
  237. else{
  238. item_num = await checkitem(item,item_num);
  239. }
  240. //window.areufind = true;
  241. //return;
  242. }
  243.  
  244. let itemtime;
  245. let itemtag;
  246. if(item != undefined){
  247. itemtime = item.querySelector('.bili-dyn-time');
  248. if(itemtime != null){ //正常获取动态上的时间
  249. itemtime = itemtime.innerText;
  250. itemtag = item.querySelector('.bili-dyn-tag__text');
  251. //itemtag = itemtag.innerText;
  252. console.log("> " + itemtime + " <");
  253.  
  254. //统统转成时间戳
  255. itemtime = timestamp(itemtime,now);
  256. }
  257. else{ //如果遇到 '1条动态被折叠' 的话
  258. itemtime = item.querySelector('.bili-dyn-item-fold__statement.fs-small');
  259. console.log("%c> " + itemtime.innerText + " <",window.color_red);
  260. itemtime = new Date();
  261. itemtime = itemtime.valueOf();
  262. }
  263.  
  264. console.log(itemtime);
  265. }
  266.  
  267. if(item != undefined){
  268. if(itemtime > time){
  269. if(two != 2){
  270. item.remove();
  271. item_number = item_number + 1;
  272. }
  273. }
  274. else if(itemtag != undefined){
  275. if(two == true){
  276. item.remove();
  277. item_number = item_number + 1;
  278. }
  279. }
  280. else{
  281. item.scrollIntoView();
  282. window.scrollTo(0, window.scrollY - 70);
  283. console.log("%c完成!!!",window.color_blue);
  284. window.areufind = true;
  285. }
  286. }
  287. else{
  288. await checknewitem(two);
  289. }
  290. }
  291. catch (err){
  292. console.log("%c# 错误: \n" + err.stack ,window.color_red);
  293. await checknewitem(two);
  294. }
  295. //areufind = true;
  296.  
  297. await delay(ddd);
  298.  
  299. //时间统计
  300. if(window.areufind == true){
  301. let nowtime = new Date();
  302. let spendtime = nowtime.valueOf() - now.valueOf();
  303. let hhh
  304. let mmm
  305. let sss
  306. if(spendtime >= 3600000){
  307. hhh = spendtime / 1000 / 60 / 60;
  308. }
  309. else{
  310. hhh = 0;
  311. }
  312. if(spendtime >= 60000){
  313. mmm = (spendtime - Math.trunc(hhh) * 3600000) / 1000 / 60;
  314. }
  315. else{
  316. mmm = 0;
  317. }
  318. sss = (spendtime - Math.trunc(hhh) * 3600000 - Math.trunc(mmm) * 60000) / 1000;
  319. console.log("%c###### 总计用时: " + Math.trunc(hhh) + "小时" + Math.trunc(mmm) + "分钟" + Math.trunc(sss) + "秒, 总计 " + item_number + " 项动态 ######",window.color_blue);
  320. }
  321. }
  322.  
  323. };
  324.  
  325. //接受参数
  326. window.bilidel = function(input,ddd = 1,two = false) {
  327. //console.log(window.areufind);
  328. let returns = "################################";
  329. //帮助
  330. if(input == "Help" || input == "help"){
  331. //console.log("帮助\n");
  332. //好麻烦
  333. let text = "%c#############################################################################################################\n";
  334. text = text + "#\t\t\t\t\t\t\t\t\t\t\t\t 介素幫助 \t\t\t\t\t\t\t\t\t\t\t\t#\n";
  335. text = text + "#############################################################################################################\n";
  336. text = text + "# bbdel\(\"指定日期\"\,\"停頓時間, 單位ms\"\,\"操縱類型\"\)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t#\n";
  337. text = text + "# bbdel\(\"list\"\)\t\t\t\t\t查詢當前動態的總數目\;\t\t\t\t\t\t\t\t\t\t\t\t\t\t#\n";
  338. text = text + "# bbdel\(\"stop\"\)\t\t\t\t\t終止任務運行\;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t#\n";
  339. text = text + "# bbdel\(\"skip\"\)\t\t\t\t\t跳過失效圖像部分\;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t#\n";
  340. text = text + "# bbdel\(\"help\"\)\t\t\t\t\t獲取幫助。\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t#\n";
  341. text = text + "#===========================================================================================================#\n";
  342. text = text + "# 舉個栗子\:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t#\n";
  343. text = text + "# bbdel\(\"2024-12-5\"\,\"1000\"\,\"2\"\)\t導航到 2024-12-5 的動態, 延時1000ms\;\t\t\t\t\t\t\t\t\t\t#\n";
  344. text = text + "# bbdel\(\"2024-12-5\"\)\t\t\t保留置頂, 清除至 2024-11-16 之間的動態 \(並不是真的把動態刪掉\)\;\t\t\t\t#\n";
  345. text = text + "# bbdel\(\"1733392922\"\,\"100\"\,\"1\"\)\t不保留置頂, 延時100ms, 清除至 2024-12-5 之間的動態 \(並不是真的把動態刪掉\)\。\t#\n";
  346. text = text + "#############################################################################################################";
  347. console.log(text,window.color_lightblue);
  348. return undefined;
  349. }
  350. if(window.areufind == false){
  351. if(input == "stop" || input == "Stop"){
  352. window.areufind = true;
  353. console.log("%c# 终止任务 #",window.color_red);
  354. }
  355. else if(input == "skip" || input == "Skip"){
  356. window.areuskip = true;
  357. console.log("%c# 尝试跳过 #",window.color_red);
  358. }
  359. else{
  360. console.log("%c\(#`O′\) 上一次任务尚未完成欸!!!",window.color_red);
  361. }
  362. return "################################";
  363. }
  364. if(input == "stop" || input == "Stop" || input == "skip" || input == "Skip"){
  365. console.log("%c\(#`O′\) 参数错误欸。",window.color_red);
  366. console.log("%c键入 bbdel\(\"help\"\) 以尋求幫助。",window.color_blue);
  367. }
  368. else if(input == "List" || input == "list"){
  369. bblist();
  370. return undefined;
  371. }
  372. else{
  373. //console.log(input);
  374.  
  375. let now = new Date();
  376.  
  377. let Y;
  378. let M;
  379. let D;
  380.  
  381. //给了目标日期
  382. if(input == "" || input == undefined || input == null){
  383. if(two == 2){
  384. input = "1970-1-1";
  385. }
  386. }
  387. if(input != "" && input != undefined && input != null){
  388. input = input.replace(/\//g, "-");
  389. input = input.replace(/年/g, "-");
  390. input = input.replace(/月/g, "-");
  391. input = input.replace(/日/g, "");
  392.  
  393. if((input.split("-").length - 1) == 0){
  394. if(input == "0"){
  395. input = "1970-1-1";
  396. }
  397. else if(input.length > 4){
  398. input = new Date(input * 1);
  399. console.log(input);
  400. input = input.getFullYear() + "-" + (input.getMonth() + 1) + "-" + input.getDate();
  401. }
  402. else if(input.length > 2){
  403. input = input + "-1-1";
  404. }
  405. else{
  406. input = now.getFullYear() + "-1-" + input;
  407. }
  408. }
  409.  
  410. Y = input.substring(0,input.indexOf("-"));
  411. M = input.substring(input.indexOf("-") + 1);
  412. if(M.indexOf("-") != -1){
  413. M = M.substring(0,M.indexOf("-"));
  414. }
  415. if((input.split("-").length - 1) > 1){
  416. D = input.substring((Y + "-" + M + "-").length);
  417. }
  418. else{
  419. D = 1;
  420. }
  421.  
  422. if((input.split("-").length - 1) > 2){
  423. console.log("%c\(#`O′\) 你参数写错了欸。",window.color_red);
  424. console.log("%c键入 bbdel\(\"help\"\) 以尋求幫助。",window.color_blue);
  425. return "################################";
  426. }
  427. else if((input.split("-").length - 1) == 1){
  428. if(Y.length > 2){
  429. D = 1;
  430. }
  431. else{
  432. D = M;
  433. M = Y;
  434. Y = now.getFullYear();
  435. }
  436. }
  437. }
  438.  
  439. //没给具体日期
  440. else{
  441. let item_time = finditem(-1,two,now);
  442. item_time = new Date(item_time + 86400000);
  443. Y = item_time.getFullYear();
  444. M = item_time.getMonth() + 1;
  445. D = item_time.getDate();
  446. }
  447.  
  448. console.log("年: " + Y);
  449. console.log("月: " + M);
  450. console.log("日: " + D);
  451.  
  452. let time = new Date(Y + "-" + M + "-" + D);
  453. time = time.valueOf();
  454.  
  455. console.log("当前时间戳: " + now.valueOf());
  456. console.log("目标时间戳: " + time);
  457.  
  458. //要不要把置顶给干了
  459. if(two == 2){
  460. //two = 2;
  461. console.log("准备开始遍历动态");
  462. }
  463. else{
  464. if(two == 1 && Number.isNaN(time) != true){
  465. two = true;
  466. }
  467. else if(two == 0 && Number.isNaN(time) != true){
  468. two = false;
  469. }
  470. else{
  471. console.log("%c\(#`O′\) 你参数写错了欸。",window.color_red);
  472. console.log("%c键入 bbdel\(\"help\"\) 以尋求幫助。",window.color_blue);
  473. return "################################";
  474. }
  475. console.log("是否把置顶给干了: " + two);
  476. //防误操作,先询问
  477. let areudel = prompt("需要删除 " + Y + "-" + M + "-" + D + " 之前的动态吗? (Y/N)", "N");
  478. if(areudel == "Y" || areudel == "y" || areudel == "yes" || areudel == "Yes" || areudel == 1 || areudel == true){
  479. console.log("%c出发喽~~~",window.color_blue);
  480. }
  481. else{
  482. console.log("%c# 任务取消 #",window.color_red);
  483. return "################################";
  484. }
  485. }
  486.  
  487. window.areufind = false;
  488. run(time,now,two,ddd);
  489. if(window.areufind == false){
  490. returns = undefined;
  491. }
  492. }
  493. return returns;
  494. };
  495.  
  496. window.Bilidel = window.bilidel
  497. window.bbdel = window.bilidel
  498. window.BBdel = window.bilidel
  499.  
  500. //计数
  501. let bblist = function(){
  502. try{
  503. let items = document.querySelector('.bili-dyn-list__items');
  504. let item = items.querySelectorAll('.bili-dyn-list__item');
  505. let no_more = document.querySelector('.bili-dyn-list-no-more');
  506. if(item != undefined || item != null){
  507. let tip;
  508. if(no_more == undefined || no_more == null)
  509. {
  510. tip = ", 尚未全部加载完成欸。"
  511. }
  512. else{
  513. tip = ", 已全部加载完成。"
  514. }
  515. console.log("%c###### 总计 " + item.length + " 项动态" + tip + " ######",window.color_blue);
  516. }
  517. else{
  518. console.log("%c# 找不到任何动态欸 #",window.color_red);
  519. }
  520. }
  521. catch{
  522. console.log("%c# 找不到任何动态欸 #",window.color_red);
  523. }
  524. return undefined;
  525. }
  526.  
  527. })();

QingJ © 2025

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