2022-07-28 21:24:28 +08:00
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html lang="cn">
|
|
|
|
|
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
<title>B站热搜</title>
|
2022-07-29 14:44:23 +08:00
|
|
|
|
<link rel="stylesheet" href="./assets/css/main.css">
|
2022-07-28 21:24:28 +08:00
|
|
|
|
<style>
|
|
|
|
|
#list td {
|
2022-07-29 14:08:23 +08:00
|
|
|
|
font-size: 14px;
|
2022-07-28 21:24:28 +08:00
|
|
|
|
}
|
2022-07-29 20:33:57 +08:00
|
|
|
|
|
|
|
|
|
#mobile-info {
|
|
|
|
|
color: grey;
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
2022-07-28 21:24:28 +08:00
|
|
|
|
</style>
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
<body>
|
|
|
|
|
<div style="text-align: center;">
|
|
|
|
|
<h1>B站热搜榜</h1>
|
|
|
|
|
<hr>
|
|
|
|
|
<div>
|
|
|
|
|
显示字段:
|
2022-07-28 23:13:21 +08:00
|
|
|
|
<label for="show_keyword">
|
|
|
|
|
<input type="checkbox" class="filter_checkbox" name="show_keyword" id="show_keyword" checked="true"
|
|
|
|
|
detailed-checked="true">关键词
|
|
|
|
|
</label>
|
|
|
|
|
<label for="show_word_type">
|
|
|
|
|
<input type="checkbox" class="filter_checkbox" name="show_word_type" id="show_word_type"
|
|
|
|
|
detailed-checked="true">word_type
|
|
|
|
|
</label>
|
|
|
|
|
<label for="show_hot_id">
|
|
|
|
|
<input type="checkbox" class="filter_checkbox" name="show_hot_id" id="show_hot_id"
|
|
|
|
|
detailed-checked="true">hot_id
|
|
|
|
|
</label>
|
2022-07-28 21:24:28 +08:00
|
|
|
|
<br>
|
|
|
|
|
<button id="btn_show_all">全选</button>
|
|
|
|
|
<button id="btn_show_none">全不选</button>
|
|
|
|
|
|
|
|
|
|
|
<button id="btn_show_default">普通</button>
|
|
|
|
|
<button id="btn_show_detailed">详细</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<p id="latestUpdateTime" style="font-size: 12px; display: inline-block; vertical-align: middle;"></p>
|
|
|
|
|
<nobr>
|
|
|
|
|
<button id="btn_refresh">重新拉取</button>
|
|
|
|
|
</nobr>
|
|
|
|
|
<nobr>
|
|
|
|
|
<label for="auto_refresh">
|
2022-07-28 23:13:21 +08:00
|
|
|
|
<input type="checkbox" name="auto_refresh" id="auto_refresh">自动拉取<span id="auto_refresh_countdown"></span>
|
2022-07-28 21:24:28 +08:00
|
|
|
|
</label>
|
|
|
|
|
</nobr>
|
|
|
|
|
<nobr>
|
|
|
|
|
<span id="update-finish-info" style="color: green; font-weight: bold; display: none;">拉取成功,数据已更新</span>
|
|
|
|
|
</nobr>
|
|
|
|
|
<table id="list"></table>
|
2022-07-29 20:33:57 +08:00
|
|
|
|
<p id="mobile-info"></p>
|
|
|
|
|
<div class="bottom-placeholder">
|
2022-07-29 21:49:38 +08:00
|
|
|
|
<p>
|
|
|
|
|
— 到底啦 —<br>
|
|
|
|
|
数据来源: https://www.bilibili.com/blackboard/activity-trending-topic.html
|
|
|
|
|
</p>
|
2022-07-29 20:33:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script src="./assets/js/isMobile.js"></script>
|
|
|
|
|
<script>
|
|
|
|
|
let mobileFlag = isMobile();
|
|
|
|
|
document.getElementById('mobile-info').innerHTML = `手机、电脑端热搜链接不同,当前为您呈现 <span style="font-weight: bold;">${mobileFlag ? '手机端' : '电脑端'}</span> 链接`;
|
|
|
|
|
</script>
|
2022-07-28 21:24:28 +08:00
|
|
|
|
<script>
|
2022-07-28 23:13:21 +08:00
|
|
|
|
let iconMapper = {
|
2023-05-25 17:51:16 +08:00
|
|
|
|
// 2023.05.25 更新
|
|
|
|
|
"http://i0.hdslb.com/bfs/activity-plat/static/20221118/eaf2dd702d7cc14d8d9511190245d057/UF7B1wVKT2.png": ["新", "#FFB027"],
|
|
|
|
|
"http://i0.hdslb.com/bfs/activity-plat/static/20221213/eaf2dd702d7cc14d8d9511190245d057/lrx9rnKo24.png": ["热", "#F85A54"],
|
|
|
|
|
"http://i0.hdslb.com/bfs/activity-plat/static/20221117/eaf2dd702d7cc14d8d9511190245d057/nhoSO8rRli.png": ["话题", "#FF6699"],
|
|
|
|
|
"http://i0.hdslb.com/bfs/activity-plat/static/20221117/eaf2dd702d7cc14d8d9511190245d057/EeuqbMwao9.png": ["梗", "#FF6699"],
|
|
|
|
|
|
2022-07-28 23:13:21 +08:00
|
|
|
|
"http://i0.hdslb.com/bfs/feed-admin/e9e7a2d8497d4063421b685e72680bf1cfb99a0d.png": ["热", "#FF895C"],
|
|
|
|
|
"http://i0.hdslb.com/bfs/feed-admin/4d579fb61f9655316582db193118bba3a721eec0.png": ["新", "#F87399"],
|
|
|
|
|
}
|
|
|
|
|
function getIconText(iconUrl) {
|
|
|
|
|
if (!iconUrl) {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
else if (Object.keys(iconMapper).indexOf(iconUrl) != -1) {
|
|
|
|
|
return iconMapper[iconUrl];
|
|
|
|
|
} else {
|
|
|
|
|
console.log("未知 iconUrl:", iconUrl);
|
|
|
|
|
return [" ? ", 'grey'];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
<script>
|
|
|
|
|
/**
|
|
|
|
|
* 全局变量
|
|
|
|
|
*/
|
|
|
|
|
// 拉取下来的数据
|
|
|
|
|
let hotBandData;
|
|
|
|
|
|
|
|
|
|
// 按钮
|
|
|
|
|
const btnShowAll = document.getElementById('btn_show_all');
|
|
|
|
|
const btnShowNone = document.getElementById('btn_show_none');
|
|
|
|
|
const btnShowDefault = document.getElementById('btn_show_default');
|
|
|
|
|
const btnShowDetailed = document.getElementById('btn_show_detailed');
|
|
|
|
|
|
|
|
|
|
const btnRefresh = document.getElementById('btn_refresh');
|
|
|
|
|
|
|
|
|
|
// 复选框
|
|
|
|
|
const filterCheckbox = document.getElementsByClassName("filter_checkbox");
|
|
|
|
|
|
|
|
|
|
const showKeyword = document.getElementById("show_keyword");
|
|
|
|
|
const showWordType = document.getElementById("show_word_type");
|
|
|
|
|
const showHotId = document.getElementById("show_hot_id");
|
|
|
|
|
|
|
|
|
|
const autoRefresh = document.getElementById("auto_refresh");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 绑定按钮点击事件
|
|
|
|
|
btnShowAll.addEventListener('click', function () {
|
|
|
|
|
for (let i = 0; i < filterCheckbox.length; i++) {
|
|
|
|
|
const element = filterCheckbox[i];
|
|
|
|
|
element.checked = true;
|
|
|
|
|
}
|
|
|
|
|
render();
|
|
|
|
|
});
|
|
|
|
|
btnShowNone.addEventListener('click', function () {
|
|
|
|
|
for (let i = 0; i < filterCheckbox.length; i++) {
|
|
|
|
|
const element = filterCheckbox[i];
|
|
|
|
|
element.checked = false;
|
|
|
|
|
}
|
|
|
|
|
render();
|
|
|
|
|
});
|
|
|
|
|
btnShowDefault.addEventListener('click', function () {
|
|
|
|
|
for (let i = 0; i < filterCheckbox.length; i++) {
|
|
|
|
|
const element = filterCheckbox[i];
|
|
|
|
|
element.checked = element.getAttribute('checked') === 'true';
|
|
|
|
|
}
|
|
|
|
|
render();
|
|
|
|
|
});
|
|
|
|
|
btnShowDetailed.addEventListener('click', function () {
|
|
|
|
|
for (let i = 0; i < filterCheckbox.length; i++) {
|
|
|
|
|
const element = filterCheckbox[i];
|
|
|
|
|
element.checked = element.getAttribute('detailed-checked') === 'true';
|
|
|
|
|
}
|
|
|
|
|
render();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
btnRefresh.onclick = function () {
|
|
|
|
|
getData();
|
|
|
|
|
document.getElementById("update-finish-info").style.display = "";
|
|
|
|
|
// btnRefresh.style.display = "none";
|
|
|
|
|
btnRefresh.style.visibility = "hidden";
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
document.getElementById("update-finish-info").style.display = "none";
|
|
|
|
|
// btnRefresh.style.display = "";
|
|
|
|
|
btnRefresh.style.visibility = "";
|
|
|
|
|
}, 1000);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 绑定复选框改变事件
|
|
|
|
|
for (let i = 0; i < filterCheckbox.length; i++) {
|
|
|
|
|
// console.log(filterCheckbox[i]);
|
|
|
|
|
filterCheckbox[i].onchange = function () {
|
|
|
|
|
render();
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let autoRefreshIntreval = null;
|
|
|
|
|
const autoRefreshCountDownElement = document.getElementById('auto_refresh_countdown');
|
|
|
|
|
const countDown = 20; // 自动拉取间隔时间,单位:秒
|
|
|
|
|
let autoRefreshCountDown = countDown;
|
|
|
|
|
autoRefresh.onchange = function () {
|
|
|
|
|
if (autoRefresh.checked) {
|
|
|
|
|
btnRefresh.style.display = "none";
|
|
|
|
|
btnRefresh.click();
|
|
|
|
|
autoRefreshIntreval = setInterval(function () {
|
|
|
|
|
if ((--autoRefreshCountDown) > 0) {
|
|
|
|
|
autoRefreshCountDownElement.innerHTML = `(${autoRefreshCountDown}s)`;
|
|
|
|
|
} else {
|
|
|
|
|
autoRefreshCountDown = countDown;
|
|
|
|
|
btnRefresh.click();
|
|
|
|
|
autoRefreshCountDownElement.innerHTML = ``;
|
|
|
|
|
}
|
|
|
|
|
}, 1000);
|
|
|
|
|
} else {
|
|
|
|
|
clearInterval(autoRefreshIntreval);
|
|
|
|
|
btnRefresh.style.display = "";
|
|
|
|
|
autoRefreshCountDownElement.innerHTML = ``;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 根据屏幕判断要显示哪些字段
|
|
|
|
|
// 此时还未拉取数据,所以进入 render 函数会直接返回,不会多次渲染
|
|
|
|
|
let initWidth = document.body.offsetWidth;
|
|
|
|
|
// console.log(initWidth);
|
|
|
|
|
if (initWidth < 400) {
|
|
|
|
|
btnShowNone.click();
|
|
|
|
|
btnShowNone.innerHTML += "(默认)";
|
|
|
|
|
} else if (initWidth < 780) {
|
|
|
|
|
btnShowDefault.click();
|
|
|
|
|
btnShowDefault.innerHTML += "(默认)";
|
|
|
|
|
} else {
|
|
|
|
|
btnShowDetailed.click();
|
|
|
|
|
btnShowDetailed.innerHTML += "(默认)";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 网页加载后加载榜单
|
|
|
|
|
getData();
|
|
|
|
|
|
|
|
|
|
// 定时刷新
|
|
|
|
|
// setInterval(getData, 10 * 1000);
|
|
|
|
|
|
|
|
|
|
function getData() {
|
|
|
|
|
var xhr = new XMLHttpRequest();
|
2022-07-29 16:15:45 +08:00
|
|
|
|
xhr.open("GET", "../data/bilibili-hotband/latest.json?t=" + Date.now(), true);
|
2022-07-28 23:13:21 +08:00
|
|
|
|
xhr.send();
|
|
|
|
|
xhr.onreadystatechange = function () {
|
|
|
|
|
if (xhr.readyState !== 4) return;
|
|
|
|
|
|
|
|
|
|
if (xhr.status == 200) {
|
|
|
|
|
try {
|
|
|
|
|
hotBandData = JSON.parse(xhr.responseText);
|
|
|
|
|
if (!hotBandData.data || typeof hotBandData.data !== 'object')
|
|
|
|
|
throw new Error("data is undefined or not an object");
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error("[error]", "\n", e, "\n", "\n", "[xhr.responseText]", "\n", xhr.responseText);
|
|
|
|
|
alert("latest.json 文件解析失败,请检查文件");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
console.log(hotBandData);
|
|
|
|
|
|
|
|
|
|
// 更新时间
|
|
|
|
|
document.getElementById("latestUpdateTime").innerHTML =
|
|
|
|
|
"数据拉取时间:" + new Date().toLocaleString() + "<br/>" +
|
|
|
|
|
"热榜更新时间:" + new Date(hotBandData.update_time).toLocaleString();
|
|
|
|
|
|
|
|
|
|
// 渲染榜单
|
|
|
|
|
render();
|
|
|
|
|
} else if (xhr.status == 404) {
|
|
|
|
|
alert("data 目录下未找到 latest.json 文件,可能的原因:\n您还没有运行脚本拉取数据,请先运行脚本,然后刷新页面");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function render() {
|
|
|
|
|
if (!hotBandData) return;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 渲染热搜列表
|
|
|
|
|
*/
|
|
|
|
|
let hotBandList = hotBandData.data;
|
|
|
|
|
var str = [];
|
|
|
|
|
// 渲染表格
|
|
|
|
|
str.push(`<thead>
|
|
|
|
|
<tr class="thead" style="top: 0; background-color: white; position: sticky;">
|
|
|
|
|
<td>编号</td>
|
|
|
|
|
<td>热搜</td>
|
|
|
|
|
${showKeyword.checked ? "<td>关键词</td>" : ""}
|
|
|
|
|
${showWordType.checked ? "<td>word_type</td>" : ""}
|
|
|
|
|
${showHotId.checked ? "<td>hot_id</td>" : ""}
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>`);
|
|
|
|
|
str.push(`<tbody>`);
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < hotBandList.length; i++) {
|
|
|
|
|
const hotBand = hotBandList[i];
|
2022-07-29 20:33:57 +08:00
|
|
|
|
|
|
|
|
|
let linkUrl = mobileFlag
|
|
|
|
|
? `https://m.bilibili.com/search?keyword=${encodeURIComponent(hotBand.keyword)}`
|
|
|
|
|
: `https://search.bilibili.com/all?keyword=${encodeURIComponent(hotBand.keyword)}`;
|
|
|
|
|
|
2022-07-28 23:13:21 +08:00
|
|
|
|
str.push(`<tr>
|
|
|
|
|
<!-- 编号 -->
|
|
|
|
|
<td>${hotBand.position}</td>
|
|
|
|
|
|
|
|
|
|
<!-- 热搜 -->
|
2022-07-29 14:08:23 +08:00
|
|
|
|
<td style="text-align: left;">
|
2022-07-28 23:13:21 +08:00
|
|
|
|
<nobr>
|
|
|
|
|
<div style="min-width: 20px; display: inline-block;">
|
|
|
|
|
<span class="hotband-label" style="background-color: ${getIconText(hotBand.icon)[1]}; ${hotBand.icon ? "" : "display: none;"}">${getIconText(hotBand.icon)[0]}</span>
|
|
|
|
|
</div>
|
2022-07-29 20:33:57 +08:00
|
|
|
|
<span>
|
|
|
|
|
<a href="${linkUrl}" target="_blank">${hotBand.show_name}</a>
|
|
|
|
|
</span>
|
2022-07-29 15:27:08 +08:00
|
|
|
|
${hotBand.show_live_icon ? `<span class="hotband-label" style="background-color: #f69; padding: 1px 5px;">直播中</span>` : ""}
|
2022-07-28 23:13:21 +08:00
|
|
|
|
</nobr>
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
|
|
${showKeyword.checked ? `
|
|
|
|
|
<!-- 关键词 -->
|
|
|
|
|
<td>${hotBand.keyword}</td>
|
|
|
|
|
` : ""}
|
|
|
|
|
|
|
|
|
|
${showWordType.checked ? `
|
|
|
|
|
<!-- word_type -->
|
|
|
|
|
<td>${hotBand.word_type}</td>
|
|
|
|
|
` : ""}
|
|
|
|
|
|
|
|
|
|
${showHotId.checked ? `
|
|
|
|
|
<!-- hot_id -->
|
|
|
|
|
<td>${hotBand.hot_id}</td>
|
|
|
|
|
` : ""}
|
|
|
|
|
</tr >`);
|
|
|
|
|
}
|
|
|
|
|
str.push(`</tbody>`);
|
|
|
|
|
document.getElementById('list').innerHTML = str.join('');
|
|
|
|
|
}
|
2022-07-28 21:24:28 +08:00
|
|
|
|
</script>
|
|
|
|
|
</body>
|
|
|
|
|
|
|
|
|
|
</html>
|