您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
bilibili弹幕词云
当前为
// ==UserScript== // @name 弹幕词云 // @namespace http://tampermonkey.net/ // @version 2.0 // @description bilibili弹幕词云 // @author You // @match https://www.bilibili.com/bangumi/play/* // @match https://www.bilibili.com/video/* // @grant none // @require https://cdn.bootcdn.net/ajax/libs/wordcloud2.js/1.1.2/wordcloud2.min.js // ==/UserScript== (function() { 'use strict'; function geo(){ console.log("开始") // setInterval(modi,1000); init(); } //======变量======= var canv; var btnTextE; var baocun;//保存按钮 var baocun2;//保存按钮 var holder;//包裹词云 var canvP;//词云div var title; var hasCi=false;//词云是否显示 let s=[]//弹幕 let sai=[]//词频 let dmBar; let fail=false; let tez=[0,1]//[最大值,最小值,中位数] let count=350//最大词数 let reqParm=[0,1] let liFac=0.5;// let weiFac=0.5;//字体权重 let colorTable=['#9794DB','#8240BF','#6344C1','#4840BF','#444EC1','#4461C1','#5E90C9','#4BABC3','#66C7CC','#66CCBD','#53C69F','#BDD071','#C9965E','#C15444','#BF4640','#D13D3D','#FF533E'] let peiIdx=0; let sepei=[//背景色,高频色,低频色,遮罩 ['#AC1F18',[28,13,26],[54,41,47],'//i0.hdslb.com/bfs/article/874074999995e6981d7602a7d5a770043a10b932.png@256w_256h.webp','对联红'], ['#621d34',[226,225,228],[97,113,114],'//i0.hdslb.com/bfs/article/874074999995e6981d7602a7d5a770043a10b932.png@256w_256h.webp','鹞冠紫'], ['#ed9db2',[51,20,30],[181,152,162],'//i0.hdslb.com/bfs/article/874074999995e6981d7602a7d5a770043a10b932.png@256w_256h.webp','豇豆红'], ['#2775b6',[255,255,255],[73,92,105],'//i0.hdslb.com/bfs/article/874074999995e6981d7602a7d5a770043a10b932.png@256w_256h.webp','景泰蓝'], ['#1ba784',[173, 213, 162],[65, 174, 60],'//i0.hdslb.com/bfs/article/874074999995e6981d7602a7d5a770043a10b932.png@256w_256h.webp','竹绿'], ['#fed71a',[140, 194, 105],[140, 194, 105],'//i0.hdslb.com/bfs/article/874074999995e6981d7602a7d5a770043a10b932.png@256w_256h.webp','佛手黄'], ['#f26b1f',[249, 233, 205],[240, 156, 90],'//i0.hdslb.com/bfs/article/874074999995e6981d7602a7d5a770043a10b932.png@256w_256h.webp','金黄'], ['#500A16',[226,225,228],[97,113,114],'//i0.hdslb.com/bfs/article/d2bba9afdcd82302d8d387696e076da26050fb37.jpg@1320w_1760h.webp','浪'], ]//背景+文字颜色2 //======函数====== function drag(obj){ obj.onmousedown = function(e){ // 鼠标点击物体那一刻相对于物体左侧边框的距离=点击时的位置相对于浏览器 // 最左边的距离-物体左边框相对于浏览器最左边的距离,纵向同理 var divX = e.clientX - this.offsetLeft; var divY = e.clientY - this.offsetTop; document.onmousemove = function(e){ var disX = e.clientX - divX; var disY = e.clientY - divY; // 移动时重新得到物体的距离,解决拖动时出现晃动现象 obj.style.top = disY + "px"; obj.style.left = disX + "px"; document.onmouseup = function(){ // 鼠标抬起时不再移动 // 预防鼠标弹起来后还会循环(即预防鼠标放上去的时候还会移动) document.onmousedown = document.onmousemove = null; } } } } var init=()=>{ var sty=document.createElement("style"); sty.innerHTML=` .blura{ animation: 1s animatea 1 linear; } .blura:hover{ animation: 2s animateb 1 linear; } @keyframes animatea{ 0%{ text-shadow: 0 0 0 white; } 50%{ color: rgba(238, 235, 235, 0.8); text-shadow: 0 0 30px rgb(216, 227, 243); } 100%{ text-shadow: 0 0 40px white; } } @keyframes animateb{ 0%{ text-shadow: 0 0 0px rgba(255,255,255,0); } 50%{ color: rgba(255, 255, 255, 0.925); text-shadow: 0 0 10px rgb(184, 245, 242); } 100%{ text-shadow: 0 0 0 white; } } @keyframes ac{ 0%{ color: rgba(33, 33, 33, 0.9); } 50%{color: rgba(238, 235, 235, 0.9);} 100%{ color: rgba(33, 33, 33, 0.9); } } @keyframes ad{ 0%{ color: rgba(33, 33, 33, 0.9); } 50%{color: rgba(238, 235, 235, 0.9);} 100%{ color: rgba(33, 33, 33, 0.9); } } .btnBg{ position:relative;top:-17px;background: linear-gradient(45deg , #e5c0ff, skyblue);border-radius: 4px;filter: blur(15px);width: 100%;height: 100%; } .blr-btn{ user-select:none;overflow:hidden;position:fixed;top:56px;z-index:999999;left:10px;width: 54px;height: 26px;border-radius: 3px;font-size: 18px;padding: 5px;cursor: pointer; width:fit-content; width:-webkit-fit-content; width:-moz-fit-content; animation: 0.5s ad 1 linear; } .blr-btn:hover{ animation: 0.5s ac 1 linear; } .fEl{ width: 100%; height: 25px; padding: 5px 0px; color: cornsilk; } .bar-indicator{ height: 5px; background-color: rgb(76 173 104); width: 80%; } .fEl:hover{ background-color: rgba(96, 160, 243, 0.363); transition:1s; cursor: pointer; } .frequency{ width: 10%; float: right; font-size: 14px; padding: 9px 5px 0 0; text-align: right; text-shadow: -2px -1px 8px #bdfa9d; } .danmu-word{ padding: 5px; font-size: 12px; line-height: 15px; } ` document.head.append(sty) //按钮 let cibtn=newBtn(document.body,ciw,10,54,'词云'); btnTextE=cibtn.tx; let saveBtn=newBtn(document.body,()=>{ saveDiv(holder) },10,100,'保存') let saveBtn2=newBtn(document.body,()=>{ saveDiv(canvP) },10,140,'仅文字保存') let dmBarBtn=newBtn(document.body,()=>{ if(dmBar.hidden) { dmBar.hidden=false $(dmBar).fadeIn( 300 , 'linear') } else{ dmBar.hidden=true; dmBar.style.display='none' } },60,54,'列表') baocun=saveBtn.bt baocun.style.display='none' baocun2=saveBtn2.bt baocun2.style.display='none' //词云画布 canv=document.createElement("div"); canvP=document.createElement("div");//背景 canvP.append(canv); canv.style="height: 100%;width: 100%;" //渐变 // canvP.style="opacity:0.96;border: 5px solid rgb(237 237 237 / 74%);height: 700px;width: 1200px;position:fixed;top:50px;left:60px;z-index:999999;background:linear-gradient(311deg, rgb(234 229 229), rgb(233 241 227), rgb(218 231 230));"; //单色background-image: url(https://i0.hdslb.com/bfs/album/d16f34b89e59174bd066a27101bf6b9c92d16615.jpg); canvP.style="background-image: url(//i0.hdslb.com/bfs/article/874074999995e6981d7602a7d5a770043a10b932.png@256w_256h.webp);opacity:0.96;border: 5px solid rgb(237 237 237 / 74%);height: 700px;width: 1200px;background-color: rgb(236, 43, 36);"; holder=document.createElement('div') holder.style="position:fixed;top:40px;left:80px;z-index:999999;" holder.setAttribute("hidden",true); title=document.createElement("span") title.style="font-size:10px;color:rgb(225,235,215);position:absolute;z-index:10;background-color:#888" holder.append(canvP) holder.append(title) document.body.append(holder) drag(holder) //弹幕列表 dmBar=document.createElement('div') dmBar.style='background-color:rgb(128 204 150 / 96%);position: absolute;z-index: 999990;width: 320px;border: 4px solid #c1f8db38;' dmBar.style.display='none' dmBar.hidden=true drag(dmBar) } var modi=()=>{ var dms=$(".b-danmaku"); for(var i=0;i<dms.length;i++){ if(dms[i].innerHTML.indexOf("div")==-1){ var s=dms[i].style.fontSize.replace("px","") var l=dms[i].innerHTML.length*s+"px" dms[i].innerHTML=` <div style="overflow: hidden;height: `+dms[i].style.fontSize+`;width: `+l+`"> <div style="position: relative;top: -32px;">`+dms[i].innerHTML+`</div> <div style="width: 100%; height: 100%; background: linear-gradient(45deg , #e5c0ff, skyblue); border-radius: 4px; filter: blur(20px); position: relative; top: -90px;"></div> </div>` } } } //产生词云 function ciw(){ if(hasCi) { holder.setAttribute("hidden",true); $(baocun,baocun2).fadeOut( 1000 , 'linear' , ()=>{ }) $(baocun2).fadeOut( 1000 , 'linear' , ()=>{ }) btnTextE.innerText='词云' hasCi=false; return; }; console.log('生成词云'); btnTextE.innerText='→_→'; if(sai.length==0||window.cid!=reqParm[0]) analysi(); peiIdx=peiIdx==sepei.length-1?0:peiIdx+1 holder.removeAttribute("hidden"); btnTextE.innerText='关闭' backgroundImag() WordCloud([canv], { list: sai, color: colorw, //'random-light' backgroundColor: '', gridSize: 18, weightFactor: weiFac,//200/tez[0],//被除数为最大字号 fontFamily: '楷体', rotateRatio: 0.5, classes: "blura", rotationSteps: 2 } ); hasCi=true; $(baocun).fadeIn( 1000 , 'linear') $(baocun2).fadeIn( 1000 , 'linear') } //上色 let colorw=(wd,weight)=>{ //tez[0]红色 #ff0000 //1=>蓝色 #0000ff // console.log(wd,weight,tez[0]) let i=sai.findIndex(e=>e[0]==wd); let v=i/sai.length; // let v=parseInt(colorTable.length*i/sai.length) // return colorTable[v]; let s=sepei[peiIdx][1] let e=sepei[peiIdx][2] let colo='rgb(' for(let x in s){ colo+=(parseInt(s[x]+v*(e[x]-s[x])))+',' } return colo.substr(0,colo.lastIndexOf(','))+')' } let analysi=()=>{ //清空 s=[]; sai=[]; loadParam() reCalcFac() console.log("等待弹幕获取完成") btnTextE.innerText='^_^' getOneSeg(1) //计算weiFac if(sai.length>count) sai.splice(count) let siz=0; sai.forEach(e=>siz+=e[0].length*e[1]*e[1]) let bgSize=canvP.style.height.replace("px","")*canvP.style.width.replace("px","") weiFac=Math.sqrt(bgSize/siz) tez[0]=sai[0][1] tez[1]=sai.slice(-1)[0][1] tez[2]=sai[parseInt(sai.length/2)][1] console.log("大小中",tez) console.log("筛选结果:",sai) dmLiebiao()// } let getOneSeg=(seg)=>{ let regex=/:.(.*?)[�@]/ $.ajax({ url:'https://api.bilibili.com/x/v2/dm/web/seg.so?type=1&oid='+reqParm[0]+'&pid='+reqParm[1]+'&segment_index='+seg, data:{}, async:false, cache:false, ifModified :true, type:'GET', success:function(re, textStatus, xhr){ //成功回调函数 if(xhr.status!=200) { console.log("失败点:",seg) fail=true return; } let ss=re.split('\n'); ss.forEach(e=>{ let dm=regex.exec(e); if(dm&&dm[1]) s.push(dm[1]) }) console.log(s); //分析进行 cia(1) //清空s s=[] sleep(500) getOneSeg(seg+1) }, error:function (err){ //失败回调函数 fail=true; console.log("失败点:",seg) console.log(err); } }); } function cia(l){ console.log('分析弹幕...') btnTextE.innerText='>_<' let wds=[] s.forEach(e => { e=e.replace(/[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]/g,""); ctin(wds,e) }); wds.forEach(e=>{ if(e[1]>=l) { sai.push(e) } }) sai.sort((a,b)=>b[1]-a[1]);//降序 } function ctin(a,b){ var h=true; for(let i in a){ if(a[i][0].indexOf(b)>-1||xiangsi(a[i][0],b)){ a[i][1]+=1; h=false; } } if(h){ a.push([b,0]) } } let xiangsi=(a,b)=>{ if(xiangsi0(a,b)||xiangsi0(b,a)) return true; return false; } let xiangsi0=(a,b)=>{ let m=a.split('') let c=0; m.forEach(e=>{ if(b.indexOf(e)>-1) c++; }) if(c/m.length>=liFac) return true; return false; } let loadParam=()=>{ reqParm= [window.cid,window.aid] console.log('找到参数:',reqParm) } //设置词云宽高和筛选因子 let reCalcFac=()=>{ let m= parseInt(document.querySelector('.bilibili-player-video-info-danmaku-number').innerText); let titleEl=document.querySelector('#media_module > div > a') if(!titleEl) titleEl=document.querySelector('#viewbox_report > h1 > span') title.innerText="视频标题:"+titleEl.innerText+" "+new Date() if(m<1000) { liFac=0.5 }else{ liFac=0.5+(m-1000)/10000; if(liFac>1) liFac=1; } let w=window.innerWidth-160; let h=window.innerHeight-70; canvP.style.width=w+'px' canvP.style.height=h+'px' holder.style.width=(10+w)+'px' holder.style.height=(10+h+17.6)+'px' } let dmLiebiao=()=>{ dmBar.innerHTML=''// if(null==dmBar.parent){ let p=document.querySelector('#app > div.v-wrap > div.r-con'); if(null==p) p=document.querySelector('#app > div.plp-r'); p.prepend(dmBar) } sai.forEach(e=>{ let fe=document.createElement('div'); fe.className='fEl'; let dw=document.createElement('span'); dw.className='danmu-word'; dw.innerHTML=e[0] if(e[0].length>21){ dw.innerText=e[0].substr(0,21)+"..." } let f=document.createElement('div'); f.className="frequency"; f.innerText=e[1] let bi=document.createElement('div'); bi.className='bar-indicator' bi.style='width:'+(Math.round(80*e[1]/tez[0]))+'%' fe.append(dw) fe.append(f) fe.append(bi) dmBar.append(fe) }) } let backgroundImag=()=>{ console.log("主题更改:",sepei[peiIdx][4]) canvP.style.backgroundImage='url("'+sepei[peiIdx][3]+'")' canvP.style.backgroundColor=sepei[peiIdx][0] // $.ajax({ // url:'http://zhongguose.com/img/texture.png', // type:'get', // success:(data)=>{ // console.log(daata) // var img=new Blob([data],{type:"png"}) // var url=URL.createObjectURL(img); // canvP.style.backgroundImage='url("'+url+'")' // } // }) } //保存div内容为png function saveDiv(div){ //1.将div转成svg var divContent = div.innerHTML; let w=div.offsetWidth; let h=div.offsetHeight if(w==0||h==0){ w=div.firstElementChild.offsetWidth h=div.firstElementChild.offsetHeight } var data = "data:image/svg+xml," + "<svg xmlns='http://www.w3.org/2000/svg' width='"+w+"' height='"+h+"'>" + "<foreignObject width='100%' height='100%'>" + "<div xmlns='http://www.w3.org/1999/xhtml' style='font-size:16px;font-family:Helvetica'>" + divContent + "</div>" + "</foreignObject>" + "</svg>"; var img = new Image(); img.src = data; // document.body.appendChild(img); //2.svg转成canvas var canvas = document.createElement('canvas'); //准备空画布 img.onload=()=>{ var dpr =window.devicePixelRatio; canvas.width = img.width; canvas.height =img.height; canvas.style.width =dpr*w + "px" canvas.style.height =dpr*h + "px" var context = canvas.getContext('2d'); //取得画布的2d绘图上下文 context.drawImage(img, 0, 0); var a = document.createElement('a'); a.href = canvas.toDataURL('image/png'); //将画布内的信息导出为png图片数据 let titleEl=document.querySelector('#media_module > div > a') if(!titleEl) titleEl=document.querySelector('#viewbox_report > h1 > span') a.download =titleEl.innerText+(new Date()).getTime()+".png"; //设定下载名称 a.click() } } //生产按钮 function newBtn(p,f,left,top,word){ var cibtn= document.createElement("div"); var cibtnBg= document.createElement("div"); cibtnBg.className='btnBg' let TextE=document.createElement('span') TextE.innerText=word cibtn.append(TextE) cibtn.className='blr-btn' cibtn.append(cibtnBg); cibtn.style.left=left+'px'; cibtn.style.top=top+'px'; // moveAble(cibtn,f)//setTimeOut还是卡 cibtn.onclick=f; p.append(cibtn) return {bt:cibtn,bg:cibtnBg,tx:TextE} } function sleep(numberMillis) { var now = new Date(); var exitTime = now.getTime() + numberMillis; while (true) { now = new Date(); if (now.getTime() > exitTime) return; } } geo(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址