新前言
因為 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(中獎數) 抽取中獎者