UNPKG

rsshub

Version:
165 lines (144 loc) 6.64 kB
import { Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { load } from 'cheerio'; import { parseDate } from '@/utils/parse-date'; const mainCategories = { local: 119, international: 120, entertainment: 500, life: 501, technology: 502, finance: 121, }; const categories = { tracker: 123, feature: 124, opinion: 125, }; export const route: Route = { path: '/news/:category?/:id?', categories: ['traditional-media'], example: '/now/news', parameters: { category: '分类,见下表,默认为首页', id: '编号,可在对应专题/节目页 URL 中找到 topicId' }, features: { requireConfig: false, requirePuppeteer: false, antiCrawler: false, supportBT: false, supportPodcast: false, supportScihub: false, }, radar: [ { source: ['news.now.com/home/:category?', 'news.now.com/'], target: '/news/:category?', }, ], name: '新聞', maintainers: ['nczitzk'], handler, url: 'news.now.com/', description: `::: tip **编号** 仅对事件追蹤、評論節目、新聞專題三个分类起作用,例子如下: 对于 [事件追蹤](https://news.now.com/home/tracker) 中的 [塔利班奪權](https://news.now.com/home/tracker/detail?catCode=123\&topicId=1056) 话题,其网址为 \`https://news.now.com/home/tracker/detail?catCode=123&topicId=1056\`,其中 \`topicId\` 为 1056,则对应路由为 [\`/now/news/tracker/1056\`](https://rsshub.app/now/news/tracker/1056) ::: | 首頁 | 港聞 | 兩岸國際 | 娛樂 | | ---- | ----- | ------------- | ------------- | | | local | international | entertainment | | 生活 | 科技 | 財經 | 體育 | | ---- | ---------- | ------- | ------ | | life | technology | finance | sports | | 事件追蹤 | 評論節目 | 新聞專題 | | -------- | -------- | -------- | | tracker | feature | opinion |`, }; async function handler(ctx) { const { category = '', id = '' } = ctx.req.param(); const limit = Number.parseInt(ctx.req.query('limit') || '20', 10); const hasTopicId = id && Object.hasOwn(categories, category); const rootUrl = 'https://news.now.com'; const pageUrl = hasTopicId ? `${rootUrl}/home/${category}/detail?catCode=${categories[category]}&topicId=${id}` : `${rootUrl}/home${category ? `/${category}` : ''}`; let apiUrl; if (hasTopicId) { apiUrl = pageUrl; } else if (category === 'sports') { apiUrl = `https://sportsapi.now.com/api/getNewsList?pageSize=${limit}&pageNo=1&searchTagsKey=allSportsSearchTags`; } else if (category) { apiUrl = `https://d3sli7vh0lsda4.cloudfront.net/api/getNewsList?category=${mainCategories[category]}&pageNo=1&pageSize=${limit}`; } else { apiUrl = pageUrl; } const response = await ofetch(apiUrl); const isApi = typeof response === 'object' && Array.isArray(response); const $ = load(response); let list; if (isApi) { list = category === 'sports' ? response.map((item) => { const image = item.newsPhotos ?.filter((p) => p.sizeType === '3') ?.map((p) => `<img src="${p.imageFileUrl}">`) .join(''); return { title: item.headlineChi, description: image, link: `https://news.now.com/home/${category}/player?newsId=${item.newsId}`, pubDate: parseDate(item.publishDate, 'x'), category: [...item.sportTypes.map((t) => t.sportTypeNameChi), ...item.players.map((p) => p.playerFullNameChi), ...item.teams.map((t) => t.teamCodeChi)], image: item.newsPhotos?.find((p) => p.sizeType === '3')?.imageUrl, newsId: item.newsId, }; }) : response.map((item) => { const image = item.image2Url ?? item.imageUrl ?? item.image3Url; return { title: item.title, description: (image ? `<img src="${image}">` : '') + item.leading + item.summary, link: `https://news.now.com/home/${category}/player?newsId=${item.newsId}`, pubDate: parseDate(item.publishDate, 'x'), updated: parseDate(item.lastModifyDate, 'x'), category: item.newsTags.map((t) => t.tag), image, }; }); } else { list = $(`${category === '' ? '.homeFeaturedNews ' : '.newsCategoryColLeft '}.newsTitle`) .toArray() .slice(0, limit) .map((item) => { item = $(item); return { title: item.text(), link: `${rootUrl}${item.parent().parent().attr('href')}`, }; }); } const items = await Promise.all( list.map((item) => cache.tryGet(item.link, async () => { if (!item.pubDate || item.newsId) { const detailResponse = await ofetch(item.link); const $ = load(detailResponse); const newsData = JSON.parse( $('script:contains("var newsData")') .text() .match(/var newsData = (.*?);/)?.[1] || '{}' ); const images = newsData.imageList ? newsData.imageList.map((img) => `<img src="${img.image2Url}">`).join('') : ''; item.description = item.description ? item.description + ($('.img_caption').prop('outerHTML') ?? '') + $('.newsLeading').html() : images + $('.newsLeading').html(); item.pubDate ||= parseDate(newsData.publishDate, 'x'); item.updated ||= parseDate(newsData.lastModifyDate, 'x'); item.category ||= [...new Set([newsData.categoryName, ...newsData.newsTags.map((t) => t.tag), ...newsData.newsTopics.map((t) => t.topicName)])]; } return item; }) ) ); return { title: Object.hasOwn(categories, category) ? $('title').text() : ($('.smallSpace.active').text() || '首頁') + ' | Now 新聞', link: pageUrl, item: items, }; }