欢迎光临散文网 会员登陆 & 注册

JS实现b站动态抽奖“公平”方案——动态+转发

2020-06-01 22:46 作者:Love丶伊卡洛斯  | 我要投稿

新前言

    因为 b站动态升级原因,原来评论的页数也变成了无限下拉加载的形式,导致旧版程序无法使用,新版本的程序简单重构了一下,可参考下面的3.0版本新代码,使用方法一样。
    目前成功完成1250评论的动态的测试

补充

当然 感兴趣的可以去试试官方API 

https://api.bilibili.com/x/v2/reply/main?callback=jQuery33106548244954033764_1618553940827&jsonp=jsonp&next=4&type=11&oid=130267145&mode=3&_=1618553940831

我这也简单分析一下

开发者工具 Network JS
用户数据
postman 构建GET请求
请求头追加referer

不加referer

视频演示+讲解

前期

因为非官方途径无法获取全部的转发人员信息,但评论的人员信息可以全部获取(暂时看来一百多页加载都没有问题)
参考链接:
JS实现b站动态转发抽奖(小人数)新方案讲解
JS实现b站动态评论区抽奖(含去重)

公平抽奖实现方案讲解

因为评论获取数是的,那么只需要转发+评论双管齐下,就可以通过在评论区抽奖,再对中奖用户的动态继续检索,中奖者会有评论时间,当天查看他的动态是否有转发抽奖动态,从而判断其资格。

抽奖代码

打开“动态”,保持评论第一页!!!,鼠标右键打开“检查”,来到“console”,贴入代码运行即可。
代码如下:

console.log("程序开始运行");
console.log("定义集合存储数据");
let name_set = new Set();
let id_set = new Set();
console.log("开始载入数据");
var page = 1;
var my_loop;

// 抽奖函数
function draw()
{
   // 循环次数
    for(var i=0; i<document.getElementsByClassName("con").length; i++)
    {
        var name = document.getElementsByClassName("con")[i].getElementsByClassName("user")[0].getElementsByTagName("a")[0].innerText;
        console.log(name+",加入集合");
        name_set.add(name);
        var id = document.getElementsByClassName("con")[i].getElementsByClassName("user")[0].getElementsByTagName("a")[0].getAttributeNode("data-usercard-mid").value;
        id_set.add(id);
    }
    console.log("第"+page+"页数据存入Set完毕");
    if(null != document.getElementsByClassName("next")[0])
    {
        page++;
        console.log("自动翻页...");
        document.getElementsByClassName("next")[0].click();
        //return true;
    }
    else
    {
        console.log("全部数据加载完毕");
        console.log("总共"+name_set.size+"名用户");
        // 生成随机数,直接打印中奖者信息
        var lucky_num = parseInt(Math.random()*(name_set.size),10);
        console.log("中奖用户ID为:"+Array.from(id_set)[lucky_num]);
        console.log("中奖用户名为:"+Array.from(name_set)[lucky_num]);
        console.log("中奖者大概位于 第" +parseInt(lucky_num/20+1)+ "页");
        clearInterval(my_loop);
        // 这就是注释
        //return false;
    }
}
// 定时调用函数
my_loop = setInterval(draw, 1500);



相关问题

最后一行my_loop = setInterval(draw, 1500);,这里的1500代表毫秒数,你可以修改这个数字来实现延长自动翻页时间差,因为翻页加载数据会受网络影响,网速慢的话,数据加载慢,可能会丢失数据,所以可以相对的延长翻页时间。
如果打印的内容不需要,可以注释掉相关 console.log代码,注释就是在这个代码前加 //,这2个反斜杠就是注释。注释后就不会打印了。

代码升级

准确获取中奖者位置,不过是在数据不丢失的前提下

// 获取时间

function get_date() {

    var date = new Date();

     var h = date.getHours();

     var m = date.getMinutes();

     var s = date.getSeconds();

     h = h < 10 ? ('0' + h) : h;

     m = m < 10 ? ('0' + m) : m;

     s = s < 10 ? ('0' + s) : s;

    var currentDate = "[" + h + ":" + m + ":" + s + "] ";

    return currentDate;

}


// 从map获取下标为index的键

function get_map_key(map, index)

{

     var i = 0;

     for (var [key, value] of map) {

         if(i == index)

         {

              return key;

         }

         i++;

     }

}


// 从map获取下标为index的值

function get_map_value(map, index)

{

     var i = 0;

     for (var [key, value] of map) {

         if(i == index)

         {

              return value;

         }

         i++;

     }

}


// 遍历map

function get_map(map)

{

     for (var [key, value] of map) {

          console.log(key + " = " + value);

     }

}


console.log(get_date() + "程序开始运行");

console.log(get_date() + "定义图存储数据(自动去重)");

let name_map = new Map();

let id_map = new Map();

console.log(get_date() + "开始载入数据");

var page = 1;

var my_loop;


// 抽奖函数

function draw()

