diff --git a/assets/radar-rules.js b/assets/radar-rules.js
index d4308b3c2b..7aa1c1d4b4 100644
--- a/assets/radar-rules.js
+++ b/assets/radar-rules.js
@@ -485,8 +485,8 @@
},
],
},
- 'biquge5200.com': { www: [{ title: 'biquge5200.com', docs: 'https://docs.rsshub.app/reading.html#bi-qu-ge-biquge5200-com', source: '/:id', target: '/novel/biquge/:id' }] },
- 'biquge.info': { www: [{ title: 'biquge.info', docs: 'https://docs.rsshub.app/reading.html#bi-qu-ge-biquge-info', source: '/:id', target: '/novel/biqugeinfo/:id' }] },
+ // 'biquge5200.com': { www: [{ title: 'biquge5200.com', docs: 'https://docs.rsshub.app/reading.html#bi-qu-ge-biquge5200-com', source: '/:id', target: '/novel/biquge/:id' }] },
+ // 'biquge.info': { www: [{ title: 'biquge.info', docs: 'https://docs.rsshub.app/reading.html#bi-qu-ge-biquge-info', source: '/:id', target: '/novel/biqugeinfo/:id' }] },
'matters.news': {
_name: 'Matters',
'.': [
diff --git a/docs/reading.md b/docs/reading.md
index 71e73799ca..e83ce5529f 100644
--- a/docs/reading.md
+++ b/docs/reading.md
@@ -158,26 +158,60 @@ pageClass: routes
## 笔趣阁
-### biquge5200.com
+::: tip 看我
-
-
-::: tip 提示
-
-由于笔趣阁网站有多个,各站点小说对应的小说 id 不同。此 feed 只对应在[`www.biquge5200.com`](https://www.biquge5200.com/)中的小说 id.
+此处的 **笔趣阁** 指网络上使用和 **笔趣阁** 样式相似模板的小说阅读网站,包括但不限于下方列举的网址。
:::
-### biquge.info
+| 网址 |
+| ------------------------- |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
-
+### 小说
-::: tip 提示
+
-由于笔趣阁网站有多个,各站点小说对应的小说 id 不同。此 feed 只对应在[`www.biquge.info`](http://www.biquge.info/)中的小说 id.
+::: tip 看我
+
+#### 使用方法
+
+如订阅 [《大主宰》](http://www.biqu5200.net/0\_7/),此时在 [biqu5200.net](http://www.biqu5200.net) 中查询得到对应小说详情页 URL 为 。此时,路由为 [`/biquge/http://www.biqu5200.net/0_7/`](https://rsshub.app/biquge/http://www.biqu5200.net/0\_7/)
+
+又如同样订阅 [《大主宰》](https://www.shuquge.com/txt/70/index.html),此时在 [shuquge.com](https://www.shuquge.com) 中查询得到对应小说详情页 URL 为 。此时,把末尾的 `index.html` 去掉,路由为 [`/biquge/https://www.shuquge.com/txt/70/`](https://rsshub.app/biquge/https://www.shuquge.com/txt/70/)
+
+#### 关于章节数
+
+路由默认返回最新 **1** 个章节,如有需要一次性获取多个章节,可在路由后指定 `limit` 参数。如上面的例子:订阅 [《大主宰》](http://www.biqu5200.net/0\_7/) 并获取最新的 **10** 个章节。此时,路由为 [`/biquge/http://www.biqu5200.net/0_7/?limit=10`](https://rsshub.app/biquge/http://www.biqu5200.net/0\_7/?limit=10)
+
+需要注意的是,单次获取的所有章节更新时间统一设定为最新章节的更新时间。也就是说,获取最新的 **10** 个章节时,除了最新 **1** 个章节的更新时间是准确的(和网站一致的),其他 **9** 个章节的更新时间是不准确的。
+
+另外,若设置获取章节数目过多,可能会触发网站反爬,导致路由不可用。
:::
+::: warning 提示
+
+上方列举的网址可能部分不可用,这取决于该网站的维护者是否持续运营网站。请选择可以正常访问的网址,获取更新的前提是该网站可以正常访问。
+
+:::
+
+
+
## 博客来
### 新书出版
diff --git a/lib/radar-rules.js b/lib/radar-rules.js
index 8d4fe0df05..11d034e6bf 100644
--- a/lib/radar-rules.js
+++ b/lib/radar-rules.js
@@ -1164,26 +1164,26 @@ module.exports = {
},
],
},
- 'biquge5200.com': {
- www: [
- {
- title: 'biquge5200.com',
- docs: 'https://docs.rsshub.app/reading.html#bi-qu-ge-biquge5200-com',
- source: '/:id',
- target: '/novel/biquge/:id',
- },
- ],
- },
- 'biquge.info': {
- www: [
- {
- title: 'biquge.info',
- docs: 'https://docs.rsshub.app/reading.html#bi-qu-ge-biquge-info',
- source: '/:id',
- target: '/novel/biqugeinfo/:id',
- },
- ],
- },
+ // 'biquge5200.com': {
+ // www: [
+ // {
+ // title: 'biquge5200.com',
+ // docs: 'https://docs.rsshub.app/reading.html#bi-qu-ge-biquge5200-com',
+ // source: '/:id',
+ // target: '/novel/biquge/:id',
+ // },
+ // ],
+ // },
+ // 'biquge.info': {
+ // www: [
+ // {
+ // title: 'biquge.info',
+ // docs: 'https://docs.rsshub.app/reading.html#bi-qu-ge-biquge-info',
+ // source: '/:id',
+ // target: '/novel/biqugeinfo/:id',
+ // },
+ // ],
+ // },
'matters.news': {
_name: 'Matters',
'.': [
diff --git a/lib/router.js b/lib/router.js
index 1105175009..96e9fe4c5c 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -460,8 +460,8 @@ router.get('/mafengwo/ziyouxing/:code', lazyloadRouteHandler('./routes/mafengwo/
// router.get('/earthquake/ceic/:type', lazyloadRouteHandler('./routes/earthquake/ceic'));
// 小说
-router.get('/novel/biquge/:id', lazyloadRouteHandler('./routes/novel/biquge'));
-router.get('/novel/biqugeinfo/:id/:limit?', lazyloadRouteHandler('./routes/novel/biqugeinfo'));
+// router.get('/novel/biquge/:id', lazyloadRouteHandler('./routes/novel/biquge'));
+// router.get('/novel/biqugeinfo/:id/:limit?', lazyloadRouteHandler('./routes/novel/biqugeinfo'));
router.get('/novel/uukanshu/:uid', lazyloadRouteHandler('./routes/novel/uukanshu'));
router.get('/novel/wenxuemi/:id1/:id2', lazyloadRouteHandler('./routes/novel/wenxuemi'));
router.get('/novel/booksky/:id', lazyloadRouteHandler('./routes/novel/booksky'));
diff --git a/lib/v2/biquge/index.js b/lib/v2/biquge/index.js
new file mode 100644
index 0000000000..8c210cc4c8
--- /dev/null
+++ b/lib/v2/biquge/index.js
@@ -0,0 +1,78 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const iconv = require('iconv-lite');
+const timezone = require('@/utils/timezone');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const rootUrl = ctx.path.split('/').slice(1, 4).join('/');
+ const currentUrl = ctx.path.slice(1);
+
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ responseType: 'buffer',
+ https: {
+ rejectUnauthorized: false,
+ },
+ });
+
+ const isGBK = /charset="?'?gb/i.test(response.data.toString());
+ const encoding = isGBK ? 'gbk' : 'utf-8';
+
+ const $ = cheerio.load(iconv.decode(response.data, encoding));
+ const author = $('meta[property="og:novel:author"]').attr('content');
+ const pubDate = timezone(parseDate($('meta[property="og:novel:update_time"]').attr('content')), +8);
+
+ let items = $('dl dd a')
+ .toArray()
+ .reverse()
+ .slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 1)
+ .map((item) => {
+ item = $(item);
+
+ let link = '';
+ const url = item.attr('href');
+ if (/^http/.test(url)) {
+ link = url;
+ } else if (/^\//.test(url)) {
+ link = `${rootUrl}${url}`;
+ } else {
+ link = `${currentUrl}/${url}`;
+ }
+
+ return {
+ title: item.text(),
+ link,
+ author,
+ pubDate,
+ };
+ });
+
+ items = await Promise.all(
+ items.map((item) =>
+ ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ responseType: 'buffer',
+ https: {
+ rejectUnauthorized: false,
+ },
+ });
+
+ const content = cheerio.load(iconv.decode(detailResponse.data, encoding));
+
+ item.description = content('#content').html();
+
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: `${$('meta[property="og:title"]').attr('content')} - 笔趣阁`,
+ link: currentUrl,
+ item: items,
+ };
+};
diff --git a/lib/v2/biquge/maintainer.js b/lib/v2/biquge/maintainer.js
new file mode 100644
index 0000000000..afe3c1a48d
--- /dev/null
+++ b/lib/v2/biquge/maintainer.js
@@ -0,0 +1,3 @@
+module.exports = {
+ '/:url': ['nczitzk'],
+};
diff --git a/lib/v2/biquge/radar.js b/lib/v2/biquge/radar.js
new file mode 100644
index 0000000000..a14868f5b3
--- /dev/null
+++ b/lib/v2/biquge/radar.js
@@ -0,0 +1,29 @@
+const biquge = {
+ _name: '笔趣阁',
+ '.': [
+ {
+ title: '',
+ docs: 'https://docs.rsshub.app/reading.html#bi-qu-ge-xiao-shuo',
+ source: ['/'],
+ target: (params, url) => `/biquge/${new URL(url).toString()}`,
+ },
+ ],
+};
+
+module.exports = {
+ 'xbiquwx.la': biquge,
+ 'biqu5200.net': biquge,
+ 'xbiquge.so': biquge,
+ 'biqugeu.net': biquge,
+ 'b520.cc': biquge,
+ 'biquge.biz': biquge,
+ 'xbiquge.la': biquge,
+ 'qbiqu.com': biquge,
+ 'bswtan.com': biquge,
+ 'biquge.co': biquge,
+ 'zhhbqg.com': biquge,
+ 'biqugse.com': biquge,
+ 'ibiquge.net': biquge,
+ 'shuquge.com': biquge,
+ 'mayiwxw.com': biquge,
+};
diff --git a/lib/v2/biquge/router.js b/lib/v2/biquge/router.js
new file mode 100644
index 0000000000..37c089127b
--- /dev/null
+++ b/lib/v2/biquge/router.js
@@ -0,0 +1,3 @@
+module.exports = function (router) {
+ router.get(/([\w/-]+)?/, require('./index'));
+};