V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Get Google Chrome
Vimium · 在 Chrome 里使用 vim 快捷键
MegrezZhu
V2EX  ›  Chrome

TypeScript 初战 Chrome 插件: Bilibili 弹幕热度

  •  2
     
  •   MegrezZhu · 2018-07-23 13:36:32 +08:00 · 2048 次点击
    这是一个创建于 2322 天前的主题,其中的信息可能已经有所发展或是发生改变。

    TL;DR

    这是一个用来在 B 站视频进度条上方创建显示弹幕热度的 Chrome 插件,以弹幕数量-时间的直方图显示,在高能处(定义为短时间内有大量弹幕出现的时间点)有明显的峰值,可以用来直观地看视频中的热点,也可以拿来作为空降(跳跃快进)的指示。

    已经上架 Chrome 插件市场,在这里或者搜 [ Danmaku ] 就能找到。

    源代码在GitHub,欢迎 Star。

    Chrome Webstore

    背景

    其实做一个这样的插件的想法已经在脑海里盘桓好一阵了(创意来源于某 Hub ),直到最近才有空(摸鱼)写了出来,正好拿来作为 TypeScript 跟 Chrome Extension 的练手项目。

    实现

    插件的实现主要分为如下几个部分:

    • 代码注入
    • 获取 av 号及分 P
    • 获取弹幕
    • 可视化
    • 监控网页重载

    基于chrome-extension-typescript-starter的脚手架。

    比较核心的库

    • TypeScript
      • 类型系统用来静态检查 /代码提示的效率提升还是十分显著的,也减少了一些很蠢的 bug 的发生
    • echarts
      • 百度家的图表库,用来生成直方图
    • rxjs
      • 观察者 + 迭代器模式的实现
    • jquery
      • 简易的 DOM 操作

    代码注入

    依靠 Chrome Extension 的manifest.json文件可以指定在 bilibili 的页面中执行指定的代码文件。

    获取 av 号、分 P

    av 号跟分 P 信息一般可从 url 中直接获得(形如https://www.bilibili.com/video/avXXXXX/?p=XXXX),但事实上 B 站的视频格式分很多种,目前光我见到的就有下面几种:

    • 普通视频/video/avXXXXX/?p=XXXX
    • 稍后再看/watchlater/#/avXXXXXX/pXXXX
    • 从历史观看中进入/video/avXXXXXX/index_XXXXX.html
    • 番剧
      • 具体的某一集/bangumi/play/epYYYYY/
      • 从 [番剧] 分区中直接点进/bangumi/play/ssZZZZZ

    因此需要有不同的处理,特别是番剧,url 中没有 av 号信息,需要从 DOM 中获取。

    获取弹幕

    B 站每个视频都有一个 av 号,但由于每个视频有可能有多个分 P,因此 B 站还有一个隐含的 cid 用以索引一个具体的视频(以及弹幕),通过分析找到了这个 API:

    https://api.bilibili.com/x/player/pagelist?aid=AV_ID&jsonp=jsonp

    其实 cid 可以有多种方法获得,包括网页 DOM、原网页 HTML 等等,但由于 B 站视频分类众多(普通视频、番剧、稍后再看、历史观看)且网页 DOM 都有不同,因此还是用这个 API 比较优雅

    可以通过 av 号拿到该视频每个分 P 的 cid 以及视频长度,然后通过 API

    https://comment.bilibili.com/CID.xml

    能够获取 xml 格式的弹幕数据,告一段落

    弹幕数据的解析参考自这篇博客

    生成直方图

    这个倒简单,处理一下弹幕数据调用 echarts 的 API 即可。

    监控网页重载

    在用户点击切换分 P 或者其他操作的时候,B 站前端用的是 HTML5 的 History API (也有的是 hashchange ),因此不能光用 window.onhashchange 事件来监控。而对于 H5 History 的监控,标准上又只有 onpopstate 事件,没有 onpushstate (这一点是我比较困惑的,望有人解惑)。

    因此只能使用折中的方案:利用插件的 background script 以及 webNavigation 权限监控所有 B 站选项卡的 history 更新(通过 chrome 提供的 onHistoryStateUpdated 事件),并且建立 content_script 与 background_script 的连接进行单点通知,触发页面中的 url 更新事件。

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2515 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 04:55 · PVG 12:55 · LAX 20:55 · JFK 23:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.