feat(route): add 起点作者页面的作品 (#10643)

* feat(route): add 起点作者页面的作品

* fix(route): 起点作者缺少 v2 路由必要文件

* fix(route): typo

* fix(route): remove redundant code

* fix(route): author accepts pure string only

* refactor(route): cleanup code

* fix(route): remove old date parser

* refactor: migrate to v2
This commit is contained in:
miles 2022-08-30 01:20:52 +08:00 committed by GitHub
parent d5a952a55e
commit 9757d7e5be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 119 additions and 68 deletions

View File

@ -307,17 +307,6 @@
],
sites: [{ title: 'Sites', docs: 'https://docs.rsshub.app/blog.html#google-sites', source: ['/site/:id/*', '/site/:id'], target: '/google/sites/:id' }],
},
'qidian.com': {
_name: '起点',
book: [
{ title: '章节', docs: 'https://docs.rsshub.app/reading.html#qi-dian', source: '/info/:id', target: '/qidian/chapter/:id' },
{ title: '讨论区', docs: 'https://docs.rsshub.app/reading.html#qi-dian', source: '/info/:id', target: '/qidian/forum/:id' },
],
www: [
{ title: '限免', docs: 'https://docs.rsshub.app/reading.html#qi-dian', source: '/free', target: '/qidian/free' },
{ title: '女生限免', docs: 'https://docs.rsshub.app/reading.html#qi-dian', source: '/mm/free', target: '/qidian/free/mm' },
],
},
'hackerone.com': { _name: 'HackerOne', '.': [{ title: 'HackerOne Hacker Activity', docs: 'https://docs.rsshub.app/other.html#hackerone-hacker-activity', source: '/hacktivity', target: '/hackerone/hacktivity' }] },
'cowlevel.net': { _name: '奶牛关', '.': [{ title: '元素文章', docs: 'https://docs.rsshub.app/game.html#nai-niu-guan', source: ['/element/:id', '/element/:id/article'], target: '/cowlevel/element/:id' }] },
'beijing.gov.cn': { wjw: [{ title: '北京卫生健康委员会', docs: 'https://docs.rsshub.app/government.html#bei-jing-shi-wei-sheng-jian-kang-wei-yuan-hui', source: '/xwzx_20031/:caty', target: '/gov/beijing/mhc/:caty' }] },

View File

@ -399,6 +399,10 @@ count 的取值范围为 1-12为防止请求次数过多推荐设置为 5
<Route author="LogicJake" example="/qidian/free-next" path="/qidian/free-next/:type?" :paramsDesc="['默认不填为起点中文网,填 mm 为起点女生网']"/>
### 作者
<Route author="miles170" example="/qidian/author/9639927" path="/qidian/author/:id" :paramsDesc="['作者 id, 可在作者页面 URL 找到']"/>
## 起点图
### 首订

View File

