B站评论抽奖Javascript代码

《200多元的树莓派能给你的生活带来多大变化》的这一期视频中,踢踢使用了自己写的一个javascript脚本来实现评论抽奖,有不少小伙伴想要抽奖脚本的源代码,这里我就分享出来,简单地解释一下原理。

每一次点击B站视频下方的评论页码时都会看到有一条jsonp请求发出,如图:

双击打开后发现请求的地址为:https://api.bilibili.com/x/v2/reply?callback=jQuery172009350743824178642_1526364237871&jsonp=jsonp&pn=3&type=1&oid=22995513&sort=0&_=1526364249684

分析一下就可以得出,请求地址的格式为:https://api.bilibili.com/x/v2/reply?callback=<callback函数名>&jsonp=jsonp&pn=<评论页码>&type=1&oid=<视频AV号>&sort=<排序方式>&_=<时间戳>

由于B站做了请求防跨域处理,因此打算简单地用javascript代码贴入B站的console来执行(其实可以写成一个chrome插件,但是我懒,打我呀~)

由于jsonp不支持同步拉取数据,因此会导致大批量拉取评论,有些内容会丢失,因此将jsonp请求嵌套,一个请求succ的处理中再调用下一个请求,保证所有请求按序且完整地收到。

以下就是源代码,在console中执行后,只需要执行StartDraw(开始页码, 结束页码, 评论筛选开始时间, 评论筛选结束时间, 抽奖人数)即可抽出结果,

var userData = {};
var startPage = 0;
var endPage = 0;
var startTime = "";
var endTime = "";
var pickSum = 0;

var dateItem = new Date();

function StartDraw(_startPage, _endPage, _startTime, _endTime, _pickSum)
{
  startPage = _startPage;
  endPage = _endPage;
  startTime = _startTime;
  endTime = _endTime;
  pickSum = _pickSum;
  GetUserData();
}

function GetUserData()
{
  GetOneData(startPage, endPage);
}

function callback(data)
{

}

function GetOneData(page, maxPage)
{
  urlLocationParams = window.location.pathname.split("/");
  avID = urlLocationParams[urlLocationParams.length - 1].split("av")[1];
  var url = "https://api.bilibili.com/x/v2/reply?callback=callback&jsonp=jsonp&pn=" + page + "&type=1&oid=" + avID + "&sort=0&_=" + dateItem.getTime();
  $.ajax({
    url: url,
    type: 'get',
    dataType: 'jsonp',
    jsonpCallback: 'callback',
    success: function (data) {
      console.log(data);
      for (var j = 0; j < data.data.replies.length; j++) {
        var reply = data.data.replies[j];
        if (reply.ctime >= get_unix_time_stamp(startTime)
          && reply.ctime < get_unix_time_stamp(endTime)) {
          userData[reply.mid] = {};
          userData[reply.mid].uid = reply.mid;
          userData[reply.mid].floor = reply.floor;
          userData[reply.mid].name = reply.member.uname;
          userData[reply.mid].content = reply.content.message;
        }
      }
      page += 1;
      if (page <= maxPage)
      {
        GetOneData(page, maxPage)
      }
      else
      {
        PickUser();
      }
    }
  });
}

function PickUser()
{
  userList = [];
  for (var user in userData)
  {
    userList.push(user);
  }
  shuffle(userList);
  for (var i = 0; i < pickSum; i++)
  {
    console.log(userData[userList[i]])
  }
}


function get_unix_time_stamp(strtime) 
{
  if (strtime) {
    var date = new Date(strtime);
  } else {
    var date = new Date();
  }
  time = date.getTime() / 1000;

  return time;
}

function shuffle(array) {
  length = array.length;
  for (var index = 0; index < array.length; index++)
  {
    var temp = array[index];
    var changeIndex = RandomNumBoth(0, length - 1);
    array[index] = array[changeIndex];
    array[changeIndex] = temp;
  }
}

function RandomNumBoth(Min,Max){
  var Range = Max - Min;
  var Rand = Math.random();
  var num = Min + Math.round(Rand * Range); 
  return num;
}