feat(route): add 南方网南方+ (#12169)

* feat(route): add 南方网南方+

* Update lib/v2/southcn/nfapp/reporter.js

* Update lib/v2/southcn/maintainer.js

* fix(route): fix southcn

* opt(route): optimize southcn

* docs: fix route tag

---------
This commit is contained in:
Tim Wu 2023-04-05 19:43:34 +08:00 committed by GitHub
parent adf146b8f1
commit e304b0ed49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 141 additions and 0 deletions

View File

@ -1629,6 +1629,30 @@ category 对应的关键词有
</Route>
## 南方网
### 南方 +(按栏目 ID
<Route author="TimWu007" example="/southcn/nfapp/column/38" path="/southcn/nfapp/column/:column?" :paramsDesc="['栏目或南方号 ID']">
::: tip 提示
若此处输入的是栏目 ID而非南方号 ID则该接口会返回与输入栏目相关联栏目的文章。例如输入栏目 ID `38`(广州),则返回的结果还会包含 ID 为 `3547`(市长报道集)的文章。
:::
1. `pc.nfapp.southcn.com` 下的文章页面,可通过 url 查看,例:<http://pc.nfapp.southcn.com/13707/7491109.html> 的栏目 ID 为 `13707`
2. `static.nfapp.southcn.com` 下的文章页面,可查看网页源代码,搜索 `columnid`
3. <https://m.nfapp.southcn.com/column/all> 列出了部分栏目,`id` 即为栏目 ID。
</Route>
### 南方 +(按作者)
<Route author="TimWu007" example="/southcn/nfapp/reporter/969927791" path="/southcn/nfapp/reporter/:reporter" :paramsDesc="['作者 UUID']">
作者的 UUID 只可通过 `static.nfapp.southcn.com` 下的文章页面获取。点击文章下方的作者介绍,进入该作者的个人主页,即可从 url 中获取。
</Route>
## 南方周末
### 新闻分类

View File

@ -0,0 +1,4 @@
module.exports = {
'/nfapp/column/:column?': ['TimWu007'],
'/nfapp/reporter/:reporter': ['TimWu007'],
};

View File

@ -0,0 +1,35 @@
const got = require('@/utils/got');
const timezone = require('@/utils/timezone');
const { parseDate } = require('@/utils/parse-date');
const { art } = require('@/utils/render');
const path = require('path');
const { parseArticle } = require('./utils');
module.exports = async (ctx) => {
const columnId = ctx.params.column ?? 38;
const currentUrl = `https://api.nfapp.southcn.com/nfplus-manuscript-web/article/list?columnId=${columnId}&nfhSubCount=1&pageNum=1&pageSize=20`; // this api only returns up to 10 articles
const { data: response } = await got(currentUrl);
const list = response.data.list
.filter((i) => i.articleType === 0)
.map((item) => ({
title: '【' + item.columnName + '】' + item.title,
description: art(path.join(__dirname, '../templates/description.art'), {
thumb: item.picMiddle,
description: item.summary === '详见内文' ? '' : item.summary,
}),
pubDate: timezone(parseDate(item.updateTime), +8),
link: `http://pc.nfapp.southcn.com/${item.columnId}/${item.articleId}.html`,
articleId: item.articleId,
shareUrl: item.shareUrl,
}));
const items = await Promise.all(list.map((item) => parseArticle(item, ctx.cache.tryGet)));
ctx.state.data = {
title: `南方+`,
link: `https://m.nfapp.southcn.com/${columnId}`,
item: items,
};
};

View File

@ -0,0 +1,33 @@
const got = require('@/utils/got');
const timezone = require('@/utils/timezone');
const { parseDate } = require('@/utils/parse-date');
const { art } = require('@/utils/render');
const { parseArticle } = require('./utils');
const path = require('path');
module.exports = async (ctx) => {
const reporterId = ctx.params.reporter;
const currentUrl = `https://api.nfapp.southcn.com/nanfang_if/reporter/list?reporterUuid=${reporterId}&pageSize=20&pageNo=1&origin=0`;
const { data: response } = await got(currentUrl);
const list = response.data.reportInfo.articleInfo.map((item) => ({
title: '【' + item.releaseColName + '】' + item.title,
description: art(path.join(__dirname, '../templates/description.art'), {
thumb: item.picMiddle,
description: item.attAbstract,
}),
pubDate: timezone(parseDate(item.publishtime), +8),
link: `http://pc.nfapp.southcn.com/${item.colID}/${item.fileId}.html`,
articleId: item.fileId,
shareUrl: item.shareUrl,
}));
const items = await Promise.all(list.map((item) => parseArticle(item, ctx.cache.tryGet)));
ctx.state.data = {
title: `南方+ - ${response.data.reportInfo.reporterName}`,
link: `https://static.nfapp.southcn.com/apptpl/reporterWorksList/index.html?reporterUuid=${reporterId}`,
item: items,
};
};

View File

@ -0,0 +1,23 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const parseArticle = (item, tryGet) =>
tryGet(item.link, async () => {
const detailResponse = await got({
method: 'get',
url: item.link,
});
const $ = cheerio.load(detailResponse.data);
$('.article-nfh-icon, .article-crumb, .article-share, .article-copyright').remove();
item.description += $('#content').html() ?? '';
item.author = $('meta[name="author"]').attr('content');
return item;
});
module.exports = {
parseArticle,
};

12
lib/v2/southcn/radar.js Normal file
View File

@ -0,0 +1,12 @@
module.exports = {
'nfapp.southcn.com': {
_name: '南方网',
'.': [
{
title: '南方+',
docs: 'https://docs.rsshub.app/traditional-media.html#nan-fang-wang',
source: ['/'],
},
],
},
};

4
lib/v2/southcn/router.js Normal file
View File

@ -0,0 +1,4 @@
module.exports = (router) => {
router.get('/nfapp/column/:column?', require('./nfapp/column'));
router.get('/nfapp/reporter/:reporter', require('./nfapp/reporter'));
};

View File

@ -0,0 +1,6 @@
{{ if thumb }}
<img src="{{ thumb }}">
{{ /if }}
{{ if description }}
<blockquote><p>{{ description }}</p></blockquote>
{{ /if }}