{

    // 循环次数

     for(var i=0; i<document.getElementsByClassName("con").length; i++)

     {

         var name = document.getElementsByClassName("con")[i].getElementsByClassName("user")[0].getElementsByTagName("a")[0].innerText;

         var id = document.getElementsByClassName("con")[i].getElementsByClassName("user")[0].getElementsByTagName("a")[0].getAttributeNode("data-usercard-mid").value;

         //console.log(name+",加入图");

         name_map.set(name, page);

         id_map.set(id, page);

     }

     console.log(get_date() + "第"+page+"页数据存入Map完毕");

     if(null != document.getElementsByClassName("next")[0])

     {

         page++;

         //console.log("自动翻页...");

         document.getElementsByClassName("next")[0].click();

         //return true;

     }

     else

     {

         console.log(get_date() + "全部数据加载完毕");

         console.log(get_date() + "总共" + name_map.size + "名用户");

         // 生成随机数,直接打印中奖者信息

         var lucky_num = parseInt(Math.random()*(name_map.size),10);

         console.log(" ");

         console.log("中奖用户ID为:" + get_map_key(id_map, lucky_num));

         console.log("中奖用户名为:" + get_map_key(name_map, lucky_num));

         console.log("中奖者位于页:" + get_map_value(name_map, lucky_num));

         console.log(" ");

         console.log("程序运行结束");

         clearInterval(my_loop);

         // 这就是注释

         //return false;

     }

}


// 定时调用函数

my_loop = setInterval(draw, 1500);

3.0 新版本b站 单人版

使用方法相同,选中评论区后,console中贴入代码即可

console.log("程序开始运行");

console.log("定义集合存储数据");

let name_set = new Set();

let id_set = new Set();

console.log("开始载入数据");


// 循环变量

var my_loop;

// 下滑延时 500毫秒 网速/加载速度较慢的朋友们最好放慢速度 提高准确性

var r_time = 500;


// 评论数

var comment_num = parseInt(document.getElementsByClassName("text-offset")[1].innerText);


// 下滑

function r()

{

window.scroll(0, 1920*comment_num);

// 没有评论后自动停止下滑 并 抽奖

if(document.getElementsByClassName("loading-state")[0].innerText == "没有更多评论")

{

// 停止下滑循环

stop_r();

// 抽奖函数

draw();

}

}


// 停止下滑循环

function stop_r()

{

clearInterval(my_loop);

}


// 抽奖函数

function draw()

{

    // 循环次数

    var len = document.getElementsByClassName("con").length;

for(var i=0; i<len; i++)

{

var name = document.getElementsByClassName("con")[i].getElementsByClassName("user")[0].getElementsByTagName("a")[0].innerText;

// console.log(name+",加入集合");

name_set.add(name);

var id = document.getElementsByClassName("con")[i].getElementsByClassName("user")[0].getElementsByTagName("a")[0].getAttributeNode("data-usercard-mid").value;

id_set.add(id);

}

console.log("全部数据加载完毕");

console.log("总共"+name_set.size+"名用户");

// 生成随机数,直接打印中奖者信息

var lucky_num = parseInt(Math.random()*(name_set.size),10);

console.log("中奖用户ID为:"+Array.from(id_set)[lucky_num]);

console.log("中奖用户名为:"+Array.from(name_set)[lucky_num]);

// 这就是注释

//return false;

}


// 开始自动下滑 r_time毫秒一次

my_loop = setInterval(r, r_time);


3.1新版本多人抽取(适应b站动态改动)

数据加载完毕后,使用 go(中奖人数) 即可抽取

console.log("程序开始运行");

console.log("定义集合存储数据");

let name_set = new Set();

let id_set = new Set();

console.log("开始载入数据");


// 循环变量

var my_loop;

// 下滑延时 500毫秒 网速/加载速度较慢的朋友们最好放慢速度 提高准确性

var r_time = 500;


// 评论数

var comment_num = 1;

if(document.getElementsByClassName("text-offset")[1].innerText.indexOf("万") != -1)

{

comment_num = 10000 * (parseInt(document.getElementsByClassName("text-offset")[1].innerText) + 1);

}

else

{

comment_num = parseInt(document.getElementsByClassName("text-offset")[1].innerText);

}


// 下滑

function r()

{

window.scroll(0, 1920*comment_num);

// 没有评论后自动停止下滑 并 抽奖

if(document.getElementsByClassName("loading-state")[0].innerText == "没有更多评论")

{

// 停止下滑循环

stop_r();

// 抽奖函数

draw();

}

}


// 停止下滑循环

function stop_r()

{

clearInterval(my_loop);

}


// 抽奖函数

function draw()

{

    // 循环次数

    var len = document.getElementsByClassName("con").length;

for(var i=0; i<len; i++)

{

var name = document.getElementsByClassName("con")[i].getElementsByClassName("user")[0].getElementsByTagName("a")[0].innerText;

// console.log(name+",加入集合");

name_set.add(name);

var id = document.getElementsByClassName("con")[i].getElementsByClassName("user")[0].getElementsByTagName("a")[0].getAttributeNode("data-usercard-mid").value;

id_set.add(id);

}

console.log("全部数据加载完毕");

console.log("总共"+name_set.size+"名用户");

// 这就是注释

//return false;

}


// 获取幸运儿

function go(num)

{

for(var i=0; i<num; i++)

{

// 生成随机数,直接打印中奖者信息

var lucky_num = parseInt(Math.random()*(name_set.size), 10);


console.log(" ");

console.log("中奖用户ID为:"+Array.from(id_set)[lucky_num]);

console.log("中奖用户名为:"+Array.from(name_set)[lucky_num]);

console.log(" ");

}

}


// 开始自动下滑 r_time毫秒一次

my_loop = setInterval(r, r_time);


// 全部数据加载完毕后,使用 go(中奖数) 抽取中奖者


JS实现b站动态抽奖“公平”方案——动态+转发的评论 (共 条)

分享到微博请遵守国家法律