rsshub
Version:
Make RSS Great Again!
165 lines (144 loc) • 6.64 kB
text/typescript
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,
};
}