Skip to content
This repository has been archived by the owner on Apr 14, 2024. It is now read-only.

Commit

Permalink
b230815.01
Browse files Browse the repository at this point in the history
Mehver committed Aug 15, 2023
0 parents commit 8e2eb95
Showing 8 changed files with 652 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions .idea/BiliBili-SearchList.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

373 changes: 373 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
> 感谢闲鱼买家ZEP的有偿定制
<div align="center">
<img src="https://github.com/SynRGB/BiliBili-SearchList/raw/main/%23README/icon/256.png" width="20%"/>
<h1>BiliBili-搜索列表 <code>b230815.01</code></h1>
<p>
<a href='https://github.com/SynRGB/BiliBili-SearchList'><img src="https://img.shields.io/badge/-GitHub-3A3A3A?style=flat&amp;logo=GitHub&amp;logoColor=white" referrerpolicy="no-referrer" alt="GitHub"></a>
<a href=''><img src="https://img.shields.io/badge/-GreasyFork-670000?style=flat&amp;logo=tampermonkey&amp;logoColor=white" referrerpolicy="no-referrer" alt="GreasyFork"></a>
</p>
</div>

## 简介

(感谢闲鱼买家ZEP的有偿定制) 用列表的方式展示B站搜索结果,方便按各列排序。
5 changes: 5 additions & 0 deletions Update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## `b230815.01`

- 调整列表顺序
- 调成发布日期,时长,标题,播放量,up主吗
- 去掉弹幕数
229 changes: 229 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
// ==UserScript==
// @name BiliBili-SearchList
// @name:zh-CN BiliBili-搜索列表
// @namespace https://github.com/Mehver
// @version bata
// @description (Thanks to ZEP's paid customization) Display Bilibili search results in a list, which is convenient for sorting by each column.
// @description:zh-CN (感谢'ZEP'的有偿定制) 用列表的方式展示B站搜索结果,方便按各列排序。
// @sponsor ZEP (闲鱼)
// @author https://github.com/Mehver
// @icon
// @match http*://search.bilibili.com/*
// @license MPL-2.0
// @license^ Mozilla Public License 2.0
// @charset UTF-8
// @homepageURL https://github.com/SynRGB/BiliBili-SearchList
// @contributionURL https://github.com/SynRGB/BiliBili-SearchList
// @copyright Copyright © 2022-PRESENT, Mehver (https://github.com/Mehver)
// @grant GM_addStyle
// @grant GM_getResourceText
// @resource DataTablesCSS https://cdn.datatables.net/1.11.3/css/jquery.dataTables.min.css
// ==/UserScript==

//////////////////////////////////////
//////////// DataTables //////////////
let cssTxt = GM_getResourceText("DataTablesCSS");
GM_addStyle(cssTxt);
let head = document.head || document.getElementsByTagName('head')[0];
let link = document.createElement('link');
link.type = 'text/css';
link.rel = 'stylesheet';
link.href = 'https://cdn.datatables.net/1.11.3/css/jquery.dataTables.min.css';
head.appendChild(link);
(function() {
let jQueryScript = document.createElement("script");
jQueryScript.src = "https://code.jquery.com/jquery-3.6.0.min.js";
jQueryScript.onload = () => {
let dtScript = document.createElement("script");
dtScript.src = "https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js";
// 加载完成后首次运行
dtScript.onload = () => {
main();
};
document.body.appendChild(dtScript);
};
document.body.appendChild(jQueryScript);
})();
//////////// DataTables //////////////
//////////////////////////////////////

