JS實現b站動態抽獎“公平”方案——動態+轉發


新前言

    因為 b站動態升級原因,原來評論的頁數也變成了無限下拉加載的形式,導致舊版程序無法使用,新版本的程序簡單重構了一下,可參考下面的3.0版本新代碼,使用方法一樣。
    目前成功完成1250、5590評論的動態的測試

補充

當然 感興趣的可以去試試官方API
https://api.bilibili.com/x/v2/reply/main?callback=jQuery33106548244954033764_1618553940827&jsonp=jsonp&next=4&type=11&oid=130267145&mode=3&_=1618553940831
在這里插入圖片描述
在這里插入圖片描述
我這也簡單分析一下
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

視頻演示+講解

視頻傳送門

舊前言

因為非官方途徑無法獲取全部的轉發人員信息,但評論的人員信息可以全部獲取(暫時看來一百多頁加載都沒有問題)
參考鏈接:JS實現b站動態轉發抽獎(小人數)新方案講解
JS實現b站動態評論區抽獎(含去重)
當然還有一種比較費勁的方式就是發起抽獎到開獎為止,后台一直保持數據爬取(服務器),將數據整合后最后抽取中獎者的方式。
為了方便我已經對代碼做了整理,傳送門:碼雲 GitHub

公平抽獎實現方案講解

因為評論獲取數是全的,那么只需要轉發+評論雙管齊下,就可以通過在評論區抽獎,再對中獎用戶的動態繼續檢索,中獎者會有評論時間,當天查看他的動態是否有轉發抽獎動態,從而判斷其資格。

抽獎代碼

打開“動態”,保持評論第一頁,鼠標右鍵打開“檢查”(或者按F12),來到“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()
{
    // 循環次數
	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("第"+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 currentDate = "[" + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds() + "] ";
    return currentDate;
}

console.log(get_date() + "程序開始運行");
console.log(get_date() + "定義集合存儲數據(自動去重)");
let name_set = new Set();
let id_set = new Set();
console.log(get_date() + "開始載入數據");
var page = 1;
var 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(get_date() + "第"+page+"頁數據存入Set完畢");
	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_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);


2.0版本,獲取准確頁數,使用Map存儲

// 獲取時間
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()
{
    // 循環次數
	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;
		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);


2.1版本 新增多次抽獎功能

使用方式是 貼入代碼后,等待翻頁完畢,數據加載完畢后,調用 go()函數進行抽獎。

// 獲取時間
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()
{
    // 循環次數
	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;
		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 + "名用戶");
		clearInterval(my_loop);
		// 這就是注釋
		//return false;
	}
}

function go()
{
	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(" ");
}

// 定時調用函數
my_loop = setInterval(draw, 1500);



在這里插入圖片描述

2.2版本 多次抽獎功能(半自動化)

使用方式是 貼入代碼后,等待翻頁完畢,數據加載完畢后,調用 go(抽獎數)函數進行抽獎。

// 獲取時間
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()
{
    // 循環次數
    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;
		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 + "名用戶");
		clearInterval(my_loop);
		// 這就是注釋
		//return false;
	}
}

function go(num)
{
	for(var i=0; i<num; i++)
	{
		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(" ");
	}
}

// 定時調用函數
my_loop = setInterval(draw, 1500);

例如抽3個人
在這里插入圖片描述

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(中獎數) 抽取中獎者



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM