弹幕词云

bilibili弹幕词云

Устаревшая версия за 13.04.2021. Перейдите к последней версии.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==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;
	    }
}
})();