feat(route): add cls hot articles 添加财联社热门文章排行榜 (#12044)

* feat/add cls hot articles

* rename router to one word

* Apply suggestions from code review

* import crypto

* add heading 3

* refactor: migrate to v2

---------
This commit is contained in:
Hengyu
2023-03-07 04:05:48 +08:00
committed by GitHub
parent ca9efda5d4
commit dae0b254eb
12 changed files with 232 additions and 76 deletions
+12 -8
View File
@@ -224,24 +224,28 @@ TokenInsight 官方亦有提供 RSS,可参考 <https://api.tokeninsight.com/re
### 电报
<Route author="nczitzk" example="/cls/telegraph" path="/cls/telegraph/:category?" :paramsDesc="['分类,见下表']">
<Route author="nczitzk" example="/cls/telegraph" path="/cls/telegraph/:category?" :paramsDesc="['分类,见下表,默认为全部']" radar="1">
| 看盘 | 公告 | 解读 | 加红 | 推送 | 提醒 | 基金 |
| ----- | ------------ | ------- | --- | ----- | ------ | ---- |
| watch | announcement | explain | red | jpush | remind | fund |
| 看盘 | 公司 | 解读 | 加红 | 推送 | 提醒 | 基金 | 港股 |
| ----- | ------------ | ------- | --- | ----- | ------ | ---- | -- |
| watch | announcement | explain | red | jpush | remind | fund | hk |
</Route>
### 深度
<Route author="nczitzk" example="/cls/depth/1000" path="/cls/depth/:category?" :paramsDesc="['分类代码,可在首页导航栏的目标网址 URL 中找到']">
<Route author="nczitzk" example="/cls/depth/1000" path="/cls/depth/:category?" :paramsDesc="['分类代码,可在首页导航栏的目标网址 URL 中找到']" radar="1">
| 要闻 | 股市 | 环球 | 公司 | 地产 | 券商 | 金融 | 汽车 | 科创版 |
| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| 1000 | 1003 | 1007 | 1005 | 1006 | 1118 | 1032 | 1119 | 1111 |
| 头条 | 股市 | 港股 | 环球 | 公司 | 券商 | 基金 | 地产 | 金融 | 汽车 | 科创版 | 品见 | 期货 | 投教 |
| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| 1000 | 1003 | 1135 | 1007 | 1005 | 1118 | 1110 | 1006 | 1032 | 1119 | 1111 | 1160 | 1124 | 1176 |
</Route>
### 热门文章排行榜
<Route author="5upernova-heng" example="/cls/hot" path="/cls/hot" radar="1"/>
## 第一财经杂志
### 首页
+2 -2
View File
@@ -2862,8 +2862,8 @@ router.get('/gov/caict/caictgd', lazyloadRouteHandler('./routes/gov/caict/caictg
router.get('/cs/news/:caty', lazyloadRouteHandler('./routes/cs/news'));
// 财联社
router.get('/cls/depth/:category?', lazyloadRouteHandler('./routes/cls/depth'));
router.get('/cls/telegraph/:category?', lazyloadRouteHandler('./routes/cls/telegraph'));
// router.get('/cls/depth/:category?', lazyloadRouteHandler('./routes/cls/depth'));
// router.get('/cls/telegraph/:category?', lazyloadRouteHandler('./routes/cls/telegraph'));
// hentai-cosplays
router.get('/hentai-cosplays/:type?/:name?', lazyloadRouteHandler('./routes/hentai-cosplays/hentai-cosplays'));
-63
View File
@@ -1,63 +0,0 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const config = {
1000: '要闻',
1003: '股市',
1007: '环球',
1005: '公司',
1006: '地产',
1118: '券商',
1032: '金融',
1119: '汽车',
1111: '科创版',
};
module.exports = async (ctx) => {
ctx.params.category = ctx.params.category || '1000';
const title = config[ctx.params.category];
if (!title) {
throw Error('Bad category. See <a href="https://docs.rsshub.app/finance.html#cai-lian-she-shen-du">docs</a>');
}
const link = `https://www.cls.cn/v3/depth/home/assembled/${ctx.params.category}?app=CailianpressWeb&os=web&sv=7.2.2&sign=6ac194f4b3b39d45631708474e058b73`;
const response = await got({
method: 'get',
url: link,
});
let list = response.data.data.depth_list.map((item) => ({
title: item.title || item.brief,
link: `https://www.cls.cn/detail/${item.id}`,
pubDate: new Date(item.ctime * 1000).toUTCString(),
}));
list = list.concat(
response.data.data.top_article.map((item) => ({
title: item.title || item.brief,
link: `https://www.cls.cn/detail/${item.id}`,
pubDate: new Date(item.ctime * 1000).toUTCString(),
}))
);
const items = await Promise.all(
list.map((item) =>
ctx.cache.tryGet(item.link, async () => {
const detailResponse = await got({
method: 'get',
url: item.link,
});
const content = cheerio.load(detailResponse.data);
item.description = content('div.detail-content').html();
return item;
})
)
);
ctx.state.data = {
title: `财联社 - ${title}`,
link: 'https://www.cls.cn/telegraph',
item: items,
};
};
+82
View File
@@ -0,0 +1,82 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { app, os, sv, getSignedSearchParams } = require('./utils');
const { art } = require('@/utils/render');
const path = require('path');
const config = {
1000: '头条',
1003: '股市',
1135: '港股',
1007: '环球',
1005: '公司',
1118: '券商',
1110: '基金',
1006: '地产',
1032: '金融',
1119: '汽车',
1111: '科创版',
1160: '品见',
1124: '期货',
1176: '投教',
};
module.exports = async (ctx) => {
const category = ctx.params.category || '1000';
const title = config[category];
if (!title) {
throw Error('Bad category. See <a href="https://docs.rsshub.app/finance.html#cai-lian-she-shen-du">docs</a>');
}
const searchParams = getSignedSearchParams({
app,
os,
sv,
});
const baseUrl = 'https://www.cls.cn';
const link = `${baseUrl}/v3/depth/home/assembled/${category}`;
const response = await got({
method: 'get',
url: link,
searchParams,
});
let list =
response.data.data.depth_list?.map((item) => ({
title: item.title || item.brief,
link: `${baseUrl}/detail/${item.id}`,
pubDate: new Date(item.ctime * 1000).toUTCString(),
})) || [];
list = list.concat(
response.data.data.top_article.map((item) => ({
title: item.title || item.brief,
link: `${baseUrl}/detail/${item.id}`,
pubDate: new Date(item.ctime * 1000).toUTCString(),
}))
);
const items = await Promise.all(
list.map((item) =>
ctx.cache.tryGet(item.link, async () => {
const detailResponse = await got({
method: 'get',
url: item.link,
});
const content = cheerio.load(detailResponse.data);
const nextData = JSON.parse(content('script#__NEXT_DATA__').text());
const articleDetail = nextData.props.initialState.detail.articleDetail;
item.description = art(path.join(__dirname, 'templates/depth.art'), { articleDetail });
item.author = articleDetail.author?.name;
return item;
})
)
);
ctx.state.data = {
title: `财联社 - ${title}`,
link: `${baseUrl}/depth?id=${category}`,
item: items,
};
};
+45
View File
@@ -0,0 +1,45 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { app, os, sv, getSignedSearchParams } = require('./utils');
async function getDescription(link, ctx) {
const description = await ctx.cache.tryGet(link, async () => {
const detailResponse = await got({
method: 'get',
url: link,
});
const content = cheerio.load(detailResponse.data);
return content('div.detail-content').html();
});
return description;
}
module.exports = async (ctx) => {
const searchParams = getSignedSearchParams({
app,
os,
sv,
});
const link = 'https://www.cls.cn/v2/article/hot/list';
const response = await got({
method: 'get',
url: link,
searchParams,
});
const items = await Promise.all(
response.data.data.map(async (item) => ({
title: item.title || item.brief,
link: `https://www.cls.cn/detail/${item.id}`,
pubDate: new Date(item.ctime * 1000).toUTCString(),
description: await getDescription(`https://www.cls.cn/detail/${item.id}`, ctx),
}))
);
ctx.state.data = {
title: '财联社 - 热门文章排行榜',
link: 'https://www.cls.cn/',
item: items,
};
};
+5
View File
@@ -0,0 +1,5 @@
module.exports = {
'/depth/:category?': ['nczitzk'],
'/hot': ['5upernova-heng'],
'/telegraph/:category?': ['nczitzk'],
};
+25
View File
@@ -0,0 +1,25 @@
module.exports = {
'cls.cn': {
_name: '财联社',
'.': [
{
title: '电报',
docs: 'https://docs.rsshub.app/finance.html#cai-lian-she',
sources: ['/telegraph', '/'],
target: '/cls/telegraph',
},
{
title: '深度',
docs: 'https://docs.rsshub.app/finance.html#cai-lian-she',
sources: ['/depth'],
target: (_, url) => `/cls/depth/${new URL(url).searchParams.get('id')}`,
},
{
title: '热门文章排行榜',
docs: 'https://docs.rsshub.app/finance.html#cai-lian-she',
sources: ['/'],
target: '/cls/hot',
},
],
},
};
+5
View File
@@ -0,0 +1,5 @@
module.exports = (router) => {
router.get('/depth/:category?', require('./depth'));
router.get('/hot', require('./hot'));
router.get('/telegraph/:category?', require('./telegraph'));
};
@@ -1,29 +1,47 @@
const got = require('@/utils/got');
const { app, os, sv, getSignedSearchParams } = require('./utils');
const { art } = require('@/utils/render');
const path = require('path');
const titles = {
watch: '看盘',
announcement: '公告',
announcement: '公司',
explain: '解读',
red: '加红',
jpush: '推送',
remind: '提醒',
fund: '基金',
hk: '港股',
};
module.exports = async (ctx) => {
const category = ctx.params.category || '';
const limit = ctx.query.limit ? parseInt(ctx.query.limit) : 30;
const link = `https://www.cls.cn/nodeapi/updateTelegraphList?app=CailianpressWeb&category=${category}&hasFirstVipArticle=1&rn=30`;
const searchParams = getSignedSearchParams({
app,
category,
hasFirstVipArticle: 1,
os,
rn: limit,
sv,
});
let link = 'https://www.cls.cn/nodeapi/updateTelegraphList';
if (category) {
link = 'https://www.cls.cn/v1/roll/get_roll_list';
}
const response = await got({
method: 'get',
url: link,
searchParams,
});
const list = response.data.data.roll_data.map((item) => ({
title: item.title || item.content,
link: item.shareurl,
description: item.content,
description: art(path.join(__dirname, 'templates/telegraph.art'), { item }),
pubDate: new Date(item.ctime * 1000).toUTCString(),
category: item.subjects?.map((s) => s.subject_name),
}));
ctx.state.data = {
+10
View File
@@ -0,0 +1,10 @@
{{ if articleDetail.images }}
{{ each articleDetail.images i }}
<img src="{{ i }}">
{{ /each }}
<br>
{{ /if }}
{{ if articleDetail.content }}
{{@ articleDetail.content }}
{{ /if }}
+10
View File
@@ -0,0 +1,10 @@
{{ if item.content }}
{{ item.content }}
{{ /if }}
{{ if item.images }}
<br>
{{ each item.images i }}
<img src="{{ i }}">
{{ /each }}
{{ /if }}
+15
View File
@@ -0,0 +1,15 @@
const CryptoJS = require('crypto-js');
const getSignedSearchParams = (searchParams) => {
searchParams = new URLSearchParams(searchParams);
searchParams.sort();
searchParams.append('sign', CryptoJS.MD5(CryptoJS.SHA1(searchParams.toString()).toString()).toString());
return searchParams;
};
module.exports = {
appName: 'CailianpressWeb',
os: 'web',
sv: '7.7.5',
getSignedSearchParams,
};