news 2026/9/19 23:03:53

Bilibili-Evolved 稍后再看重定向组件解析:将稍后再看链接一键重定向为普通播放网址

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Bilibili-Evolved 稍后再看重定向组件解析:将稍后再看链接一键重定向为普通播放网址

Bilibili-Evolved 稍后再看重定向组件解析:将稍后再看链接一键重定向为普通播放网址

【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved

稍后再看重定向(watchlaterRedirect)是 Bilibili-Evolved 脚本中一个小而精的实用组件,它的核心职责是把「稍后再看」场景下产生的链接统一重定向为普通的 bilibili 视频播放网址。本文以 组件说明文档 为骨架,结合组件入口源码、稍后再看数据 API 与自定义顶栏的集成代码,逐层剖析该组件的两个开关选项、重定向算法与 DOM 监听机制,帮助读者理解增强脚本如何在不侵入页面结构的前提下改写导航链接,并掌握在自定义顶栏中联动组件设置的正确姿势。

组件定位:解决什么痛点

「稍后再看」是 bilibili 提供的视频收藏播放功能,其列表页与自定义顶栏面板中的卡片链接默认指向https://www.bilibili.com/list/watchlater?bvid=...这类带watchlater语义的地址。这类地址在分享、转发或直接访问时体验不佳,且进入后是稍后再看专属的播放环境。该组件做的事情非常直接——将稍后再看的链接重定向为普通播放网址https://www.bilibili.com/video/{bvid}/),让链接回归标准视频页语义。

从组件元数据可以看出它的作用范围被严格限定在三个稍后再看相关页面(见 index.ts):

  • https://www.bilibili.com/watchlater/#/list
  • https://www.bilibili.com/watchlater/list#/list
  • https://www.bilibili.com/watchlater/list

urlInclude字段声明组件仅在上述页面注入执行,组件标签(tags)同时挂载在componentsTags.utilscomponentsTags.video下,归类为视频类实用工具。

两个配置开关:页面重定向与顶栏重定向

原文档对组件的功能说明非常凝练,共两条:

  • 重定向页面:对稍后再看列表页面里的链接重定向。
  • 重定向顶栏:对自定义顶栏里的稍后再看链接重定向。

对应到组件元数据中的两个布尔选项(见 index.ts):

选项键显示名默认值生效位置
page重定向页面true稍后再看列表页面(组件自身 entry 逻辑)
navbar重定向顶栏true自定义顶栏的稍后再看面板(由NavbarWatchlater.vue读取)

两个选项虽然同属一个组件,但生效机制完全不同page由组件自身的入口函数直接消费,而navbar是被「自定义顶栏」这个独立组件跨组件读取的。这是理解该组件设计的关键——它不是一个单纯的自包含功能,而是一个"可被其他组件复用其设置"的联动型开关。

选项一:重定向页面(page)

入口函数的第一行就是对page选项的判定(见 index.ts):

