mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-09-24 23:12:34 +08:00
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:
+12
-8
@@ -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
@@ -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'));
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
'/depth/:category?': ['nczitzk'],
|
||||
'/hot': ['5upernova-heng'],
|
||||
'/telegraph/:category?': ['nczitzk'],
|
||||
};
|
||||
@@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -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 = {
|
||||
@@ -0,0 +1,10 @@
|
||||
{{ if articleDetail.images }}
|
||||
{{ each articleDetail.images i }}
|
||||
<img src="{{ i }}">
|
||||
{{ /each }}
|
||||
<br>
|
||||
{{ /if }}
|
||||
|
||||
{{ if articleDetail.content }}
|
||||
{{@ articleDetail.content }}
|
||||
{{ /if }}
|
||||
@@ -0,0 +1,10 @@
|
||||
{{ if item.content }}
|
||||
{{ item.content }}
|
||||
{{ /if }}
|
||||
|
||||
{{ if item.images }}
|
||||
<br>
|
||||
{{ each item.images i }}
|
||||
<img src="{{ i }}">
|
||||
{{ /each }}
|
||||
{{ /if }}
|
||||
@@ -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,
|
||||
};
|
||||
Reference in New Issue
Block a user