diff --git a/docs/new-media.md b/docs/new-media.md
index 36d11458a..11af7ae7d 100644
--- a/docs/new-media.md
+++ b/docs/new-media.md
@@ -166,11 +166,37 @@ pageClass: routes
### 最新
-
+
+
+::: tip 提示
+
+最新的内容来源于 [官方 RSS](https://www.cnbeta.com/backend.php)
+
+:::
+
+
+
+### 分类
+
+
+
+| 影视 | 音乐 | 游戏 | 动漫 | 趣闻 | 科学 | 软件 |
+| ----- | ----- | ---- | ----- | ----- | ------- | ---- |
+| movie | music | game | comic | funny | science | soft |
+
+
### 主题
-
+
+
+::: tip 提示
+
+完整的主题列表参见 [主题列表](https://www.cnbeta.com/topics.htm)
+
+:::
+
+
## Common App
diff --git a/lib/router.js b/lib/router.js
index ed658e7b1..624bdd175 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -1824,8 +1824,8 @@ router.get('/maoyan/upcoming', lazyloadRouteHandler('./routes/maoyan/upcoming'))
router.get('/maoyan/hotComplete/:orderby?/:ascOrDesc?/:top?', lazyloadRouteHandler('./routes/maoyan/hotComplete'));
// cnBeta
-router.get('/cnbeta', lazyloadRouteHandler('./routes/cnbeta/home'));
-router.get('/cnbeta/topic/:topic_id', lazyloadRouteHandler('./routes/cnbeta/topic'));
+// router.get('/cnbeta', lazyloadRouteHandler('./routes/cnbeta/home'));
+// router.get('/cnbeta/topic/:topic_id', lazyloadRouteHandler('./routes/cnbeta/topic'));
// 国家退伍士兵信息
router.get('/gov/veterans/:type', lazyloadRouteHandler('./routes/gov/veterans/china'));
diff --git a/lib/routes/cnbeta/home.js b/lib/routes/cnbeta/home.js
deleted file mode 100644
index 2fbabc280..000000000
--- a/lib/routes/cnbeta/home.js
+++ /dev/null
@@ -1,53 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const parser = require('@/utils/rss-parser');
-
-module.exports = async (ctx) => {
- const feed = await parser.parseURL('https://rss.cnbeta.com/');
-
- const ProcessFeed = (data) => {
- const $ = cheerio.load(data);
-
- // 移除6.18广告
- $('.article-global').remove();
- $('.article-topic').remove();
-
- // 提取内容
- return $('.article-summary p').html() + '
' + $('.article-content').html();
- };
-
- const items = await Promise.all(
- feed.items
- .filter((item) => item.author !== 'adam')
- .map(async (item) => {
- const cache = await ctx.cache.get(item.link);
- if (cache) {
- return Promise.resolve(JSON.parse(cache));
- }
-
- const response = await got({
- method: 'get',
- url: item.link,
- });
-
- const description = ProcessFeed(response.data);
-
- const single = {
- title: item.title,
- description,
- pubDate: item.pubDate,
- link: item.link,
- author: item.author,
- };
- ctx.cache.set(item.link, JSON.stringify(single));
- return Promise.resolve(single);
- })
- );
-
- ctx.state.data = {
- title: 'cnBeta',
- link: 'https://www.cnbeta.com/',
- description: feed.description,
- item: items,
- };
-};
diff --git a/lib/routes/cnbeta/topic.js b/lib/routes/cnbeta/topic.js
deleted file mode 100644
index 9481b4ad8..000000000
--- a/lib/routes/cnbeta/topic.js
+++ /dev/null
@@ -1,75 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const date = require('@/utils/date');
-module.exports = async (ctx) => {
- const topicUrl = `https://www.cnbeta.com/topics/${ctx.params.topic_id}.htm`;
- const response = await got({
- method: 'get',
- url: topicUrl,
- });
- const $ = cheerio.load(response.data);
-
- const topicInfo = $('div.cate-brief h2 b').text();
- const news_list = $('div.item')
- .map((i, item) => {
- const title = $(item).find('dl dt a').text();
- let href = $(item).find('dl dt a').attr('href');
- if (href === undefined) {
- return null;
- }
- if (href.startsWith('//')) {
- href = 'https:' + href;
- }
- const status = $(item).find('div.meta-data ul.status li')['0'].children[0].data;
- const info = status.split(' ');
- const author = info[0];
- const pubDate = info[1] + ' ' + info[2];
- return { title, href, author, pubDate };
- })
- .filter((x) => x)
- .map((i, e) => e)
- .get();
-
- const ProcessFeed = (data) => {
- const $ = cheerio.load(data);
-
- // 移除6.18广告
- $('.article-global').remove();
- $('.article-topic').remove();
-
- // 提取内容
- return $('.article-summary p').html() + '
' + $('.article-content').html();
- };
-
- const out = await Promise.all(
- news_list.map(async (item) => {
- const cache = await ctx.cache.get(item.href);
- if (cache) {
- return Promise.resolve(JSON.parse(cache));
- }
-
- const response = await got({
- method: 'get',
- url: item.href,
- });
-
- const description = ProcessFeed(response.data);
- const single = {
- title: item.title,
- description,
- pubDate: date(item.pubDate, +8),
- link: item.href,
- author: item.author,
- };
- ctx.cache.set(item.href, JSON.stringify(single));
- return Promise.resolve(single);
- })
- );
-
- ctx.state.data = {
- title: `cnBeta专题 - ${topicInfo}`,
- link: topicUrl,
- item: out ?? [],
- description: `cnBeta专题 - ${topicInfo}`,
- };
-};
diff --git a/lib/v2/cnbeta/index.js b/lib/v2/cnbeta/index.js
new file mode 100644
index 000000000..68acdd594
--- /dev/null
+++ b/lib/v2/cnbeta/index.js
@@ -0,0 +1,15 @@
+const parser = require('@/utils/rss-parser');
+
+const { rootUrl, ProcessItems } = require('./utils');
+
+module.exports = async (ctx) => {
+ const currentUrl = `${rootUrl}/backend.php`;
+
+ const { items } = await parser.parseURL(currentUrl);
+
+ ctx.state.data = {
+ title: 'cnBeta',
+ link: currentUrl,
+ item: await ProcessItems(items, ctx.query.limit, ctx.cache.tryGet),
+ };
+};
diff --git a/lib/v2/cnbeta/maintainer.js b/lib/v2/cnbeta/maintainer.js
new file mode 100644
index 000000000..33741b6cd
--- /dev/null
+++ b/lib/v2/cnbeta/maintainer.js
@@ -0,0 +1,5 @@
+module.exports = {
+ '/': ['nczitzk'],
+ '/category/:id': ['nczitzk'],
+ '/topics/:id': ['nczitzk'],
+};
diff --git a/lib/v2/cnbeta/radar.js b/lib/v2/cnbeta/radar.js
new file mode 100644
index 000000000..458e2cde1
--- /dev/null
+++ b/lib/v2/cnbeta/radar.js
@@ -0,0 +1,25 @@
+module.exports = {
+ 'cnbeta.com': {
+ _name: 'cnBeta',
+ '.': [
+ {
+ title: '最新',
+ docs: 'https://docs.rsshub.app/new-media.html#cnbeta-zuixin',
+ source: ['/'],
+ target: '/cnbeta',
+ },
+ {
+ title: '分类',
+ docs: 'https://docs.rsshub.app/new-media.html#cnbeta-fenlei',
+ source: ['/category/:id', '/'],
+ target: '/cnbeta/category/:id',
+ },
+ {
+ title: '主题',
+ docs: 'https://docs.rsshub.app/new-media.html#cnbeta-zhuti',
+ source: ['/topics/:id', '/'],
+ target: '/cnbeta/topics/:id',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/cnbeta/router.js b/lib/v2/cnbeta/router.js
new file mode 100644
index 000000000..95cb0b6f9
--- /dev/null
+++ b/lib/v2/cnbeta/router.js
@@ -0,0 +1,4 @@
+module.exports = function (router) {
+ router.get('/:type/:id', require('./type'));
+ router.get('/', require('./index'));
+};
diff --git a/lib/v2/cnbeta/type.js b/lib/v2/cnbeta/type.js
new file mode 100644
index 000000000..5eaa636a1
--- /dev/null
+++ b/lib/v2/cnbeta/type.js
@@ -0,0 +1,42 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const timezone = require('@/utils/timezone');
+const { parseDate } = require('@/utils/parse-date');
+
+const { rootUrl, ProcessItems } = require('./utils');
+
+module.exports = async (ctx) => {
+ const type = ctx.params.type;
+ const id = ctx.params.id;
+
+ const currentUrl = `${rootUrl}/${type}/${id}.htm`;
+
+ let response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+
+ const $ = cheerio.load(response.data);
+
+ const token = encodeURI($('meta[name="csrf-token"]').attr('content'));
+ const apiUrl = `${rootUrl}/home/more?&type=${$('div[data-type]').attr('data-type')}&page=1&_csrf=${token}&_=${new Date().getTime()}`;
+
+ response = await got({
+ method: 'get',
+ url: apiUrl,
+ });
+
+ const items = response.data.result.list.map((item) => ({
+ title: item.title,
+ description: item.hometext,
+ author: item.source.split('@http')[0],
+ pubDate: timezone(parseDate(item.inputtime), +8),
+ link: item.url_show.indexOf('//') === 0 ? `https:${item.url_show}` : item.url_show,
+ }));
+
+ ctx.state.data = {
+ title: $('title').text(),
+ link: currentUrl,
+ item: await ProcessItems(items, ctx.query.limit, ctx.cache.tryGet),
+ };
+};
diff --git a/lib/v2/cnbeta/utils.js b/lib/v2/cnbeta/utils.js
new file mode 100644
index 000000000..0c3d68d53
--- /dev/null
+++ b/lib/v2/cnbeta/utils.js
@@ -0,0 +1,27 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+const rootUrl = 'https://www.cnbeta.com';
+
+module.exports = {
+ rootUrl,
+ ProcessItems: async (items, limit, tryGet) =>
+ await Promise.all(
+ items.slice(0, limit ? parseInt(limit) : 50).map((item) =>
+ tryGet(item.link, async () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+
+ const content = cheerio.load(detailResponse.data);
+
+ content('.topic, .article-topic, .article-global').remove();
+
+ item.description = content('.article-summary').html() + content('.article-content').html();
+
+ return item;
+ })
+ )
+ ),
+};