fix(route): cast (#14651)

* fix(route): cast

* fix(route): 兼容外链及视频页面特殊dom结构

* docs: 补充文档

* fix: use built in re-export

* Update lib/routes/cast/index.ts

* Update lib/routes/cast/index.ts

* Update lib/routes/cast/index.ts

* Update lib/routes/cast/index.ts

* Update lib/routes/cast/index.ts

* update maintainer

---------
This commit is contained in:
karasu 2024-03-05 09:27:10 +08:00 committed by GitHub
parent b6b9918c6c
commit 0f51d2f93a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 80 additions and 61 deletions

View File

@ -1,71 +1,76 @@
// @ts-nocheck
import cache from '@/utils/cache';
import got from '@/utils/got';
import got, { type Response } from '@/utils/got';
import { load } from 'cheerio';
import { parseDate } from '@/utils/parse-date';
import timezone from '@/utils/timezone';
const baseUrl = 'https://www.cast.org.cn';
export default async (ctx) => {
const { column = 457 } = ctx.req.param();
const { limit = 10 } = ctx.req.query();
const link = `${baseUrl}/col/col${column}/index.html`;
const { data: response } = await got.post(`${baseUrl}/module/web/jpage/dataproxy.jsp`, {
searchParams: {
startrecord: 1,
endrecord: limit,
perpage: limit,
},
form: {
col: 1,
appid: 1,
webid: 1,
path: '/',
columnid: column,
sourceContentType: 1,
unitid: 335,
webname: '中国科学技术协会',
permissiontype: 0,
},
});
interface ResponseData<T> extends Response {
data: T;
}
const $ = load(response, {
xml: {
xmlMode: true,
},
});
async function parsePage(html: string) {
return await Promise.all(
load(html)('li')
.toArray()
.map((el) => {
const title = load(el)('a');
let articleUrl = title.attr('href');
const pageTitle = await cache.tryGet(link, async () => {
const { data: response } = await got(link);
const $ = load(response);
return $('head title').text();
});
if (articleUrl?.startsWith('http')) {
return {
title: title.text(),
link: title.attr('href'),
};
}
articleUrl = `${baseUrl}${title.attr('href')}`;
const list = $('record')
.toArray()
.map((item) => {
item = load($(item).html(), null, false);
const a = item('a').first();
return {
title: a.text(),
pubDate: parseDate(item('.list-data').text().trim(), 'DDYYYY/MM'),
link: `${baseUrl}${a.attr('href')}`,
};
});
return cache.tryGet(articleUrl, async () => {
const res = (await got.get(articleUrl!)) as ResponseData<string>;
const article = load(res.data);
const pubDate = timezone(parseDate(article('meta[name=PubDate]').attr('content')!, 'YYYY-MM-DD HH:mm'), +8);
const items = await Promise.all(
list.map((item) =>
cache.tryGet(item.link, async () => {
const { data: response } = await got(item.link);
const $ = load(response);
item.description = $('#zoom').html();
item.pubDate = timezone(parseDate($('meta[name=PubDate]').attr('content'), 'YYYY-MM-DD HH:mm'), +8);
return item;
return {
title: title.text(),
pubDate,
description: article('#zoom').html(),
link: articleUrl,
};
});
})
)
);
}
export default async (ctx) => {
const { column, subColumn, category } = ctx.req.param();
const { limit = 10 } = ctx.req.query();
let link = `${baseUrl}/${column}/${subColumn}`;
if (category) {
link += `/${category}/index.html`;
}
const { data: indexData } = (await got.get(link)) as ResponseData<string>;
const $ = load(indexData);
let items: any[] = [];
// 新闻-视频首页特殊处理
if (column === 'xw' && subColumn === 'SP' && !category) {
items = await parsePage(indexData);
} else {
const buildUnitScript = $('script[parseType="bulidstatic"]');
const queryUrl = `${baseUrl}${buildUnitScript.attr('url')}`;
const queryData = JSON.parse(buildUnitScript.attr('querydata')?.replace(/'/g, '"') ?? '{}');
queryData.paramJson = `{"pageNo":1,"pageSize":${limit}}`;
const { data } = (await got.get(queryUrl, {
searchParams: new URLSearchParams(queryData),
})) as ResponseData<{ data: { html: string } }>;
items = await parsePage(data.data.html);
}
const pageTitle = $('head title').text();
ctx.set('data', {
title: pageTitle,

View File

@ -1,3 +1,3 @@
export default {
'/:column?': ['TonyRL'],
'/:column/:subColumn/:category?': ['KarasuShin', 'TonyRL'],
};

View File

@ -5,8 +5,8 @@ export default {
{
title: '通用',
docs: 'https://docs.rsshub.app/routes/government#zhong-guo-ke-xue-ji-shu-xie-hui',
source: ['/col/:column/index.html'],
target: (params) => `/cast/${params.column.replace('col', '')}`,
source: ['/:column/:subColumn/:category/index.html', '/:column/:subColumn/index.html'],
target: (params) => (params.category ? `/cast/${params.column}/${params.subColumn}/${params.category}` : `/cast/${params.column}/${params.subColumn}`),
},
],
},

View File

@ -1,3 +1,3 @@
export default (router) => {
router.get('/:column?', './index');
router.get('/:column/:subColumn/:category?', './index');
};

View File

@ -1348,7 +1348,21 @@
### 通用 {#zhong-guo-ke-xue-ji-shu-xie-hui-tong-yong}
<Route author="TonyRL" example="/cast" path="/cast/:column?" paramsDesc={['栏目 ID即 URL 中的数字,默认为 `457`']} radar="1" notOperational="1" />
<Route author="KarasuShin TonyRL" example="/cast/xw/tzgg/ZH" path="/cast/:column/:subColumn/:category?" paramsDesc={['栏目编号,见下表', '二级栏目编号','分类']} radar="1" notOperational="1">
:::tip
在路由末尾处加上 `?limit=限制获取数目` 来限制获取条目数量,默认值为`10`
:::
| 分类 | 编码 |
| -------- | ---- |
| 全景科协 | qjkx |
| 智库 | zk |
| 学术 | xs |
| 科普 | kp |
| 党建 | dj |
| 数据 | sj |
| 新闻 | xw |
</Route>
## 中国民用航空局 {#zhong-guo-min-yong-hang-kong-ju}