From 4e840c617ea94146232bb4cbdf2600905f60255a Mon Sep 17 00:00:00 2001 From: Tony Date: Sat, 7 Jun 2025 00:37:04 +0800 Subject: [PATCH] feat(route): add chiphell (#19304) --- lib/router.js | 3 - lib/routes-deprecated/chiphell/forum.js | 67 -------------------- lib/routes/chiphell/namespace.ts | 7 +++ lib/routes/chiphell/portal.ts | 82 +++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 70 deletions(-) delete mode 100644 lib/routes-deprecated/chiphell/forum.js create mode 100644 lib/routes/chiphell/namespace.ts create mode 100644 lib/routes/chiphell/portal.ts diff --git a/lib/router.js b/lib/router.js index 9873875f76..1ad2042507 100644 --- a/lib/router.js +++ b/lib/router.js @@ -1023,9 +1023,6 @@ router.get('/jnu/yw/:type?', lazyloadRouteHandler('./routes/universities/jnu/yw/ // moxingfans router.get('/moxingfans', lazyloadRouteHandler('./routes/moxingfans')); -// Chiphell -router.get('/chiphell/forum/:forumId?', lazyloadRouteHandler('./routes/chiphell/forum')); - // 考研帮调剂信息 router.get('/kaoyan', lazyloadRouteHandler('./routes/kaoyan/kaoyan')); diff --git a/lib/routes-deprecated/chiphell/forum.js b/lib/routes-deprecated/chiphell/forum.js deleted file mode 100644 index 3813a3a9db..0000000000 --- a/lib/routes-deprecated/chiphell/forum.js +++ /dev/null @@ -1,67 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); -const parser = require('@/utils/rss-parser'); - -module.exports = async (ctx) => { - const forumId = ctx.params.forumId; - - const feed = await parser.parseURL(`https://www.chiphell.com/forum.php?mod=rss&fid=${forumId}`); - const items = await Promise.all( - feed.items.map(async (item) => { - const cache = await ctx.cache.get(item.link); - if (cache) { - return JSON.parse(cache); - } - - const response = await got({ - method: 'get', - url: item.link, - }); - - const html = response.data; - const $ = cheerio.load(html); - const description = $('div[class="pcb"]').first(); - const imgNode = $(description).find('img'); - - // replace placeholer image url - imgNode.each((index, element) => { - if ($(element).attr('src') && $(element).attr('src').includes('none.gif')) { - $(element).attr('src', $(element).attr('zoomfile')); - } - - // remove image size limit - $(element).attr('width', null); - $(element).attr('height', null); - }); - - // remove image tips - $(description).find('div[class*="aimg_tip"]').remove(); - $(description).find('div[class*="tip"]').remove(); - $(description).find('p[class="mbn"]').remove(); - - // remove rate infomation - $(description).find('dl[class="rate"]').remove(); - $(description).find('h3[class*="psth"]').remove(); - - const single = { - title: item.title, - description: description.html(), - pubDate: item.pubDate, - link: item.link, - author: item.author, - }; - ctx.cache.set(item.link, JSON.stringify(single)); - return single; - }) - ); - - let title = feed.title.split('-'); - title = `${title.at(-1)} - Chiphell`; - - ctx.state.data = { - title, - link: feed.link, - description: feed.description, - item: items, - }; -}; diff --git a/lib/routes/chiphell/namespace.ts b/lib/routes/chiphell/namespace.ts new file mode 100644 index 0000000000..4406c6ca2e --- /dev/null +++ b/lib/routes/chiphell/namespace.ts @@ -0,0 +1,7 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: 'Chiphell', + url: 'www.chiphell.com', + lang: 'zh-CN', +}; diff --git a/lib/routes/chiphell/portal.ts b/lib/routes/chiphell/portal.ts new file mode 100644 index 0000000000..4b6f577d30 --- /dev/null +++ b/lib/routes/chiphell/portal.ts @@ -0,0 +1,82 @@ +import { Route } from '@/types'; +import type { Context } from 'hono'; + +import cache from '@/utils/cache'; +import ofetch from '@/utils/ofetch'; +import * as cheerio from 'cheerio'; +import { parseDate } from '@/utils/parse-date'; +import timezone from '@/utils/timezone'; + +const handler = async (ctx: Context) => { + const { catId = '1' } = ctx.req.param(); + const url = `https://www.chiphell.com/portal.php?mod=list&catid=${catId}`; + + const response = await ofetch(url); + const $ = cheerio.load(response); + + const list = $('dl.cl') + .toArray() + .map((item) => { + const $item = $(item); + const a = $item.find('a.xi2'); + + return { + title: a.text(), + link: `https://www.chiphell.com/${a.attr('href')}`, + category: [$item.find('dd label').text()], + pubDate: timezone(parseDate($item.find('span.xg1').text()), +8), + }; + }); + + const items = await Promise.all( + list.map((item) => + cache.tryGet(item.link, async () => { + const response = await ofetch(item.link); + const $ = cheerio.load(response); + + $('#article_content div br').parent().remove(); + let description = $('#article_content').html(); + + if ($('.pg').length) { + const urls = $('.pg a') + .toArray() + .map((item) => { + const $item = $(item); + return `https://www.chiphell.com/${$item.attr('href')}`; + }) + .slice(0, -1); + const responses = await Promise.all(urls.map((url) => ofetch(url))); + const $pages = responses.map((item) => cheerio.load(item)); + const contents = $pages.map(($item) => { + $item('#article_content div br').parent().remove(); + return $item('#article_content').html(); + }); + description = [description, ...contents].join(''); + } + + item.description = description; + + return item; + }) + ) + ); + + return { + title: $('head title').text(), + description: $('head meta[name="description"]').attr('content'), + link: url, + item: items, + }; +}; + +export const route: Route = { + path: '/portal/:catId?', + name: '分类', + categories: ['bbs'], + example: '/chiphell/portal/1', + parameters: { + catId: '分类 ID,可在 URL 中找到,默认为 1', + }, + maintainers: ['tylinux'], + handler, +};