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')); +};