您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
B站动态按照日期归类。仅作为DD调研用(考古也算的话),若有滥用等问题概不负责诶嘿。
// ==UserScript== // @name B站动态按照日期归类 // @namespace http://tampermonkey.net/ // @version 0.2 // @description B站动态按照日期归类。仅作为DD调研用(考古也算的话),若有滥用等问题概不负责诶嘿。 // @author 太陽闇の力 // @include /https?:\/\/space\.bilibili\.com/ // @grant GM_addStyle // @grant GM_registerMenuCommand // @license MIT // ==/UserScript== (function() { let flag = true; let flag2 = true; GM_registerMenuCommand("启动归类",async()=>{ if(!flag)return; let cardList={}; let dateList = []; const uid = /\d+/.exec(location.pathname)[0]; const relation={"DYNAMIC_TYPE_WORD":"文本","DYNAMIC_TYPE_DRAW":"图片","DYNAMIC_TYPE_AV":"视频","DYNAMIC_TYPE_FORWARD":"转发","DYNAMIC_TYPE_LIVE_RCMD":"直播","DYNAMIC_TYPE_ARTICLE":"专栏","DYNAMIC_TYPE_COMMON_VERTICAL":"漫画","DYNAMIC_TYPE_COURSES_SEASON":"课程","DYNAMIC_TYPE_MUSIC":"音乐","DYNAMIC_TYPE_COMMON_SQUARE":"H5页"} let offset = ""; do{ let url = `https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?offset=${offset}&host_mid=${uid}` let res =await fetcher(url); for (let item of res.data.items){ const cardType = relation[item.type]||"未知"; const cardId = item.id_str; const cardTime = item.modules.module_author.pub_ts*1000; const cardDate = fmtDate(cardTime); const content = item.modules.module_dynamic?.desc?.text||item.modules.module_dynamic.major?.archive?.title||item.modules.module_dynamic.major?.article?.title||item.modules.module_dynamic.major?.common?.title||JSON.parse(item.modules.module_dynamic?.major?.live_rcmd?.content||'{}')?.live_play_info?.title||item.modules.module_dynamic.major?.music?.title||item.modules.module_dynamic.major?.courses?.title; if(!cardList[cardDate]){ cardList[cardDate] = []; } cardList[cardDate].push([cardId,content,cardType]); dateList.push(cardTime); } offset = res.data.offset; }while(offset!=""); if(dateList.length>1){ if(dateList[0]<dateList[1]){ let temp = dateList[0]; dateList[0] = dateList[1]; dateList[1] = temp; } } dateList = dateList.map(fmtDate); function fmtDate(obj){ var date = new Date(obj); var y = 1900+date.getYear(); var m = "0"+(date.getMonth()+1); var d = "0"+date.getDate(); return y+"-"+m.substring(m.length-2,m.length)+"-"+d.substring(d.length-2,d.length); } async function fetcher(url) { const res = await fetch(url) if (!res.ok) { throw new Error(res.statusText) } const data = await res.json() if (data.code != 0) { throw new Error("B站API请求错误:" + data.message) } return data } GM_addStyle(` * { margin: 0; padding: 0; } ul { list-style: none; } #schedule-box { width: 320px; margin-bottom: 10px; padding: 10px 20px; font-size: 13px; } .schedule-hd { display: flex; justify-content: space-between; padding: 0 15px; } .today { flex: 1; text-align: center; } .ul-box { overflow: hidden; } .ul-box>li { float: left; width: 14.28%; text-align: center; padding: 5px 0; } .other-month { color: #999999; } .disabled { pointer-events: none; background-color: #eeeeee; color: #999999; } .current-month { color: #333333; } .today-style { border-radius: 50%; background: #58d321; } .arrow { cursor: pointer; } .dayStyle { display: inline-block; width: 35px; height: 35px; border-radius: 50%; text-align: center; line-height: 35px; cursor: pointer; } .current-month>.dayStyle:hover { background: #ffba5a; color: #ffffff; } .today-flag { background: #00C2B1; color: #fff; } .boxshaw { box-shadow:2px -4px 15px 2px #e3e3e3; } .selected-style { background-color: #00BDFF; color: #ffffff; } .active-style { background: #ffba5a; color: #ffffff; } .today { text-align: center; color: #8ac6d1; padding: 5px 0 0; font-weight: bold; cursor: pointer; font-size: 15px; } @font-face {font-family: "iconfont"; } .iconfont { font-family:"iconfont" !important; font-size:16px; font-style:normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .icon-115rightarrowheads:before { content: "▶"; } .icon-111arrowheadright:before { content: "▷"; } .icon-116leftarrowheads:before { content: "◀"; } .icon-112leftarrowhead:before { content: "◁"; } table { font-family: arial, sans-serif; border: 1px solid #dddddd80; border-radius: 8px; border-collapse:separate; width: 100%; } td{ border: 0; text-align: left; padding: 8px; } #tdiv::-webkit-scrollbar{ display:none } ` ) var div = document.createElement('div'); div.style.cssText = 'max-width:360px;position:fixed;top:70px;left:200px;z-index:999;background-color:#ffffffc2;border-bottom-right-radius:8px;border-bottom-left-radius:8px;'; const closeButton = window.document.createElement('button'); closeButton.innerText = "ㄨ"; closeButton.style.cssText = 'float:right;border:none;cursor:pointer;background-color:#ffffffc2;border-radius:1px;color:red;'; const collapseButton = window.document.createElement('button'); collapseButton.innerText = "─"; collapseButton.style.cssText = 'width:13.34px;height:17px;float: right;margin-right:3px;border:none;cursor:pointer;background-color:#ffffffc2;border-radius:1px;'; var sb = document.createElement('div'); sb.id = 'schedule-box'; sb.classList.add('boxshaw'); var tb = document.createElement('table'); var tdiv = document.createElement('div'); tdiv.id = "tdiv"; tdiv.style.cssText ="max-height:200px;overflow-y:scroll;overflow-x:hidden;" tdiv.append(tb) div.append(closeButton); div.append(collapseButton); div.append(sb); tdiv.append(tb); div.append(tdiv); document.body.appendChild(div); closeButton.addEventListener("click",()=>{ div.remove(); flag = true; flag2 = true; }); collapseButton.addEventListener("click",()=>{ if(flag2){ sb.style.display = "none"; tdiv.style.display = "none"; closeButton.style.display = "none"; collapseButton.style.height = "20px"; collapseButton.style.width = "15.7px"; flag2 = false; }else{ sb.style.display = "block"; tdiv.style.display = "block"; closeButton.style.display = "block"; collapseButton.style.height = "17px"; collapseButton.style.width = "13.34px"; flag2 = true; } }); var mySchedule = new Schedule({ el: '#schedule-box', //容器元素 disabledBefore: dateList[dateList.length-1], //禁用此日期之前 disabledAfter: dateList[0], //禁用此日期之后 selectedDate: dateList, //选中的日期 showToday: true, //回到今天 clickCb: function (date) { tb.innerHTML=""; if(cardList[date]){ for(let i of cardList[date]){ const cardurl = `https://t.bilibili.com/${i[0]}?tab=2` tb.innerHTML += `<tr><td><a href="${cardurl}" target="_blank">${i[1]}</a></td><td>${i[2]}</td></tr>`; } } } }); flag = false; }); //工具函数 //配置合并 function extend(def, opt, override) { for (var k in opt) { if (opt.hasOwnProperty(k) && (!def.hasOwnProperty(k) || override)) { def[k] = opt[k] } } return def; } //日期格式化 function concatDate(y, m, d) { var symbol = '-'; if (m) { m = (m.toString())[1] ? m : '0' + m; } if (d) { d = (d.toString())[1] ? d : '0' + d; } return y + (m ? symbol + m : '') + (d ? symbol + d : ''); } //得到时间戳 function getTimeStamp(d) { var date = new Date(d); if (isNaN(date.getTime())) { console.error(d + ' is invalid date'); return ''; } return date.getTime(); } //polyfill if (!Array.isArray) { Array.isArray = function (arg) { return Object.prototype.toString.call(arg) === '[object Array]'; }; } //过滤非日期,格式化日期 function filterDate(arr) { if(!Array.isArray(arr)) { return []; } arr = arr || []; var dateArr = []; for (var i = 0; i < arr.length; i++) { var item = arr[i]; var date = new Date(item); if (isNaN(date.getTime())) { console.error(item + ' is invalid date') } else { var y = date.getFullYear(); var m = date.getMonth(); var d = date.getDate(); var dateStr = concatDate(y, m + 1, d); dateArr.push(dateStr); } } return dateArr; } function Schedule(opta) { var def = {}, opt = extend(def, opta, true), curDate = opt.date ? new Date(opt.date) : new Date(), disabledDate = opt.disabledDate ? filterDate(opt.disabledDate) : [], selectedDate = opt.selectedDate ? filterDate(opt.selectedDate) : [], disabledBefore = opt.disabledBefore ? getTimeStamp(opt.disabledBefore) : '', disabledAfter = opt.disabledAfter ? getTimeStamp(opt.disabledAfter) : '', showToday = opt.showToday, year = curDate.getFullYear(), month = curDate.getMonth(), currentYear = curDate.getFullYear(), currentMonth = curDate.getMonth(), currentDay = curDate.getDate(), activeDate = '', el = document.querySelector(opt.el) || document.querySelector('body'), _this = this; var bindEvent = function () { el.addEventListener('click', function (e) { switch (e.target.id) { case 'nextMonth': _this.nextMonthFun(); break; case 'nextYear': _this.nextYearFun(); break; case 'prevMonth': _this.prevMonthFun(); break; case 'prevYear': _this.prevYearFun(); break; case 'todayBtn': _this.renderToday(); break; default: break; }; if (e.target.className.indexOf('currentDate') > -1) { activeDate = e.target.title; opt.clickCb && opt.clickCb(activeDate); render(); } }, false) } var init = function () { var scheduleHd = '<div class="schedule-hd">' + '<div>' + '<span class="arrow icon iconfont icon-116leftarrowheads" id="prevYear" ></span>' + '<span class="arrow icon iconfont icon-112leftarrowhead" id="prevMonth"></span>' + '</div>' + '<div class="today"></div>' + '<div>' + '<span class="arrow icon iconfont icon-111arrowheadright" id="nextMonth"></span>' + '<span class="arrow icon iconfont icon-115rightarrowheads" id="nextYear"></span>' + '</div>' + '</div>' var scheduleWeek = '<ul class="week-ul ul-box">' + '<li>日</li>' + '<li>一</li>' + '<li>二</li>' + '<li>三</li>' + '<li>四</li>' + '<li>五</li>' + '<li>六</li>' + '</ul>' var scheduleBd = '<ul class="schedule-bd ul-box" ></ul>'; var todayBtn = '<div id="todayBtn" class="today">今天</div>' el.innerHTML = scheduleHd + scheduleWeek + scheduleBd + (showToday ? todayBtn : ''); bindEvent(); render(); } var render = function () { var fullDay = new Date(year, month + 1, 0).getDate(), //当月总天数 startWeek = new Date(year, month, 1).getDay(), //当月第一天是周几 total = (fullDay + startWeek) % 7 == 0 ? (fullDay + startWeek) : fullDay + startWeek + (7 - (fullDay + startWeek) % 7),//元素总个数 lastMonthDay = new Date(year, month, 0).getDate(), //上月最后一天 eleTemp = []; for (var i = 0; i < total; i++) { var nowDate = concatDate(year, month + 1, (i + 1 - startWeek)); var nowTimestamp = new Date(nowDate).getTime(); var isDisbale = disabledDate.indexOf(nowDate) > -1; var isSelected = selectedDate.indexOf(nowDate) > -1; if (i < startWeek) { eleTemp.push('<li class="other-month"><span class="dayStyle">' + (lastMonthDay - startWeek + 1 + i) + '</span></li>') } else if (i < (startWeek + fullDay)) { var addClass = ''; if (isDisbale) { addClass = 'disabled' } else { isSelected && (addClass = 'selected-style'); activeDate == nowDate && (addClass = 'active-style'); concatDate(currentYear, currentMonth + 1, currentDay) == nowDate && (addClass = 'today-flag'); } if (disabledBefore && nowTimestamp < disabledBefore) { addClass = 'disabled' } if (disabledAfter && nowTimestamp > disabledAfter) { addClass = 'disabled' } eleTemp.push('<li class="current-month" ><span title=' + nowDate + ' class="currentDate dayStyle ' + addClass + '">' + (i + 1 - startWeek) + '</span></li>') } else { eleTemp.push('<li class="other-month"><span class="dayStyle">' + (i + 1 - (startWeek + fullDay)) + '</span></li>') } } el.querySelector('.schedule-bd').innerHTML = eleTemp.join(''); el.querySelector('.today').innerHTML = concatDate(year, month + 1); }; this.nextMonthFun = function () { if (month + 1 > 11) { year += 1; month = 0; } else { month += 1; } render(); opt.nextMonthCb && opt.nextMonthCb(year, month + 1); }; this.nextYearFun = function () { year += 1; render(); opt.nextYeayCb && opt.nextYeayCb(year, month + 1); }; this.prevMonthFun = function () { if (month - 1 < 0) { year -= 1; month = 11; } else { month -= 1; } render(); opt.prevMonthCb && opt.prevMonthCb(year, month + 1); }; this.prevYearFun = function () { year -= 1; render(); opt.prevYearCb && opt.prevYearCb(year, month + 1); } this.renderToday = function () { if (year === currentYear && month === currentMonth) { return; } year = currentYear; month = currentMonth; render(); } init(); } })();