const entry: ComponentEntry = async ({ settings }) => { if (!settings.options.page) { return } // ... }

当用户关闭「重定向页面」后,入口函数直接返回,列表页的链接重定向逻辑完全不再执行。该选项控制的是稍后再看列表页中视频卡片链接的改写。

选项二:重定向顶栏(navbar)

navbar选项不在 entry 中使用,而是由自定义顶栏的稍后再看弹窗组件读取(见 NavbarWatchlater.vue):

data() { const redirect = getComponentSettings('watchlaterRedirect') return { // ... redirect: redirect.enabled && redirect.options.navbar, } }

这里通过getComponentSettings('watchlaterRedirect')跨组件获取本组件设置,并取「组件启用」与「重定向顶栏开启」的交集。顶栏卡片生成链接时依据该开关分流(见 NavbarWatchlater.vue):

const getLink = (item: RawWatchlaterItem) => { if (this.redirect) { return `https://www.bilibili.com/video/${item.bvid}/` } return `https://www.bilibili.com/list/watchlater?bvid=${item.bvid}` }

即:顶栏重定向开启时,顶栏内稍后再看卡片的跳转地址直接变为普通视频页;关闭时保留原始的watchlater列表地址。同时注意读取条件是redirect.enabled && redirect.options.navbar——即使顶栏开关为开启状态,若整个「稍后再看重定向」组件被禁用,顶栏也不会重定向。这一联动细节对使用自定义顶栏的用户尤为重要。

页面重定向的底层实现:三步改写链接

页面重定向的完整逻辑位于入口函数entry中,核心分为「获取数据 → 定位容器 → 改写链接」三步。

第一步:拉取稍后再看原始列表

const list: RawWatchlaterItem[] = await getWatchlaterList(true)

getWatchlaterList(true)的第二个参数raw表示返回未转换过的原始数据列表(见 src/components/video/watchlater.ts)。其底层请求 bilibili 开放接口https://api.bilibili.com/x/v2/history/toview/web,返回的数据结构RawWatchlaterItem包含bvidcidpages(分 P 信息)、progress(观看进度)等关键字段。该接口需要登录态,未登录时函数会输出账号未登录警告并返回空数组——这也是该组件的使用前提:必须登录 bilibili 账号

第二步:定位列表容器并提取 bvid

const listContainer = await select('.watch-later-list .list-box > span, .watchlater-list')

使用select(来自 src/core/spin-query.ts,一个轮询等待元素出现的查询工具)等待稍后再看列表容器出现。随后对每个视频卡片执行tryRedirect

  • isRedirected(element):检查封面链接是否已包含/video/BV特征,已重定向过的卡片直接跳过,保证幂等;
  • getBvidFromElement(element):从封面元素.av-pic, .bili-cover-cardhref中通过正则/bvid=([^&]+)/提取bvid
  • 用提取到的bvid在第一步拉取的原始列表中find匹配项,找不到则输出告警日志跳过。

两个失败路径(bvid 提取失败、列表无匹配项)都会通过console.warn输出诊断信息,方便在控制台排查。

第三步:根据分 P 构造普通播放地址

核心改写逻辑(见 index.ts):

const { bvid, cid, pages } = watchlaterItem const page = pages.find(p => p.cid === cid)?.page ?? 1 const url = page > 1 ? `https://www.bilibili.com/video/${bvid}/?p=${page}` : `https://www.bilibili.com/video/${bvid}/`

这里体现了对多 P 视频的精细处理:通过当前播放分 P 的cidpages中找到对应的page序号,第一 P 直接生成https://www.bilibili.com/video/{bvid}/,非第一 P 则追加?p={page}参数,确保重定向后仍能回到用户正在观看的那一集。改写同时作用于封面链接(.av-pic, .bili-cover-card)与标题链接(.av-about .t, .bili-video-card__title a, .video-card__right .title),并且都设置了target = '_blank',保证新标签页打开。整个改写过程被try/catch包裹,单卡失败不会影响其他卡片。

动态监听:防抖 + MutationObserver

稍后再看列表支持翻页、删除等操作,DOM 会持续变化,因此组件没有只做一次性改写,而是双管齐下:

const runRedirect = lodash.debounce(() => { /* 遍历所有卡片改写 */ }, 200) runRedirect() // 初始执行一次 childListSubtree(listContainer, async records => { // 检测新增节点是否包含视频卡片特征类名 if (hasVideoCardChange) { runRedirect() } })
  • 首次进入页面立即执行一次runRedirect
  • 之后通过childListSubtree(来自 src/core/observer.ts,监听目标节点及其所有子孙节点的childList变化)观察列表容器的增删,当新增节点带有bili-video-card__wrapvideo-cardwatchlater-list-container等卡片特征类名时再次触发改写;
  • 改写逻辑用lodash.debounce(..., 200)做了 200ms 防抖,避免频繁 DOM 变化导致的高频重跑。

这套「初始化执行 + 增量监听 + 防抖合并」的组合,是该组件应对 SPA 动态列表的通用模式。

依赖的稍后再看数据层:getWatchlaterList 与相关 API

页面重定向和顶栏重定向都依赖 src/components/video/watchlater.ts 提供的稍后再看能力,该模块是整个"稍后再看"生态的数据中枢:

  • getWatchlaterList(raw?):请求x/v2/history/toview/web接口,返回 aid 列表或原始条目列表,同时维护内存中的watchlaterList缓存,并随返回结果自动增删;
  • toggleWatchlater(aid, add?):调用toview/addtoview/del接口添加/移除稍后再看,需要携带 CSRF 凭证;
  • 模块顶部还注释了相关接口的备用地址(toview/deltoview/clear);
  • 模块在脚本空闲时(requestIdleCallback)且已登录的情况下会预取一次列表,保证后续各组件读取时有较新的缓存。

顶栏面板(NavbarWatchlater.vue)同样基于getWatchlaterList(true)渲染卡片,并利用item.pages.find(p => p.cid === item.cid)计算当前分 P 时长、用item.progress / duration计算观看进度百分比(超过 95% 或-1视为看完),可见稍后再看的数据模型在整个生态中被多处复用。

与相邻组件的关系与使用边界

仓库中还存在一个功能相邻的组件「稍后再看页面重定向」(watchlater-page-redirect,见 registry/lib/components/utils/watchlater-page-redirect/index.ts)。从其描述可知两者分工明确:本组件是直接改写列表/顶栏中的链接,而后者是在进入稍后再看的视频页面后进行跳转,用于补充本组件覆盖不到的场景(例如通过其他入口进入的稍后再看播放页)。用户可根据实际遇到的入口类型决定启用哪个。

小结

「稍后再看重定向」组件虽小,却完整展现了 Bilibili-Evolved 增强脚本的典型工程模式:通过defineComponentMetadata声明元数据与开关,入口函数按选项分流;数据层统一收敛到watchlater.ts的 API 封装;DOM 改写遵循「幂等判定 + 防抖批量处理 + MutationObserver 增量监听」的稳健策略;跨组件联动则通过getComponentSettings读取设置形成可组合的开关体系。对想了解增强脚本如何安全地操作 SPA 动态页面,或计划在自定义顶栏中复用组件设置的开发者而言,组件入口源码、稍后再看数据模块 与 顶栏集成组件 三份文件构成了完整的研读路径。

【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 23:03:01

MySQL CPU飙升排查与优化实战:从原理到命令全解析

数据库CPU被打满,应该是所有后端开发、DBA以及运维同学都经历过的噩梦。尤其是线上业务报障,看到告警群里“MySQL CPU使用率 > 95%”的红色消息,心跳都得漏半拍。很多人在这一步容易慌,上来就重启数据库或者直接kill掉一堆进程…

作者头像 李华
网站建设 2026/9/19 23:01:46

VS Code插件与环境配置实战:从编辑器到高效开发工作流

刚接触 VS Code 的人,往往会被它的插件市场吓一跳——搜一个 "Chinese" 能出来几十个结果,配一个 C/C 环境能搜到一堆教程但照着做还是报错。作为从 Sublime 转过来、用了好几年 VS Code 的深度用户,我想把平时真正沉淀下来、每天都…

作者头像 李华
网站建设 2026/9/19 23:01:17

Spring Boot教学辅助平台:权限设计、Redis签到与部署实战

简介:基于SpringBoot的教学辅助平台设计与实现完整文档,面向高校计算机相关专业学生、JavaWeb初学者及需要完成类似课题的毕业设计者,提供从需求分析到系统实现的整体参考。包内共1个docx文件,大小1.36MB,即该课题的完…

作者头像 李华
网站建设 2026/9/19 22:59:29

QuickRecorder 轻量录屏完整上手指南:免虚拟声卡录系统声音

QuickRecorder 轻量录屏完整上手指南:免虚拟声卡录系统声音 【免费下载链接】QuickRecorder A lightweight screen recorder based on ScreenCapture Kit for macOS / 基于 ScreenCapture Kit 的轻量化多功能 macOS 录屏工具 项目地址: https://gitcode.com/GitHu…

作者头像 李华
网站建设 2026/9/19 22:58:17

系统分析师论文备考:拆解范文结构与构建素材库的实战方法

简介:面向全国计算机软考系统分析师论文备考者,这份范文PDF围绕“Java技术在因特网平台上的应用”展开,以通信信息服务平台为真实案例,完整呈现论文摘要、正文论述与结尾策略,适合需要快速熟悉论文结构、积累技术素材与…

作者头像 李华
网站建设 2026/9/19 22:56:53

Vibe Gaming 一人工作室微信小游戏开发实战:AI编程与变现全链路

一人工作室做微信小游戏,最真实的体感是:你既是策划、美术、程序,也是测试和运营。过去两年我陆续用 AI 编程工具配合微信开发者工具,独立完成了三款小游戏的上线与迭代,踩过的坑从环境配置到排行榜接入、从广告变现到…

作者头像 李华