fix(route): 中国投资者网 (#20106)

This commit is contained in:
Ethan Shen 2025-09-20 08:46:13 +08:00 committed by GitHub
parent 380874aca8
commit eedb725e46
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 356 additions and 142 deletions

View File

@ -1,156 +1,278 @@
import { Route } from '@/types';
import { type Data, type DataItem, type Route, ViewType } from '@/types';
import cache from '@/utils/cache';
import got from '@/utils/got';
import { load } from 'cheerio';
import ofetch from '@/utils/ofetch';
import { parseDate } from '@/utils/parse-date';
// Collected from https://www.investor.org.cn/images/docSearchData.js.
import { type CheerioAPI, type Cheerio, load } from 'cheerio';
import type { Element } from 'domhandler';
import { type Context } from 'hono';
const channelIds = {
63: 298519,
958: 244863,
3966: 244863,
};
export const handler = async (ctx: Context): Promise<Data> => {
const { id = 'home/zxdt' } = ctx.req.param();
const limit: number = Number.parseInt(ctx.req.query('limit') ?? '20', 10);
export const handler = async (ctx) => {
const { category = 'information_release/news_release_from_authorities/zjhfb' } = ctx.req.param();
const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 15;
const baseUrl: string = 'https://www.investor.org.cn';
const targetUrl: string = new URL(id.endsWith('/') ? id : `${id}/`, baseUrl).href;
const rootUrl = 'https://www.investor.org.cn';
const apiUrl = new URL('was5/web/search', rootUrl).href;
const currentUrl = new URL(category.endsWith('/') ? category : `${category}/`, rootUrl).href;
const response = await ofetch(targetUrl);
const $: CheerioAPI = load(response);
const language = $('html').attr('lang') ?? 'zh';
const { data: response } = await got(currentUrl);
let items: DataItem[] = [];
const $ = load(response);
items = $('div.right_content_item a')
.slice(0, limit)
.toArray()
.map((el): Element => {
const $el: Cheerio<Element> = $(el);
const language = 'zh';
const title: string = $el.find('div.title').text();
const pubDateStr: string | undefined = $el.find('div.date').text();
const linkUrl: string | undefined = $el.attr('href');
const upDatedStr: string | undefined = pubDateStr;
let items = [];
const processedItem: DataItem = {
title,
pubDate: pubDateStr ? parseDate(pubDateStr) : undefined,
link: linkUrl ? new URL(linkUrl, baseUrl).href : undefined,
updated: upDatedStr ? parseDate(upDatedStr) : undefined,
language,
};
if ($('div.hotlist dd').length === 0) {
const channelId = response.match(/params.channelId='(\d+)';/)?.[1] ?? undefined;
const {
data: { rows },
} = await got.post(apiUrl, {
form: {
channelid: channelIds?.[channelId] ?? undefined,
searchword: `CHANNELID=${channelId}`,
page: 1,
perpage: limit,
},
return processedItem;
});
items = rows.map((item) => ({
title: item.DOCTITLE,
pubDate: parseDate(item.DOCPUBTIME),
link: item.DOCURL,
language,
}));
} else {
items = $('div.hotlist dd')
.slice(0, limit)
.toArray()
.map((item) => {
item = $(item);
items = await Promise.all(
items.map((item) => {
if (!item.link || item.link.endsWith('.pdf')) {
return item;
}
const href = item.find('a').prop('href');
return cache.tryGet(item.link, async (): Promise<DataItem> => {
const detailResponse = await ofetch(item.link);
const $$: CheerioAPI = load(detailResponse);
return {
title: item.find('a').prop('title'),
pubDate: parseDate(item.find('span.date').text()),
link: new URL(href, currentUrl).href,
const title: string = $$('div.text_content_detail_title h1').text() ?? item.title;
const description: string | undefined = $$('div.trs_editor_view').html() ?? undefined;
const pubDateStr: string | undefined = $$('div.base_info_left span')
.toArray()
.some((el) => $$(el).text().includes('时间'))
? $$(
$$('div.base_info_left span')
.toArray()
.find((el) => $$(el).text().includes('时间'))
)
.text()
.split(//)
.pop()
?.trim()
: undefined;
const upDatedStr: string | undefined = pubDateStr;
const processedItem: DataItem = {
title,
description,
pubDate: pubDateStr ? parseDate(pubDateStr) : item.pubDate,
content: {
html: description,
text: description,
},
updated: upDatedStr ? parseDate(upDatedStr) : item.updated,
language,
};
});
}
items = await Promise.all(
items.map((item) =>
cache.tryGet(item.link, async () => {
if (!item.link.endsWith('html')) {
return item;
}
const { data: detailResponse } = await got(item.link);
const $$ = load(detailResponse);
const title = $$('div.contentText h2').text();
const description = $$('div.TRS_Editor').html();
item.title = title || item.title;
item.description = description;
item.author = $$('span.timeSpan')
.text()
.trim()
.split(/来源:/)
.pop();
item.content = {
html: description,
text: $$('div.TRS_Editor').text(),
return {
...item,
...processedItem,
};
item.language = language;
return item;
})
)
});
})
);
const image = $('div.img_cursor a img').prop('src');
const title: string = $('title').text();
return {
title: $('title').text(),
description: $('meta[name="apple-mobile-web-app-title"]').prop('content'),
link: currentUrl,
title,
description: title.split(/\|/)?.[0],
link: targetUrl,
item: items,
allowEmpty: true,
image,
author: $('meta[name="author"]').prop('content'),
image: $('div.fl a img').attr('src') ? new URL($('div.fl a img').attr('src') as string, baseUrl).href : undefined,
author: title.split(/\|/).pop(),
language,
id: targetUrl,
};
};
export const route: Route = {
path: '/:category{.+}?',
name: '分类',
url: 'investor.org.cn',
path: '/:id{.+}?',
name: '栏目',
url: 'www.investor.org.cn',
maintainers: ['nczitzk'],
handler,
example: '/investor/information_release/news_release_from_authorities/zjhfb',
parameters: { category: '分类,默认为证监会发布 `information_release/news_release_from_authorities/zjhfb`,可在对应分类页 URL 中找到' },
description: `::: tip
[](https://www.investor.org.cn/information_release/news_release_from_authorities/zjhfb/),网址为 \`https://www.investor.org.cn/information_release/news_release_from_authorities/zjhfb/\`。截取 \`https://www.investor.org.cn/\` 到末尾 \`/\` 的部分 \`information_release/news_release_from_authorities/zjhfb\` 作为参数填入,此时路由为 [\`/investor/information_release/news_release_from_authorities/zjhfb\`](https://rsshub.app/investor/information_release/news_release_from_authorities/zjhfb)。
example: '/investor/home/zxdt',
parameters: {
id: {
description: '分类,默认为 `home/zxdt`,即最新动态,可在对应栏目页 URL 中找到',
options: [
{
label: '最新动态',
value: 'home/zxdt',
},
{
label: '政策资讯 - 政策资讯',
value: 'zczx',
},
{
label: '政策资讯 - 权威资讯',
value: 'zczx/qwzx',
},
{
label: '政策资讯 - 证监会发布',
value: 'zczx/qwzx/zjhfb',
},
{
label: '政策资讯 - 证券交易所发布',
value: 'zczx/qwzx/hsjysfb',
},
{
label: '政策资讯 - 期货交易所发布',
value: 'zczx/qwzx/qhjysfb_1',
},
{
label: '政策资讯 - 协会发布',
value: 'zczx/qwzx/hyxhfb',
},
{
label: '政策资讯 - 市场资讯',
value: 'zczx/market_news',
},
{
label: '政策资讯 - 政策解读',
value: 'zczx/policy_interpretation',
},
{
label: '政策资讯 - 法律法规',
value: 'zczx/flfg',
},
{
label: '政策资讯 - 法律',
value: 'zczx/flfg/fljsfjs',
},
{
label: '政策资讯 - 行政法规及司法解释',
value: 'zczx/flfg/xzfg',
},
{
label: '政策资讯 - 部门规章及规范性文件',
value: 'zczx/flfg/bmgz',
},
{
label: '政策资讯 - 投服中心业务规则',
value: 'zczx/flfg/tfzxzd',
},
{
label: '政策资讯 - 工作交流',
value: 'zczx/gzjl',
},
{
label: '投保动态 - 投保动态',
value: 'qybh',
},
{
label: '投保动态 - 持股行权',
value: 'qybh/cgxq',
},
{
label: '投保动态 - 行权动态',
value: 'qybh/cgxq/xqdt',
},
{
label: '投保动态 - 个案行权',
value: 'qybh/cgxq/gaxq',
},
{
label: '投保动态 - 典型案例',
value: 'qybh/cgxq/xqal',
},
{
label: '投保动态 - 维权诉讼',
value: 'qybh/wqfw',
},
{
label: '投保动态 - 投服中心维权',
value: 'qybh/wqfw/tfzxwq',
},
{
label: '投保动态 - 维权路径与机构',
value: 'qybh/wqfw/wqljyjg',
},
{
label: '投保动态 - 纠纷调解',
value: 'qybh/tjfw',
},
{
label: '投保动态 - 调解动态',
value: 'qybh/tjfw/tjdt',
},
{
label: '投保动态 - 调解组织',
value: 'qybh/tjfw/tjzz',
},
{
label: '投保动态 - 调解案例',
value: 'qybh/tjfw/tjal',
},
],
},
},
description: `:::tip
[](https://www.investor.org.cn/home/zxdt/),其源网址为 \`https://www.investor.org.cn/home/zxdt/\`,请参考该 URL 指定部分构成参数,此时路由为 [\`/investor/home/zxdt\`](https://rsshub.app/investor/home/zxdt)。
:::
#### [](https://www.investor.org.cn/information_release/news_release_from_authorities/)
<details>
<summary></summary>
| [](https://www.investor.org.cn/information_release/news_release_from_authorities/zjhfb/) | [证券交易所发布](https://www.investor.org.cn/information_release/news_release_from_authorities/hsjysfb/) | [期货交易所发布](https://www.investor.org.cn/information_release/news_release_from_authorities/qhjysfb/) | [行业协会发布](https://www.investor.org.cn/information_release/news_release_from_authorities/hyxhfb/) | [其他](https://www.investor.org.cn/information_release/news_release_from_authorities/otner/) |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [/investor/information_release/news_release_from_authorities/zjhfb/](https://rsshub.app/investor/investor/information_release/news_release_from_authorities/zjhfb/) | [/investor/information_release/news_release_from_authorities/hsjysfb/](https://rsshub.app/investor/investor/information_release/news_release_from_authorities/hsjysfb/) | [/investor/information_release/news_release_from_authorities/qhjysfb/](https://rsshub.app/investor/investor/information_release/news_release_from_authorities/qhjysfb/) | [/investor/information_release/news_release_from_authorities/hyxhfb/](https://rsshub.app/investor/investor/information_release/news_release_from_authorities/hyxhfb/) | [/investor/information_release/news_release_from_authorities/otner/](https://rsshub.app/investor/investor/information_release/news_release_from_authorities/otner/) |
#### [](https://www.investor.org.cn/zczx/)
#### [](https://www.investor.org.cn/information_release/market_news/)
| | ID |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| [](https://www.investor.org.cn/zczx/) | [zczx](https://rsshub.app/investor/zczx) |
| [](https://www.investor.org.cn/zczx/qwzx/) | [zczx/qwzx](https://rsshub.app/investor/zczx/qwzx) |
| [](https://www.investor.org.cn/zczx/qwzx/zjhfb/) | [zczx/qwzx/zjhfb](https://rsshub.app/investor/zczx/qwzx/zjhfb) |
| [](https://www.investor.org.cn/zczx/qwzx/hsjysfb/) | [zczx/qwzx/hsjysfb](https://rsshub.app/investor/zczx/qwzx/hsjysfb) |
| [](https://www.investor.org.cn/zczx/qwzx/qhjysfb_1/) | [zczx/qwzx/qhjysfb_1](https://rsshub.app/investor/zczx/qwzx/qhjysfb_1) |
| [](https://www.investor.org.cn/zczx/qwzx/hyxhfb/) | [zczx/qwzx/hyxhfb](https://rsshub.app/investor/zczx/qwzx/hyxhfb) |
| [](https://www.investor.org.cn/zczx/market_news/) | [zczx/market_news](https://rsshub.app/investor/zczx/market_news) |
| [](https://www.investor.org.cn/zczx/policy_interpretation/) | [zczx/policy_interpretation](https://rsshub.app/investor/zczx/policy_interpretation) |
| [](https://www.investor.org.cn/zczx/flfg/) | [zczx/flfg](https://rsshub.app/investor/zczx/flfg) |
| [](https://www.investor.org.cn/zczx/flfg/fljsfjs/) | [zczx/flfg/fljsfjs](https://rsshub.app/investor/zczx/flfg/fljsfjs) |
| [](https://www.investor.org.cn/zczx/flfg/xzfg/) | [zczx/flfg/xzfg](https://rsshub.app/investor/zczx/flfg/xzfg) |
| [](https://www.investor.org.cn/zczx/flfg/bmgz/) | [zczx/flfg/bmgz](https://rsshub.app/investor/zczx/flfg/bmgz) |
| [](https://www.investor.org.cn/zczx/flfg/tfzxzd/) | [zczx/flfg/tfzxzd](https://rsshub.app/investor/zczx/flfg/tfzxzd) |
| [](https://www.investor.org.cn/zczx/gzjl/) | [zczx/gzjl](https://rsshub.app/investor/zczx/gzjl) |
| [](https://www.investor.org.cn/information_release/market_news/) |
| ---------------------------------------------------------------------------------------------------------- |
| [/investor/information_release/market_news/](https://rsshub.app/investor/information_release/market_news/) |
#### [](https://www.investor.org.cn/qybh/)
#### [](https://www.investor.org.cn/information_release/policy_interpretation/)
| | ID |
| ---------------------------------------------------------------- | ------------------------------------------------------------------ |
| [](https://www.investor.org.cn/qybh/) | [qybh](https://rsshub.app/investor/qybh) |
| [](https://www.investor.org.cn/qybh/cgxq/) | [qybh/cgxq](https://rsshub.app/investor/qybh/cgxq) |
| [](https://www.investor.org.cn/qybh/cgxq/xqdt/) | [qybh/cgxq/xqdt](https://rsshub.app/investor/qybh/cgxq/xqdt) |
| [](https://www.investor.org.cn/qybh/cgxq/gaxq/) | [qybh/cgxq/gaxq](https://rsshub.app/investor/qybh/cgxq/gaxq) |
| [](https://www.investor.org.cn/qybh/cgxq/xqal/) | [qybh/cgxq/xqal](https://rsshub.app/investor/qybh/cgxq/xqal) |
| [](https://www.investor.org.cn/qybh/wqfw/) | [qybh/wqfw](https://rsshub.app/investor/qybh/wqfw) |
| [](https://www.investor.org.cn/qybh/wqfw/tfzxwq/) | [qybh/wqfw/tfzxwq](https://rsshub.app/investor/qybh/wqfw/tfzxwq) |
| [](https://www.investor.org.cn/qybh/wqfw/wqljyjg/) | [qybh/wqfw/wqljyjg](https://rsshub.app/investor/qybh/wqfw/wqljyjg) |
| [](https://www.investor.org.cn/qybh/tjfw/) | [qybh/tjfw](https://rsshub.app/investor/qybh/tjfw) |
| [](https://www.investor.org.cn/qybh/tjfw/tjdt/) | [qybh/tjfw/tjdt](https://rsshub.app/investor/qybh/tjfw/tjdt) |
| [](https://www.investor.org.cn/qybh/tjfw/tjzz/) | [qybh/tjfw/tjzz](https://rsshub.app/investor/qybh/tjfw/tjzz) |
| [](https://www.investor.org.cn/qybh/tjfw/tjal/) | [qybh/tjfw/tjal](https://rsshub.app/investor/qybh/tjfw/tjal) |
| [](https://www.investor.org.cn/information_release/policy_interpretation/) |
| ------------------------------------------------------------------------------------------------------------------- |
| [/investorinformation_release/policy_interpretation/](https://rsshub.appinformation_release/policy_interpretation/) |
#### [](https://www.investor.org.cn/information_release/international_communication/)
| [](https://www.investor.org.cn/information_release/international_communication/) |
| --------------------------------------------------------------------------------------------------------------------------------- |
| [/investor/information_release/international_communication/](https://rsshub.app/information_release/international_communication/) |
`,
</details>
`,
categories: ['finance'],
features: {
requireConfig: false,
requirePuppeteer: false,
@ -162,52 +284,144 @@ export const route: Route = {
},
radar: [
{
source: ['investor.org.cn/:category'],
target: (params) => {
const category = params.category;
return `/investor${category ? `/${category}` : ''}`;
},
source: ['www.investor.org.cn/:id'],
target: '/:id',
},
{
title: '权威发布 - 证监会发布',
source: ['www.investor.org.cn/information_release/news_release_from_authorities/zjhfb/'],
target: '/information_release/news_release_from_authorities/zjhfb/',
title: '最新动态',
source: ['https://www.investor.org.cn/home/zxdt/'],
target: '/home/zxdt',
},
{
title: '权威发布 - 证券交易所发布',
source: ['www.investor.org.cn/information_release/news_release_from_authorities/hsjysfb/'],
target: '/information_release/news_release_from_authorities/hsjysfb/',
title: '政策资讯 - 政策资讯',
source: ['www.investor.org.cn/zczx/'],
target: '/zczx',
},
{
title: '权威发布 - 期货交易所发布',
source: ['www.investor.org.cn/information_release/news_release_from_authorities/qhjysfb/'],
target: '/information_release/news_release_from_authorities/qhjysfb/',
title: '政策资讯 - 权威资讯',
source: ['www.investor.org.cn/zczx/qwzx/'],
target: '/zczx/qwzx',
},
{
title: '权威发布 - 行业协会发布',
source: ['www.investor.org.cn/information_release/news_release_from_authorities/hyxhfb/'],
target: '/information_release/news_release_from_authorities/hyxhfb/',
title: '政策资讯 - 证监会发布',
source: ['www.investor.org.cn/zczx/qwzx/zjhfb/'],
target: '/zczx/qwzx/zjhfb',
},
{
title: '权威发布 - 其他',
source: ['www.investor.org.cn/information_release/news_release_from_authorities/otner/'],
target: '/information_release/news_release_from_authorities/otner/',
title: '政策资讯 - 证券交易所发布',
source: ['www.investor.org.cn/zczx/qwzx/hsjysfb/'],
target: '/zczx/qwzx/hsjysfb',
},
{
title: '市场资讯',
source: ['www.investor.org.cn/information_release/market_news/'],
target: '/information_release/market_news/',
title: '政策资讯 - 期货交易所发布',
source: ['www.investor.org.cn/zczx/qwzx/qhjysfb_1/'],
target: '/zczx/qwzx/qhjysfb_1',
},
{
title: '政策解读',
source: ['www.investor.org.cn/information_release/policy_interpretation/'],
target: '/information_release/policy_interpretation/',
title: '政策资讯 - 协会发布',
source: ['www.investor.org.cn/zczx/qwzx/hyxhfb/'],
target: '/zczx/qwzx/hyxhfb',
},
{
title: '国际交流',
source: ['www.investor.org.cn/information_release/international_communication/'],
target: '/information_release/international_communication/',
title: '政策资讯 - 市场资讯',
source: ['www.investor.org.cn/zczx/market_news/'],
target: '/zczx/market_news',
},
{
title: '政策资讯 - 政策解读',
source: ['www.investor.org.cn/zczx/policy_interpretation/'],
target: '/zczx/policy_interpretation',
},
{
title: '政策资讯 - 法律法规',
source: ['www.investor.org.cn/zczx/flfg/'],
target: '/zczx/flfg',
},
{
title: '政策资讯 - 法律',
source: ['www.investor.org.cn/zczx/flfg/fljsfjs/'],
target: '/zczx/flfg/fljsfjs',
},
{
title: '政策资讯 - 行政法规及司法解释',
source: ['www.investor.org.cn/zczx/flfg/xzfg/'],
target: '/zczx/flfg/xzfg',
},
{
title: '政策资讯 - 部门规章及规范性文件',
source: ['www.investor.org.cn/zczx/flfg/bmgz/'],
target: '/zczx/flfg/bmgz',
},
{
title: '政策资讯 - 投服中心业务规则',
source: ['www.investor.org.cn/zczx/flfg/tfzxzd/'],
target: '/zczx/flfg/tfzxzd',
},
{
title: '政策资讯 - 工作交流',
source: ['www.investor.org.cn/zczx/gzjl/'],
target: '/zczx/gzjl',
},
{
title: '投保动态 - 投保动态',
source: ['www.investor.org.cn/qybh/'],
target: '/qybh',
},
{
title: '投保动态 - 持股行权',
source: ['www.investor.org.cn/qybh/cgxq/'],
target: '/qybh/cgxq',
},
{
title: '投保动态 - 行权动态',
source: ['www.investor.org.cn/qybh/cgxq/xqdt/'],
target: '/qybh/cgxq/xqdt',
},
{
title: '投保动态 - 个案行权',
source: ['www.investor.org.cn/qybh/cgxq/gaxq/'],
target: '/qybh/cgxq/gaxq',
},
{
title: '投保动态 - 典型案例',
source: ['www.investor.org.cn/qybh/cgxq/xqal/'],
target: '/qybh/cgxq/xqal',
},
{
title: '投保动态 - 维权诉讼',
source: ['www.investor.org.cn/qybh/wqfw/'],
target: '/qybh/wqfw',
},
{
title: '投保动态 - 投服中心维权',
source: ['www.investor.org.cn/qybh/wqfw/tfzxwq/'],
target: '/qybh/wqfw/tfzxwq',
},
{
title: '投保动态 - 维权路径与机构',
source: ['www.investor.org.cn/qybh/wqfw/wqljyjg/'],
target: '/qybh/wqfw/wqljyjg',
},
{
title: '投保动态 - 纠纷调解',
source: ['www.investor.org.cn/qybh/tjfw/'],
target: '/qybh/tjfw',
},
{
title: '投保动态 - 调解动态',
source: ['www.investor.org.cn/qybh/tjfw/tjdt/'],
target: '/qybh/tjfw/tjdt',
},
{
title: '投保动态 - 调解组织',
source: ['www.investor.org.cn/qybh/tjfw/tjzz/'],
target: '/qybh/tjfw/tjzz',
},
{
title: '投保动态 - 调解案例',
source: ['www.investor.org.cn/qybh/tjfw/tjal/'],
target: '/qybh/tjfw/tjal',
},
],
view: ViewType.Articles,
};