diff --git a/lib/routes/csust/tggs.ts b/lib/routes/csust/tggs.ts index 38d44b98a..6da0a2579 100644 --- a/lib/routes/csust/tggs.ts +++ b/lib/routes/csust/tggs.ts @@ -1,25 +1,48 @@ -import type { Route } from '@/types'; +import { load } from 'cheerio'; -import { createCsustHandler } from './utils'; +import type { Data, DataItem, Route } from '@/types'; +import cache from '@/utils/cache'; +import got from '@/utils/got'; +import { parseDate } from '@/utils/parse-date'; +import timezone from '@/utils/timezone'; -const handler = createCsustHandler({ - listPath: '/tggs.htm', - feedTitle: '长沙理工大学 - 通告公示', - feedDescription: '长沙理工大学通告公示', -}); +import { getNoticeContent } from './utils'; + +const baseUrl = 'https://www.csust.edu.cn'; +const listPath = '/tggs.htm'; + +async function handler(): Promise { + const response = await got(`${baseUrl}${listPath}`); + const $ = load(response.body); + + const items: Array = $('.list ul li') + .toArray() + .map((li) => { + const $li = $(li); + + return { + title: $li.find('.newTitle').text().trim(), + link: new URL($li.find('a').attr('href')!, baseUrl).href, + pubDate: timezone(parseDate($li.find('.data1').text().trim(), '发布时间 : YYYY-MM-DD'), 8), + }; + }); + + const enrichedItems = await Promise.all(items.map((item) => cache.tryGet(item.link, () => getNoticeContent(item)))); + + return { + title: '长沙理工大学 - 通告公示', + link: `${baseUrl}${listPath}`, + description: '长沙理工大学通告公示', + item: enrichedItems, + }; +} export const route: Route = { path: '/tggs', categories: ['university'], example: '/csust/tggs', - parameters: {}, features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, + supportRadar: true, }, radar: [ { diff --git a/lib/routes/csust/utils.ts b/lib/routes/csust/utils.ts index 5e69f612d..ef9638ac1 100644 --- a/lib/routes/csust/utils.ts +++ b/lib/routes/csust/utils.ts @@ -1,86 +1,26 @@ -import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; -import cache from '@/utils/cache'; +import type { DataItem } from '@/types'; import got from '@/utils/got'; -import { parseDate } from '@/utils/parse-date'; -// 抓取并清清理内容 -export async function getNoticeContent(item: any) { +type NoticeItem = DataItem & { link: string }; + +export async function getNoticeContent(item: NoticeItem): Promise { const response = await got(item.link); const $ = load(response.body); + const pageTitle = $('title').text(); const $content = $('.v_news_content'); + $content.find('script, style, .vsbcontent_end').remove(); + $content.find('img[src], a[href]').each((_, element) => { + const $element = $(element); + const attribute = element.tagName === 'img' ? 'src' : 'href'; + $element.attr(attribute, new URL($element.attr(attribute)!, item.link).href); + }); - if ($content.length) { - // 移除无用元素 - $content.find('script').remove(); - $content.find('style').remove(); - $content.find('.vsbcontent_end').remove(); - $content.find('iframe').remove(); - item.description = $content.html() || item.title; - } else { - item.description = item.title; - } - - return item; -} - -// 解析列表页面,返回包含标题、链接与发布日期的条目 -export function parseListItems($: CheerioAPI, baseUrl: string) { - return $('.list ul li') - .toArray() - .map((li) => { - const element = $(li); - const title = element.find('.newTitle').text().trim(); - const linkRaw = element.find('a').attr('href'); - const dateText = element.find('.data1').text().trim(); - - if (!linkRaw || !title) { - return null; - } - - const dateMatch = dateText.match(/发布时间\s*[::]\s*(\d{4}-\d{1,2}-\d{1,2})/); - const pubDate = dateMatch ? parseDate(dateMatch[1]) : null; - - // 使用 URL 构造函数确保正确拼接 URL - const link = linkRaw.startsWith('http') ? linkRaw : new URL(linkRaw, baseUrl).href; - - return { - title, - link, - pubDate, - } as any; - }) - .filter((i) => i !== null) as any[]; -} - -// 通用处理器工厂:根据栏目路径与标题信息生成 handler -export function createCsustHandler({ listPath, feedTitle, feedDescription }: { listPath: string; feedTitle: string; feedDescription: string }) { - const baseUrl = 'https://www.csust.edu.cn'; - return async function () { - const response = await got(`${baseUrl}${listPath}`); - const $ = load(response.body); - - const items = parseListItems($, baseUrl); - - const item = await Promise.all( - items.map((it) => - cache.tryGet(it.link, async () => { - try { - return await getNoticeContent(it); - } catch { - return it; - } - }) - ) - ); - - return { - title: feedTitle, - link: `${baseUrl}${listPath}`, - description: feedDescription, - item, - }; + return { + ...item, + title: pageTitle.slice(0, pageTitle.lastIndexOf('-')).trim(), + description: $content.html()!, }; } diff --git a/lib/routes/csust/xkxs.ts b/lib/routes/csust/xkxs.ts index fa641b293..2149799f5 100644 --- a/lib/routes/csust/xkxs.ts +++ b/lib/routes/csust/xkxs.ts @@ -1,25 +1,48 @@ -import type { Route } from '@/types'; +import { load } from 'cheerio'; -import { createCsustHandler } from './utils'; +import type { Data, DataItem, Route } from '@/types'; +import cache from '@/utils/cache'; +import got from '@/utils/got'; +import { parseDate } from '@/utils/parse-date'; +import timezone from '@/utils/timezone'; -const handler = createCsustHandler({ - listPath: '/xkxs.htm', - feedTitle: '长沙理工大学 - 学科学术', - feedDescription: '长沙理工大学学科学术', -}); +import { getNoticeContent } from './utils'; + +const baseUrl = 'https://www.csust.edu.cn'; +const listPath = '/xkxs.htm'; + +async function handler(): Promise { + const response = await got(`${baseUrl}${listPath}`); + const $ = load(response.body); + + const items: Array = $('.list ul li') + .toArray() + .map((li) => { + const $li = $(li); + + return { + title: $li.find('.newTitle').text().trim(), + link: new URL($li.find('a').attr('href')!, baseUrl).href, + pubDate: timezone(parseDate($li.find('.data1').text().trim(), '发布时间 : YYYY-MM-DD'), 8), + }; + }); + + const enrichedItems = await Promise.all(items.map((item) => cache.tryGet(item.link, () => getNoticeContent(item)))); + + return { + title: '长沙理工大学 - 学科学术', + link: `${baseUrl}${listPath}`, + description: '长沙理工大学学科学术', + item: enrichedItems, + }; +} export const route: Route = { path: '/xkxs', categories: ['university'], example: '/csust/xkxs', - parameters: {}, features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, + supportRadar: true, }, radar: [ {