🏠

Greasy Fork is available in English.

MyBilibili

b站主页面视频推荐挂载脚本,可以下载b站视频(最新版包括互动视频,番剧)呦~~~


安装此脚本?
提问、发表评价,或者 举报这个脚本
// ==UserScript==
// @name         MyBilibili
// @namespace    http://tampermonkey.net/
// @version      0.4.3
// @description  b站主页面视频推荐挂载脚本,可以下载b站视频(最新版包括互动视频,番剧)呦~~~
// @author       N-cat
// @match        https://api.bilibili.com/x/web-interface/dynamic/region?ps=*&rid=*
// @match        *://www.bilibili.com/
// @match        *://www.bilibili.com/video/*
// @match        *://www.bilibili.com/bangumi/play/*
// @icon         https://www.bilibili.com/favicon.ico?v=1
// @grant        GM_xmlhttpRequest
// @grant        GM_download
// @connect      *
// ==/UserScript==
(function() {
'use strict';
// api及参数说明来自 https://zhuanlan.zhihu.com/p/210779665
const style = `<style>
.add-main{
margin:auto;
width:1100px;
z-index:999999;
}
.add-div{
width: 206px;
height: 206px;
display:inline-block;
padding:7px 7px 7px 7px;
box-sizing:content-box;
position:relative;
z-index:999999;
}
.add-a{
color: #212121;
margin: 10px 0 8px;
height: 40px;
text-decoration: none;
width: 206px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
font-size: 14px;
line-height: 20px;
overflow: hidden;
text-overflow: ellipsis;
transition: color .3s;
z-index:999999;
}
.add-a:hover{
color: #00a1d6;
transition: color .3s;
z-index:999999;
}
.add-img{
width: 206px;
height: 116px;
border-radius: 2px;
z-index:999999;
}
.add-author{
color:#999;
text-decoration: none;
transition: color .3s;
font-size: 12px;
z-index:999999;
}
.add-author:hover{
color: #00a1d6;
transition: color .3s;
z-index:999999;
}
.re{
position:fixed;
right:80px;
bottom:80px;
background-color:#00a1d6;
color:white;
height:50px;
width:50px;
border-radius: 10px;
font-size:15px;
border:solid 3px #FA5A57;
cursor:pointer;
outline: none;
z-index:999999;
}
.top{
position:fixed;
right:80px;
bottom:150px;
background-color:#00a1d6;
color:white;
height:50px;
width:50px;
border-radius: 10px;
font-size:15px;
border:solid 3px #FA5A57;
cursor:pointer;
outline: none;
z-index:999999;
}
.add-bds{
position: absolute;
height: 22px;
width: 206px;
top: 101px;
color: white;
font-size: 14px;
background-color: rgba(0,0,0,.6);
// text-align: center;
border-radius: 2px;
z-index:999999;
}
.jindu{
position:fixed;
right:80px;
bottom:40px;
background-color:#00a1d6;
width: 80px;
color:white;
border-radius: 10px;
height: 20px;
border:solid 3px #FA5A57;
outline: none;
cursor:default;
text-align: center;
font-size: 10px;
z-index:999999;
}
</style>`;
var ps = 50; // 页数
var rid = 1; // 类型(1:综合)
// var cookie = document.cookie;
// console.log(cookie)
var data
// api删除原数据
var pre = document.getElementsByTagName('pre')
if(pre.length != 0){
pre[0].remove();
}
// 主站隐藏原数据(旧)
var olddiv = document.getElementsByClassName('b-wrap');
for(let i in olddiv){
if(i > 1){
olddiv[i].style.display = "none";
}
}
olddiv = document.getElementsByClassName('international-footer');
if(olddiv.length != 0){
olddiv[0].style.display = "none";
}
// 主站隐藏原数据(新)
var newdiv = document.getElementsByClassName('bili-layout');
if(newdiv.length != 0){
newdiv[0].style.display = "none";
}
// 请求推荐api
function getvideo(){
GM_xmlhttpRequest({
url:"https://api.bilibili.com/x/web-interface/dynamic/region?ps=" + ps + "&rid=" + rid,
// url:"https://api.bilibili.com/x/web-interface/popular?ps=50&pn=10",
method:"get",
// cookie:cookie,
onload:function(xhr){
data = JSON.parse(xhr.response)
console.log(data.data.archives)
// 添加元素
let div = document.createElement("div");
div.classList.add('add-main');
for(let i of data.data.archives){
//div.innerHTML += '<div class="add-div">'
//div.innerHTML += '<a href="https://www.bilibili.com/video/' + i.bvid + '" target="_blank"><img class="add-img" src="' + i.pic + '" /></a><br>'
//div.innerHTML += '<a class="add-a" href="https://www.bilibili.com/video/' + i.bvid + '" target="_blank">' + i.title + '</a></div>';
// 视频总div
let id = document.createElement("div");
div.appendChild(id);
id.classList.add('add-div');
// 图片链接
let a1 = document.createElement("a");
id.appendChild(a1);
a1.innerHTML = '<img class="add-img" src="' + i.pic + '" />'
a1.setAttribute('href',"https://www.bilibili.com/video/" + i.bvid );
a1.setAttribute('target',"_blank");
// 文字链接
let a2 = document.createElement("a");
id.appendChild(a2);
a2.classList.add('add-a');
a2.setAttribute('href',"https://www.bilibili.com/video/" + i.bvid );
a2.setAttribute('target',"_blank");
// 文字
let txt = document.createTextNode(i.title);
a2.appendChild(txt);
// 作者
let a3 = document.createElement("a");
id.appendChild(a3);
a3.classList.add('add-author');
a3.setAttribute('href',"https://space.bilibili.com/" + i.owner.mid );
a3.setAttribute('target',"_blank");
let author = document.createTextNode(i.owner.name);
a3.appendChild(author);
// 播放量,点赞,时常
let bds = document.createElement("div");
bds.classList.add('add-bds');
let b = i.stat.view;
if(i.stat.view >= 10000){
b = (i.stat.view/10000).toFixed(1) + '万'
}
let d = i.stat.like;
if(i.stat.like >= 10000){
d = (i.stat.like/10000).toFixed(1) + '万'
}
let s = i.duration;
if(i.duration >= 3600){
let mm = parseInt((i.duration%3600)/60);
if(mm < 10){
mm = '0' + mm;
}
let ss = i.duration%60;
if(ss < 10){
ss = '0' + ss;
}
s = parseInt(i.duration/3600) + ':' + mm + ':' + ss;
} else if(i.duration <= 3600 && i.duration >= 60){
let mm = parseInt(i.duration/60);
if(mm < 10){
mm = '0' + mm;
}
let ss = i.duration%60;
if(ss < 10){
ss = '0' + ss;
}
s = mm + ':' + ss;
} else {
let ss = i.duration%60;
if(ss < 10){
ss = '0' + ss;
}
s = '00:' + ss
}
bds.innerHTML = '<span style="padding-left:10px;float:left;line-height:22px"> ▶ ' + b + ' ❤ ' + d + '</span><span style="padding-right:10px;float:right;line-height:22px">' + s + '</span>';
id.appendChild(bds);
}
div.innerHTML += style;
// 设置添加位置
var header = document.getElementsByClassName('bili-layout');
if(header.length != 0){
header[0].parentNode.insertBefore(div, header[0]); // 新
} else {
document.body.append(div); // 旧
}
}
})
}
function getQueryVariable(variable){
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
// 进度条
let jindu = document.createElement("input");
jindu.classList.add('jindu');
jindu.setAttribute("value", "下载进度条");
jindu.setAttribute("readonly", "true");
document.body.append(jindu);
// 请求事件监听(每0.5s输出一次)
var ms= 500;
var lastClick = Date.now() - ms;
function downloadProgress(event, type) {
// 如果lengthComputable属性的值是false,那么意味着总字节数是未知并且total的值为零
if ((event.lengthComputable && Date.now() - lastClick >= ms) || event.loaded == event.total) {
let progress = event.loaded / event.total * 100;
jindu.setAttribute("value", `${type}下载${progress.toFixed(0)}%`);
console.log(`${type}下载${progress.toFixed(0)}%`);
// 更新时间
lastClick = Date.now();
}
}
getvideo();
var url = window.location.href;
var btn = document.createElement("input");
// 创建blob下载
function downloadVideo(data, filename, type, page){
try {
// 文件流可以自定义文件名
var blob = new Blob([data], { type: `${type}/mp4` });
var url = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = `${filename}-P${page}-${type}.mp4`;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url); // 释放 URL
console.log(`下载成功: ${filename}-P${page}-${type}.mp4`);
} catch (error) {
console.error("下载失败: ", error);
}
}
// 下载视频或音频
function download(url, name, type, page){
GM_xmlhttpRequest({
url: url,
method: "GET",
responseType: 'blob',
// cookie:document.cookie,
headers: {
'Referer': 'https://www.bilibili.com', // 根据实际情况设置
// 'Cookie':document.cookie,
},
onload: function(xhr) {
console.log("下载完成");
console.log(xhr.response)
downloadVideo(xhr.response, name, type, page);
},
onerror: function(error) {
console.error("下载失败", error);
},
onprogress: function(progress) {
downloadProgress(progress, type);
}
});
}
// 获下载链接
function getUrl(name, bv, cid, mod, page) {
var url = 'https://api.bilibili.com/x/player/playurl?bvid='+bv+'&cid='+cid+'&qn=120';
console.log(url);
if(mod == 3 || mod == 2){
url += '&fnval=4048';
}
GM_xmlhttpRequest({
url:url,
method:"get",
// cookie:cookie,
onload:function(xhr){
data = JSON.parse(xhr.response)
console.log(data);
var con = confirm('确认后视频开始下载,请耐心等待...\n下载视频及音频:'+name+'-P'+page);
if(con == true){
if(mod == 3 || mod == 2){
var videourl = data.data.dash.video[0].baseUrl;
console.log(videourl);
download(videourl, name, "video", page);
var audiourl = data.data.dash.audio[0].baseUrl;
console.log(audiourl);
download(audiourl, name, "audio", page);
} else {
var allurl = data.data.durl[0].url;
download(allurl, name, "all", page);
}
}
// 复制视频音频合并软件链接到剪切板
const input = document.createElement('input');
document.body.appendChild(input);
input.setAttribute('value', "https://gitee.com/z2322739526/mybilibili/blob/master/%E5%90%88%E5%B9%B6%E8%A7%86%E9%A2%91%E9%9F%B3%E9%A2%91.exe");
input.select(); // 选取文本域的内容
if (document.execCommand('copy')) {
document.execCommand('copy');
console.log('复制成功');
}
document.body.removeChild(input);
}
});
}
if(url.split('/')[3] == 'video' || url.split('/')[3] == "bangumi"){
// 下载按钮
btn.setAttribute("type", "button");
btn.setAttribute("value", "下载");
btn.classList.add('re');
document.body.append(btn);
var page = 1;
var bv = "";
btn.onclick = function(){
var page = 1;
var bv = "";
// 番剧类型获取bv
if(url.includes('www.bilibili.com/bangumi/play')){
const parentElement = document.querySelector('.mediainfo_mediaRight__SDOq4');
const divElement = parentElement.getElementsByTagName('div')[1]; // 第二个div(索引1)
const spanElement = divElement.getElementsByTagName('span')[3]; // 第四个span(索引3)
bv = spanElement.textContent;
} else {
bv = url.split('/')[4].split('?')[0];
if(getQueryVariable('p')){
page = getQueryVariable('p');
}
}
console.log('bvid:' + bv);
GM_xmlhttpRequest({
url:'https://api.bilibili.com/x/web-interface/view/detail?bvid='+bv,
method:"get",
// cookie:cookie,
onload:function(xhr){
data = JSON.parse(xhr.response);
console.log(data);
console.log(data.data.View);
var name = data.data.View.title;
var cid = data.data.View.pages[page-1].cid;
// cid = 268123629 // test
var aid = data.data.View.aid;
var part = data.data.View.pages[page-1].part;
console.log('aid:' + aid);
console.log('cid:' + cid);
// 判断是否是互动视频
// https://api.bilibili.com/x/player/wbi/v2?bvid=BV1DK411u7QX&cid=267642140
// https://api.bilibili.com/x/stein/nodeinfo?bvid=BV1DK411u7QX&graph_version=397257
GM_xmlhttpRequest({
url:'https://api.bilibili.com/x/player/wbi/v2?bvid='+bv+'&cid='+cid,
method:"get",
// cookie:cookie,
onload:function(xhr){
data = JSON.parse(xhr.response)
console.log(data);
var graph_version = 0;
if('interaction' in data.data){
console.log('互动视频graph_version:' + data.data.interaction.graph_version);
graph_version = data.data.interaction.graph_version;
} else {
console.log('未检测到interaction字段,该视频非互动视频');
}
var mod = 1; // 默认1直接完整视频,2视频音频分别下载,3互动视频
if(graph_version != 0){
// 互动视频
GM_xmlhttpRequest({
url:'https://api.bilibili.com/x/stein/nodeinfo?bvid='+bv+'&graph_version='+graph_version,
method:"get",
// cookie:cookie,
onload:function(xhr){
data = JSON.parse(xhr.response)
console.log(data);
var story_list = data.data.story_list;
var outlist = {}
var outtext = "检测到该视频为互动视频,视频音频合并软件链接将在确认后复制到剪切板,请输入下载视频名称对应id:\n"
for(let i of story_list){
outlist[i.cursor] = [i.title, i.cid];
// outtext += 'id:' + i.cursor + '-' + i.title + ',';
outtext += `${i.title}(id=${i.cursor});`
}
var id = 0; // 默认为0
id = prompt(outtext);
cid = outlist[id][1];
name += "-" + outlist[id][0];
console.log('互动视频cid:' + cid);
mod = 3;
getUrl(name, bv, cid, mod, page);
}
});
} else {
// 非互动视频
mod = prompt("请选择下载模式id:\nid:1-直接下载视频,画质较低(默认)\nid:2-分别下载视频音频,画质较高(视频音频合并软件链接将在确认后复制到剪切板)")
getUrl(name, bv, cid, mod, page);
}
}
});
}
});
}
}else{
// 刷新按钮
btn.setAttribute("type", "button");
btn.setAttribute("value", "刷新");
btn.classList.add('re');
document.body.append(btn);
btn.onclick = function(){
document.body.scrollTop = document.documentElement.scrollTop = 0;
var dd = document.getElementsByClassName('add-main');
for(let j of dd){
j.style.display = "none";
}
getvideo(); // 请求后刷新也会请求一次,这里待优化
}
}
// 顶部按钮
var top = document.createElement("input");
top.setAttribute("type", "button");
top.setAttribute("value", "顶部");
top.classList.add('top');
document.body.append(top);
top.onclick = function(){
document.body.scrollTop = document.documentElement.scrollTop = 0;
}
// 下拉刷新
let timeout = null;
window.onscroll = function() {
const scrollH = document.documentElement.scrollHeight;// 文档的完整高度
const scrollT = document.documentElement.scrollTop || document.body.scrollTop; // 当前滚动条的垂直偏移
const screenH = window.screen.height; // 屏幕可视高度
if ((scrollH - scrollT - screenH) < 500) { // 只是一个相对值,可以让页面再接近底面的时候就开始请求
timeout && clearTimeout(timeout); // 判断timeout是否在执行
timeout = setTimeout(() => {
console.log('下拉刷新')
getvideo();
}, 3000); // api在3s内请求返回重复内容
}
};
})();