TypeScript初戰Chrome插件:Bilibili彈幕熱度

TL;DR

這是一個用來在B站視頻進度條上方建立顯示彈幕熱度的Chrome插件,以彈幕數量-時間的直方圖顯示,在高能處(定義爲短期內有大量彈幕出現的時間點)有明顯的峯值,能夠用來直觀地看視頻中的熱點,也能夠拿來做爲空降(跳躍快進)的指示。html

已經上架Chrome插件市場,在這裏或者搜【Danmaku】就能找到。前端

源代碼在GitHub,歡迎Star。jquery

Chrome Webstore

背景

其實作一個這樣的插件的想法已經在腦海裏盤桓好一陣了(創意來源於某Hub),直到最近纔有空(摸魚)寫了出來,正好拿來做爲TypeScript跟Chrome Extension的練手項目。git

實現

插件的實現主要分爲以下幾個部分:github

  • 代碼注入
  • 獲取av號及分P
  • 獲取彈幕
  • 可視化
  • 監控網頁重載

基於chrome-extension-typescript-starter的腳手架。web

比較核心的庫

  • TypeScript
    • 類型系統用來靜態檢查/代碼提示的效率提高仍是十分顯著的,也減小了一些很蠢的bug的發生
  • echarts
    • 百度家的圖表庫,用來生成直方圖
  • rxjs
    • 觀察者 + 迭代器模式的實現
  • jquery
    • 簡易的DOM操做

代碼注入

依靠Chrome Extension的manifest.json文件能夠指定在bilibili的頁面中執行指定的代碼文件。chrome

獲取av號、分P

av號跟分P信息通常可從url中直接得到(形如https://www.bilibili.com/video/avXXXXX/?p=XXXX),但事實上B站的視頻格式分不少種,目前光我見到的就有下面幾種:typescript

  • 普通視頻/video/avXXXXX/?p=XXXX
  • 稍後再看/watchlater/#/avXXXXXX/pXXXX
  • 從歷史觀看中進入/video/avXXXXXX/index_XXXXX.html
  • 番劇
    • 具體的某一集/bangumi/play/epYYYYY/
    • 從【番劇】分區中直接點進/bangumi/play/ssZZZZZ

所以須要有不一樣的處理,特別是番劇,url中沒有av號信息,須要從DOM中獲取。json

獲取彈幕

B站每一個視頻都有一個av號,但因爲每一個視頻有可能有多個分P,所以B站還有一個隱含的cid用以索引一個具體的視頻(以及彈幕),經過分析找到了這個API: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更新事件。

相關文章
相關標籤/搜索