对于很多视频网站我并不希望默认进行循环,因为现在很多视频特别短,如果循环的话就很容易洗脑……
同样我也不希望默认自动下一集,虽然听起来这是一个很有用的功能,但如果合集是一个歌单我只想单曲循环其中某一个,或者只是某个up主的某一系列合集我只想看其中一个。自动连播也会给我带来一些困扰。
当然这些都有选项可以进行设置,但这些设置项都是全站统一的。我默认将它们关闭,但是对某个视频我又需要这样功能的时候就比较尴尬。当然可以打开这些选项但是就会忘记关闭,下一次带来困惑。
是我需要一些临时选项,在当前视频中开启,但这个设置并不会影响到这个网站的其他视频。
以前也写过类似的脚本,但是后来因为网站改版导致布局有些错乱。最近忽然想到这件事情似乎有一个简单的实现方法,然后就花几分钟撸了个脚本出来。
使用方法
非常粗暴:(脚本下方有快捷使用的小书签)
- 如果你想让这个视频单曲循环,就在网址后面加上
#loop,然后回车 - 如果你想让视频自动播放下一集就在网址后面加上
#next,然后回车
脚本如下:
// ==UserScript==
// @name 哔哩哔哩简易循环 2.0
// @namespace Bilibili Simple Loop
// @version 2025-12-11
// @description 不想在设置里开启循环/自动连播,但听歌的时候又希望能够单曲循环/自动连播,给他加一个临时开关
// @author dms
// @match https://www.bilibili.com/video/*
// @match https://www.bilibili.com/bangumi/play/*
// @icon https://i0.hdslb.com/bfs/static/jinkela/long/images/favicon.ico
// @contributionURL https://afdian.com/a/daomishu
// @grant none
// ==/UserScript==
(function() {
'use strict';
/**
* 从 URL 查询字符串中获取指定参数的值
* @param {string} name - 要获取的参数名
* @returns {string|null} - 返回参数值,如果参数不存在则返回 null
*/
const getQuery = (name) => {
// 构建匹配参数的正则表达式
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
// 获取 URL 中的查询字符串并进行匹配
const r = window.location.search.substring(1).match(reg);
// 如果找到匹配项则解码并返回参数值,否则返回 null
return r != null ? decodeURIComponent(r[2]) : null;
}
/**
* next 确实可以通过点击下一首的按钮(`#bilibili-player div.bpx-player-ctrl-btn.bpx-player-ctrl-next`)来实现
* 但这样无法把 hash 带过去,导致只能执行一次。
* 而循环不会造成页面刷新所以不存在这个问题。
* 但循环并没有使用点击按钮的方案,即如下循环规则并没有实际应用。
*/
const rules = {
'www.bilibili.com': {
'video': {
loop: '#bilibili-player div.bpx-player-ending-functions-btn[data-action="restart"]',
next: (url) => {
const p = getQuery('p') ? +getQuery('p') : 1;
return url.split(/\?|#/)[0] + `?p=${p+1}#next`;
}
},
'bangumi': {
loop: '#bilibili-player div.bpx-player-ending-functions-btn[data-action="restart"]',
next: (url) => {
const p = url.match(/\/ep(\d+)/i)[1];
console.log(p)
return p ? url.replace(p, (+p+1)) : false;
}
}
}
}
/**
* 根据当前页面 URL 获取对应的规则配置
* @returns {Object|false} 返回匹配的规则对象,如果没有匹配则返回 false
*/
const getRule = () => {
const host = window.location.host;
// 获取当前页面的路径
const path = window.location.pathname;
// 从规则配置中获取对应主机名的规则
const rule = rules[host];
// 如果没有找到对应主机名的规则,返回 false
if (!rule) return false;
// 从路径中提取视频类型(video 或 bangumi)
const type = path.match(/\/(video|bangumi)\//i)[1];
// 返回对应类型的具体规则
return rule[type];
}
// 获取视频播放器元素
const video = document.querySelector('#bilibili-player video');
const rule = getRule();
const runAction = () => {
if (rule) {
const hash = window.location.hash;
if (hash === '#loop') {
// document.querySelector(rule.loop).click();
video.currentTime = 0;
video.play();
return;
}
if (hash === '#next') {
const newUrl = rule.next(window.location.href);
if (newUrl) window.location.href = newUrl;
return;
}
}
}
const videoWaiter = window.setInterval(() => {
if (video) {
window.clearInterval(videoWaiter);
video.addEventListener('ended', runAction);
}
}, 1000);
})();
原理么……注释应该写的非常清楚了。
理论上一些手机浏览器应该也可以用,因为没有使用任何特殊接口。但具体效果我没测试过,也不做支持。毕竟在手机上,我们应该都会去用客户端的。
小书签
把如下小书签拖入书签栏(在论坛没法制作可拖动的小书签所以自己手动添加一下吧),在视频播放页面点击小书签启用对应功能:
- 开启单曲循环:
javascript:void(window.location.hash='#loop') - 开启自动连播:
javascript:void(window.location.hash='#next') - 取消一切效果:
javascript:void(window.location.hash='')
如果觉得我很可爱,请务必 老鼠爱发电