diff --git a/docs/README.md b/docs/README.md
index 075a4158d7..985e5b86df 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -297,6 +297,8 @@ RSSHub 提供下列 API 接口:
+
+
#### 直播开播
diff --git a/lib/router.js b/lib/router.js
index a7cc9e9a4d..5583d28029 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -123,6 +123,7 @@ router.get('/bilibili/partion/ranking/:tid/:days?', require('./routes/bilibili/p
router.get('/bilibili/bangumi/:seasonid', require('./routes/bilibili/bangumi')); // 弃用
router.get('/bilibili/bangumi/media/:mediaid', require('./routes/bilibili/bangumi'));
router.get('/bilibili/video/reply/:aid', require('./routes/bilibili/reply'));
+router.get('/bilibili/video/danmaku/:aid/:pid?', require('./routes/bilibili/danmaku'));
router.get('/bilibili/link/news/:product', require('./routes/bilibili/linkNews'));
router.get('/bilibili/live/room/:roomID', require('./routes/bilibili/liveRoom'));
router.get('/bilibili/live/search/:key/:order', require('./routes/bilibili/liveSearch'));
diff --git a/lib/routes/bilibili/cache.js b/lib/routes/bilibili/cache.js
index b53f5db0c0..21c7f1b124 100644
--- a/lib/routes/bilibili/cache.js
+++ b/lib/routes/bilibili/cache.js
@@ -102,4 +102,24 @@ module.exports = {
}
return name;
},
+ getCidFromAid: async (ctx, aid, pid) => {
+ const key = `bili-Cid-from-Aid-${aid}-${pid}`;
+ let cid = await ctx.cache.get(key);
+ if (!cid) {
+ const cidResponse = await axios({
+ method: 'get',
+ url: `https://api.bilibili.com/x/web-interface/view?aid=${aid}`,
+ headers: {
+ Referer: `https://www.bilibili.com/video/av${aid}`,
+ },
+ });
+ if (cidResponse && cidResponse.data && cidResponse.data.data && cidResponse.data.data.pages && cidResponse.data.data.pages.length >= pid) {
+ cid = cidResponse.data.data.pages[pid - 1].cid;
+ }
+ if (!cid) {
+ ctx.cache.set(key, cid, 24 * 60 * 60);
+ }
+ }
+ return cid;
+ },
};
diff --git a/lib/routes/bilibili/danmaku.js b/lib/routes/bilibili/danmaku.js
new file mode 100644
index 0000000000..8d1f1fba42
--- /dev/null
+++ b/lib/routes/bilibili/danmaku.js
@@ -0,0 +1,35 @@
+const cheerio = require('cheerio');
+const cache = require('./cache');
+const fetch = require('node-fetch');
+
+module.exports = async (ctx) => {
+ const aid = ctx.params.aid;
+ const pid = Number(ctx.params.pid || 1);
+ const limit = 50;
+ const cid = await cache.getCidFromAid(ctx, aid, pid);
+
+ const videoName = await cache.getVideoNameFromAid(ctx, aid);
+
+ const danmakuResponse = await fetch(`https://comment.bilibili.com/${cid}.xml`);
+ const danmakuText = await danmakuResponse.text();
+ let danmakuList = [];
+ const $ = cheerio.load(danmakuText, { xmlMode: true });
+ $('d').each((index, item) => {
+ danmakuList.push({ p: $(item).attr('p'), text: $(item).text() });
+ });
+
+ danmakuList = danmakuList.reverse().slice(0, limit);
+
+ ctx.state.data = {
+ title: `${videoName} 的 弹幕动态`,
+ link: `https://www.bilibili.com/video/av${aid}`,
+ description: `${videoName} 的 弹幕动态`,
+ item: danmakuList.map((item) => ({
+ title: item.text,
+ description: item.text,
+ pubDate: new Date(item.p.split(',')[4] * 1000).toUTCString(),
+ guid: `${cid}-${item.p.split(',')[4]}-${item.p.split(',')[7]}`,
+ link: `https://www.bilibili.com/video/av${aid}`,
+ })),
+ };
+};
diff --git a/package.json b/package.json
index 3f5c454de8..17a710f146 100644
--- a/package.json
+++ b/package.json
@@ -67,6 +67,7 @@
"lru-cache": "5.1.1",
"luxon": "^1.7.1",
"markdown-it": "^8.4.2",
+ "node-fetch": "^2.3.0",
"path-to-regexp": "3.0.0",
"pidusage": "^2.0.17",
"plist": "^3.0.1",