弹幕词云

bilibili弹幕词云

À partir de 2021-04-13. Voir la dernière version.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         弹幕词云
// @namespace    http://tampermonkey.net/
// @version      0.1
// @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';
    geo();
    // Your code here...
    function geo(){
    console.log("开始")
  //  setInterval(modi,1000);
   init();
}
//======变量=======
var canv;
var canvP;//词云div
var hasCi=false;//词云是否显示
let s=[]//弹幕
let sai=[]//词频
let fail=false;
let tez=[0]//[最大值]
let reqParm=[0,1]
let colorTable=['ffff00','ffff33','ffff66','ffff99','ffffcc','ffffff','ffcc00','ffcc33','ffcc66','ffcc99','ffcccc','ffccff','ff9900','ff9933','ff9966','ff9999','ff99cc','ff99ff','ff6600','ff6633','ff6666','ff6699','ff66cc','ff66ff','ff3300','ff3333','ff3366','ff3399','ff33cc','ff33ff','ff0000','ff0033','ff0066','ff0099','ff00cc','ff00ff']
//======函数======


let moveAble=function(dv,clickFun){
  var x = 0;
  var y = 0;
  var l = 0;
  var t = 0;
  var isDown = false;
  var moved=false;
  //鼠标按下事件
  dv.onmousedown = function(e) {
      //获取x坐标和y坐标
      x = e.clientX;
      y = e.clientY;

      //获取左部和顶部的偏移量
      l = dv.offsetLeft;
      t = dv.offsetTop;
      //开关打开
      isDown = true;
      //设置样式
  }
  //鼠标移动
  window.onmousemove = function(e) {
      if (isDown == false) {
          return;
      }
      //获取x和y
      var nx = e.clientX;
      var ny = e.clientY;
      //计算移动后的左偏移量和顶部的偏移量
      var nl = nx - (x - l);
      var nt = ny - (y - t);
      moved=true;
      dv.style.left = nl + 'px';
      dv.style.top = nt + 'px';
  }
  //鼠标抬起事件
  dv.onmouseup = function() {
      if(moved) {
          moved=false;
      }else if(clickFun){
          clickFun();
      }
      //开关关闭
      isDown = false;
  }
}
var init=()=>{
  var cibtn= document.createElement("div");
  var cibtnBg= document.createElement("div");
  cibtnBg.style="position:relative;top:-17px;background: linear-gradient(45deg , #e5c0ff, skyblue);border-radius: 4px;filter: blur(15px);width: 54px;height: 30px;"
  cibtn.innerText='词云'
  cibtn.style='user-select:none;overflow:hidden;position:fixed;top:20px;z-index:999999;left:40px;width: 54px;height: 30px;border-radius: 3px;font-size: 22px;padding: 4px;cursor: pointer;'
  cibtn.append(cibtnBg);
  moveAble(cibtn,ciw)
  document.body.append(cibtn)
  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; }
  }`
  document.head.append(sty)
  canv=document.createElement("div");
  canvP=document.createElement("div");
  canvP.append(canv);
  canv.style="height: 700px;width: 1200px;"
  canvP.style="height: 700px;width: 1200px;position:fixed;top:50px;left:60px;z-index:999999";
  document.body.append(canvP)
  canvP.setAttribute("hidden",true);
  moveAble(canvP)
}

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) {
      canvP.setAttribute("hidden",true);
      hasCi=false;
      return;
  };
  console.log('生成词云');
  var list=sai;
  if(sai.length==0) analysi();
  canvP.removeAttribute("hidden");
  WordCloud([canv], 
  { 
   list: list,
   color: colorw, //'random-light'
   backgroundColor: 'rgba(125,100,125,0.8)',
   gridSize: 18,
   weightFactor: 200/tez[0],
  fontFamily: 'Times, serif',
  rotateRatio: 0.5,
  classes: "blura",
  rotationSteps: 2
} );
hasCi=true;
}

let colorw=(wd,weight)=>{
  //tez[0]红色 #ff0000
  //1=>蓝色 #0000ff
  console.log(wd,weight,tez[0])
  let v=parseInt((colorTable.length-1)*weight/(tez[0]))
  return '#'+colorTable[v];
  // let v=parseInt(512*weight/(tez[0]))-1
  // return 'rgb('+(v>255?(v-255):125)+','+(v<255?v:510-v)+','+(v<255?255-v:125)+')';
}

let analysi=()=>{
  loadParam()
  console.log("等待弹幕获取完成")
  getOneSeg(1)
  // while(!fail){
  //   console.log("等待弹幕获取完成")
  // }
  return cia(3);
}

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);
              sleep(500)
              getOneSeg(seg+1)
       },
      error:function (err){ //失败回调函数
            fail=true;
            console.log("失败点:",seg)
       console.log(err);
       }
      });
}
function cia(l){
  console.log('分析弹幕...')
  let wds=[]
  s.forEach(e => {
    e=e.replace(/[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]/g,"");
    ctin(wds,e)
  });
  wds.forEach(e=>{
  if(e[1]>=l) {
    if(tez[0]<e[1]) tez[0]=e[1]
    sai.push(e)
  }
  })
  console.log("最大次数:",tez[0])
  console.log("筛选结果:",sai)
  return sai;
}
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>=0.5) return true;
  return false;
}

let loadParam=()=>{
  reqParm= [window.cid,window.aid]
  console.log('找到参数:',reqParm)
}

function sleep(numberMillis) {
	var now = new Date();
	var exitTime = now.getTime() + numberMillis;
	while (true) {
		now = new Date();
		if (now.getTime() > exitTime)
		return;
	    }
}
})();