@ -747,37 +747,6 @@ module.exports = {
},
],
},
'qidian.com': {
_name: '起点',
book: [
{
title: '章节',
docs: 'https://docs.rsshub.app/reading.html#qi-dian',
source: '/info/:id',
target: '/qidian/chapter/:id',
},
{
title: '讨论区',
docs: 'https://docs.rsshub.app/reading.html#qi-dian',
source: '/info/:id',
target: '/qidian/forum/:id',
},
],
www: [
{
title: '限免',
docs: 'https://docs.rsshub.app/reading.html#qi-dian',
source: '/free',
target: '/qidian/free',
},
{
title: '女生限免',
docs: 'https://docs.rsshub.app/reading.html#qi-dian',
source: '/mm/free',
target: '/qidian/free/mm',
},
],
},
'hackerone.com': {
_name: 'HackerOne',
'.': [

View File

@ -338,11 +338,11 @@ router.get('/mi/bbs/board/:boardId', lazyloadRouteHandler('./routes/mi/board'));
// Keep
// router.get('/keep/user/:id', lazyloadRouteHandler('./routes/keep/user'));
// 起点
router.get('/qidian/chapter/:id', lazyloadRouteHandler('./routes/qidian/chapter'));
router.get('/qidian/forum/:id', lazyloadRouteHandler('./routes/qidian/forum'));
router.get('/qidian/free/:type?', lazyloadRouteHandler('./routes/qidian/free'));
router.get('/qidian/free-next/:type?', lazyloadRouteHandler('./routes/qidian/free-next'));
// 起点 migrated to v2
// router.get('/qidian/chapter/:id', lazyloadRouteHandler('./routes/qidian/chapter'));
// router.get('/qidian/forum/:id', lazyloadRouteHandler('./routes/qidian/forum'));
// router.get('/qidian/free/:type?', lazyloadRouteHandler('./routes/qidian/free'));
// router.get('/qidian/free-next/:type?', lazyloadRouteHandler('./routes/qidian/free-next'));
// 纵横
router.get('/zongheng/chapter/:id', lazyloadRouteHandler('./routes/zongheng/chapter'));

41
lib/v2/qidian/author.js Normal file
View File

@ -0,0 +1,41 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate, parseRelativeDate } = require('@/utils/parse-date');
const { art } = require('@/utils/render');
const path = require('path');
const timezone = require('@/utils/timezone');
module.exports = async (ctx) => {
const id = ctx.params.id;
const rootUrl = 'https://my.qidian.com';
const currentUrl = `${rootUrl}/author/${id}/`;
const response = await got(currentUrl);
const $ = cheerio.load(response.data);
const authorName = $('.header-msg h1').contents().first().text().trim();
const items = $('.author-work .author-item')
.toArray()
.map((item) => {
item = $(item);
const messageItem = item.find('.author-item-msg');
const updatedDate = messageItem.find('.author-item-update span').text().replace('·', '').trim();
return {
title: messageItem.find('.author-item-title').text().trim(),
author: authorName,
category: messageItem.find('.author-item-exp a').first().text().trim(),
description: art(path.join(__dirname, 'templates/description.art'), {
description: messageItem.find('.author-item-update a').attr('title'),
image: item.find('a img').attr('src'),
}),
pubDate: timezone(/(今|昨)/.test(updatedDate) ? parseRelativeDate(updatedDate) : parseDate(updatedDate, 'YYYY-MM-DD HH:mm'), +8),
link: messageItem.find('.author-item-update a').attr('href'),
};
});
ctx.state.data = {
title: `${authorName} - 起点中文网`,
description: $('.header-msg-desc').text().trim(),
link: currentUrl,
item: items,
};
};

View File

@ -1,13 +1,11 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const id = ctx.params.id;
const response = await got({
method: 'get',
url: `https://book.qidian.com/info/${id}#Catalog`,
});
const response = await got(`https://book.qidian.com/info/${id}/#Catalog`);
const $ = cheerio.load(response.data);
const name = $('.book-info>h1>em').text();
@ -15,10 +13,7 @@ module.exports = async (ctx) => {
const csrfToken = response.headers['set-cookie'].find((s) => s.startsWith('_csrfToken=')).split(';')[0];
const chapters_response = await got({
method: 'get',
url: `https://book.qidian.com/ajax/book/category?${csrfToken}&bookId=${id}`,
});
const chapters_response = await got(`https://book.qidian.com/ajax/book/category?${csrfToken}&bookId=${id}`);
const chapter_item = [];
for (let i = 0; i < chapters_response.data.data.vs.length; i++) {
@ -27,7 +22,7 @@ module.exports = async (ctx) => {
const chapter = chapters[j];
chapter_item.push({
title: chapter.cN,
pubDate: new Date(chapter.uT).toUTCString(),
pubDate: parseDate(chapter.uT),
link: `https://vipreader.qidian.com/chapter/${id}/${chapter.id}`,
});
}

View File

@ -7,9 +7,7 @@ module.exports = async (ctx) => {
const url = `https://forum.qidian.com/NewForum/List.aspx?BookId=${id}`;
const forum_response = await got({
method: 'get',
url,
const forum_response = await got(url, {
headers: {
Referer: `https://book.qidian.com/info/${id}`,
},

View File

@ -13,10 +13,7 @@ module.exports = async (ctx) => {
title = '起点中文网';
}
const response = await got({
method: 'get',
url: link,
});
const response = await got(link);
const $ = cheerio.load(response.data);
const list = $('div.other-rec-wrap li');

View File

@ -1,5 +1,6 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const parseDate = require('@/utils/date');
module.exports = async (ctx) => {
const type = ctx.params.type;
@ -13,10 +14,7 @@ module.exports = async (ctx) => {
title = '起点中文网';
}
const response = await got({
method: 'get',
url: link,
});
const response = await got(link);
const $ = cheerio.load(response.data);
const list = $('#limit-list li');
@ -31,7 +29,7 @@ module.exports = async (ctx) => {
return {
title: item.find('.book-mid-info h4 a').text(),
description: img + rank + update + '<br>' + item.find('p.intro').html(),
pubDate: new Date(item.find('p.update span').text()).toUTCString(),
pubDate: parseDate(item.find('p.update span').text()),
link: 'https:' + item.find('.book-mid-info h4 a').attr('href'),
author: item.find('p.author a.name').text(),
};

View File

@ -0,0 +1,7 @@
module.exports = {
'/author/:id': ['miles170'],
'/chapter/:id': ['Chingyat'],
'/forum/:id': ['Chingyat'],
'/free/:type?': ['LogicJake'],
'/free-next/:type?': ['LogicJake'],
};

41
lib/v2/qidian/radar.js Normal file
View File

@ -0,0 +1,41 @@
module.exports = {
'qidian.com': {
_name: '起点',
book: [
{
title: '章节',
docs: 'https://docs.rsshub.app/reading.html#qi-dian',
source: '/info/:id',
target: '/qidian/chapter/:id',
},
{
title: '讨论区',
docs: 'https://docs.rsshub.app/reading.html#qi-dian',
source: '/info/:id',
target: '/qidian/forum/:id',
},
],
my: [
{
title: '作者',
docs: 'https://docs.rsshub.app/reading.html#qi-dian',
source: '/author/:id',
target: '/qidian/author/:id',
},
],
www: [
{
title: '限免',
docs: 'https://docs.rsshub.app/reading.html#qi-dian',
source: '/free',
target: '/qidian/free',
},
{
title: '女生限免',
docs: 'https://docs.rsshub.app/reading.html#qi-dian',
source: '/mm/free',
target: '/qidian/free/mm',
},
],
},
};

7
lib/v2/qidian/router.js Normal file
View File

@ -0,0 +1,7 @@
module.exports = (router) => {
router.get('/author/:id', require('./author'));
router.get('/chapter/:id', require('./chapter'));
router.get('/forum/:id', require('./forum'));
router.get('/free/:type?', require('./free'));
router.get('/free-next/:type?', require('./free-next'));
};

View File

@ -0,0 +1,5 @@
<p>{{ description }}</p>
{{ if image }}
<img src="{{ image }}">
{{ /if }}
{{ author }}