//////////////////////////////////////
/////////////// 触发器 ////////////////
// 延时避免在 dtScript 和 jQueryScript 加载完成前就运行
setTimeout(function() {
// if DOM changed, re-run the script
let observer = new window.MutationObserver(function (mutations) {
mutations.forEach(function () {
const biliResultsTable = document.querySelector('#biliResultsTable');
if (biliResultsTable === null) {
main();
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}, 1000);
/////////////// 触发器 ////////////////
//////////////////////////////////////

/////////////////////////////////////
/////////////// main ////////////////
function main() {
// Create table with thead for DataTables
let table = document.createElement('table');
table.id = "biliResultsTable";
let thead = document.createElement('thead');
let tbody = document.createElement('tbody');
// let header = ["标题", "UP主", "播放数", "弹幕数", "时长", "发布日期"]; // 改需求A
let header = ["发布日期", "时长", "标题", "播放量", "UP主"];
let trHead = document.createElement('tr');
header.forEach(text => {
let th = document.createElement('th');
th.textContent = text;
trHead.appendChild(th);
});
thead.appendChild(trHead);

setTimeout(function() {
let videoCards = document.querySelectorAll('.bili-video-card');
videoCards.forEach(videoCard => {
let title = videoCard.querySelector('.bili-video-card__info--tit')?.textContent.trim();
let up = videoCard.querySelector('.bili-video-card__info--author')?.textContent.trim();
let playCount = videoCard.querySelector('.bili-video-card__stats--item > span')?.textContent.trim();
let danmakuCount = videoCard.querySelectorAll('.bili-video-card__stats--item > span')[1]?.textContent.trim();
let duration = videoCard.querySelector('.bili-video-card__stats__duration')?.textContent.trim();
let date = videoCard.querySelector('.bili-video-card__info--date')?.textContent.trim().replace('· ', '');
let link_video = videoCard.querySelectorAll('a')[0].getAttribute('href');
let link_up;
try { link_up = videoCard.querySelectorAll('a')[2].getAttribute('href'); } catch (e) {}

let tr = document.createElement('tr');

// 确保没有为空的数据
if (
(title !== undefined) &&
(up !== undefined) &&
(playCount !== undefined) &&
(danmakuCount !== undefined) &&
(duration !== undefined) &&
(date !== undefined) &&
(link_video !== undefined)
) {
//// 改需求A
// [title, up, playCount, danmakuCount, duration, date].forEach(text => {
// let td = document.createElement('td');
// td.textContent = text;
// tr.appendChild(td);
// });
// let tdTitle = tr.querySelector('td');
// tdTitle.innerHTML = `<a href="${link_video}" target="_blank">${title}</a>`;
// let tdUp = tr.querySelector('td:nth-child(2)');
// tdUp.innerHTML = `<a href="${link_up}" target="_blank">${up}</a>`;
[date, duration, title, playCount, up].forEach(text => {
let td = document.createElement('td');
td.textContent = text;
tr.appendChild(td);
});
let tdTitle = tr.querySelector('td:nth-child(3)');
tdTitle.innerHTML = `<a href="${link_video}" target="_blank">${title}</a>`;
let tdUp = tr.querySelector('td:nth-child(5)');
tdUp.innerHTML = `<a href="${link_up}" target="_blank">${up}</a>`;
tbody.appendChild(tr);
}
});
console.log(videoCards);
table.appendChild(thead);
table.appendChild(tbody);

// 回调获取异步数据,适用于下方 targetDiv2 的异步加载
if (tbody.childElementCount === 0) {
main();
return;
}

// 搜索第一页的 DOM 结构与其他页不同,直接用这种方式即可匹配
let targetDiv1 = document.querySelector("#i_cecream > div > div:nth-child(2) > div.search-content.search-content--gray > div > div > div > div.video.i_wrapper.search-all-list");
if (targetDiv1 !== null) {
targetDiv1.innerHTML = '';
targetDiv1.appendChild(table);
} else {
// 匹配除第一页外的其他 DOM 结构,第一页返回的结果是一次性全部加载的,而其他页是异步加载的
let targetDiv2_rm = document.querySelector("#i_cecream > div > div:nth-child(2) > div.search-content--gray.search-content > div > div > div.video-list.row");
targetDiv2_rm.innerHTML = '';
let targetDiv2 = document.querySelector("#i_cecream > div > div:nth-child(2) > div.search-content--gray.search-content > div > div > div.flex_center.mt_x50.mb_lg");
targetDiv2.parentNode.insertBefore(table, targetDiv2);
// 每次翻页时,上一页的表格不会自动被覆盖而是叠加在一起,所以需要手动删除
let tables = document.querySelectorAll('#biliResultsTable');
if (tables.length > 1) {
tables.forEach(table => {
if (table !== tables[0]) {
table.remove();
}
});
}
}

// DataTables 的自定义排序算法
$.fn.dataTable.ext.type.order['duration-sort-pre'] = function (d) {return convertDurationToSeconds(d);};
$.fn.dataTable.ext.type.order['playcount-sort-pre'] = function (d) {return convertPlayCount(d);};
$.fn.dataTable.ext.type.order['date-sort-pre'] = function (d) {return convertDate(d);};
// Initialize DataTables
$(table).DataTable({
"paging": false,
"searching": false,
"info": false,
"columnDefs": [
//// 改需求A
// { "type": "playcount-sort", "targets": 2 },
// { "type": "duration-sort", "targets": 4 },
// { "type": "date-sort", "targets": 5 }
{ "type": "playcount-sort", "targets": 3 },
{ "type": "duration-sort", "targets": 1 },
{ "type": "date-sort", "targets": 0 }
]
});
}, 100);
}
/////////////// main ////////////////
/////////////////////////////////////

///////////////////////////////////
/////// DataTable 的排序算法 ////////
function convertDurationToSeconds(duration) {
let parts = duration.split(':').map(part => parseInt(part, 10));
if (parts.length === 3) {
return parts[0] * 3600 + parts[1] * 60 + parts[2];
} else if (parts.length === 2) {
return parts[0] * 60 + parts[1];
} else {
return NaN;
}
}
function convertPlayCount(playCount) {
if (playCount.includes('万')) {
return parseFloat(playCount.replace('万', '')) * 10000;
} else {
return parseInt(playCount, 10);
}
}
function convertDate(date) {
if (date.includes('小时前')) {
return parseFloat(date.replace('小时前', ''))
}
else {
date = date.split('-').map(part => {
if (part.length === 1) {
return '0' + part;
} else {
return part;
}
}).join('-');
return parseFloat(date.replace('-', ''))
}
}
/////// DataTable 的排序函数 ////////
///////////////////////////////////

console.log("JS script BiliBili-SearchList (BiliBili-搜索列表) loaded. See more details at https://github.com/SynRGB/BiliBili-SearchList");

0 comments on commit 8e2eb95

Please sign in to comment.