B站视频时长统计:一段JS脚本搞定分P/合集总时长(附倍速计算)

B站视频时长统计:一段JS脚本搞定分P/合集总时长(附倍速计算)

前言

追B站的分P教程或合集剧时,经常想知道"全P看完要多久""2倍速几天能刷完"。网上流传的书签脚本大多基于 DOM 类名(如 .duration、.cur-list)解析,B站 2023 年改版后选择器换成 video-episode-card__info-duration,老代码基本失效。

本文提供一个更抗改版的思路:直接调 B 站官方接口 api.bilibili.com/x/web-interface/view 拉取分P/合集数据,不依赖页面 DOM,只要接口在就能用。

支持两种运行方式:Console 控制台版(推荐)和书签版,均支持指定集数区间 和倍速换算。

方式一:Console 控制台版(推荐)

  1. 打开任意带分P或合集的B站视频页(URL 形如 bilibili.com/video/BVxxxx/?p=1)
  2. 按 F12 打开开发者工具,切到 Console 标签
  3. 粘贴以下代码,回车运行

⚠️ Chrome/Edge 首次粘贴会提示安全警告,需先手动输入 allow pasting 回车开启粘贴权限。

js 复制代码
(async () => {
  // ① 从 URL 抠出 BV 号
  const m = location.href.match(/BV[0-9A-Za-z]+/);
  if (!m) { alert('请在 B 站视频页运行,未识别到 BV 号'); return; }

  // ② 调 B 站官方接口拿视频信息(含分P / 合集)
  const r = await fetch(`https://api.bilibili.com/x/web-interface/view?bvid=${m[0]}`)
                  .then(res => res.json());
  if (r.code !== 0) { alert('接口返回异常:' + r.message); return; }

  // ③ 兼容两种形态:单视频多P / 合集
  let items = [];
  if (r.data.pages && r.data.pages.length > 1) {
    items = r.data.pages.map(p => ({ title: p.part, dur: p.duration }));
  } else if (r.data.ugc_season) {
    r.data.ugc_season.sections.forEach(sec =>
      sec.episodes.forEach(ep =>
        items.push({ title: ep.title, dur: ep.duration })));
  }
  if (!items.length) { alert('该视频只有一P,也没在合集里'); return; }

  // ④ 统计区间
  const input = prompt(`共 ${items.length} 个视频。\n输入区间如 5-20(直接确定=全部)`, `1-${items.length}`);
  if (input === null) return;
  let [a, b] = input.trim().split('-').map(Number);
  if (!a || a < 1) a = 1;
  if (!b || b > items.length) b = items.length;
  const slice = items.slice(a - 1, b);

  // ⑤ 求和 + 格式化
  const total = slice.reduce((s, it) => s + (it.dur || 0), 0);
  const fmt = s => {
    const h = Math.floor(s/3600), m = Math.floor(s%3600/60), sec = s%60;
    return h ? `${h}小时${m}分${sec}秒`
         : m ? `${m}分${sec}秒`
             : `${sec}秒`;
  };

  // ⑥ 倍速换算
  const sp = parseFloat(prompt('按几倍速看?(直接确定=原速)', '1')) || 1;
  const spTotal = Math.round(total / sp);

  alert(`📊 统计结果\n━━━━━━━━━━\n范围:第 ${a} ~ ${b} 集(共 ${slice.length} 个)\n原时长:${fmt(total)}\n${sp}x 倍速看完:${fmt(spTotal)}`);
})();

运行效果(以 84 集合集为例):

复制代码
📊 统计结果
━━━━━━━━━━
范围:第 1 ~ 84 集(共 84 个)
原时长:33小时35分12秒
1x 倍速看完:33小时35分12秒

方式二:书签版(可反复点击)

代码与上面完全一致,只是换个存放位置:

  1. 书签栏右键 → 添加网页/新书签
  2. 名称随意(如"B站时长统计"),网址栏粘贴整段代码
  3. ⚠️ Chrome/Edge 会自动吞掉开头的 javascript:,粘贴后手动补上,否则点击会变成搜索跳转
  4. 打开B站视频页 → 点击书签即可

常见问题排查

报错/现象 原因 解决
控制台报 Refused to paste Chrome/Edge 首次粘贴拦截 Console 输入 allow pasting 回车后重贴
接口返回 -412 触发B站风控(登录态失效/频率过快) 重新登录B站,或稍等几秒再跑
提示"只有一P,也没在合集里" 打开的是单P视频 换带分P列表/合集侧栏的视频页
书签点完没反应 javascript: 前缀被浏览器吞掉 编辑书签,确认开头为 javascript:

原理说明

为什么不用 DOM 解析:

  • 老方案依赖页面类名(.duration 等),B站前端一改版就失效
  • web-interface/view 是B站官方公开接口,返回 JSON 中直接带有:
    • pages[]:多P视频的每P标题与 duration(秒)
    • ugc_season.sections[].episodes[]:合集内每个视频的标题与时长
  • 时长单位为秒,累加后做一次进制换算即可

局限与备注

  • 仅适用于分P视频 和UGC合集页面,单P视频、收藏夹、搜索页无数据可拉
  • B站接口存在风控升级的可能(如 WBI 签名),若日后大量返回 -403/-412,需适配新签名
  • 嫌每次粘贴麻烦的话,也可以在 Greasy Fork 搜索"B站合集时长统计"类油猴脚本,装完自动显示

总结

本文提供了一个基于B站官方 API 的视频时长统计脚本,相比老版 DOM 解析方案更抗改版,支持集数区间选择和倍速换算。Console 版适合临时用一次,书签版适合高频使用。觉得有用的话点个赞吧~

相关推荐
音视频牛哥44 分钟前
不换摄像机,也能接入 WebRTC?SmartMediaKit RTSP/RTMP 转 WHIP 技术实践
音视频·webrtc·smartmediakit·rtsp转whip·rtmp转whip·whip推流·rtsp转webrtc播放
迷途小羔羊1 小时前
环境搭建
前端·javascript·后端
XiYang-DING1 小时前
P5528.带过期时间的 LRU 缓存
java·开发语言·缓存
小徐不徐说1 小时前
C++ 机器视觉入门:从零搭建 AOI 开发环境(OpenCV + CMake)
开发语言·c++·opencv
lll23526917791 小时前
Android APP短视频音频提取,主流工具怎么选
ffmpeg·音视频
zhangx1234_2 小时前
javaEE 多线程4
java·开发语言
大陈子编程2 小时前
C++ 背包九讲:从入门到精通的动态规划专题
开发语言·c++·动态规划
qq_401700412 小时前
Qt 组播(Multicast)实战详解
开发语言·qt
酷炫码神2 小时前
Day 9|Vue Router:把单页后台拆成能跳转的多页面
前端·javascript·vue.js