feat: 路透社分站:CN & UK (#5103)
Co-authored-by: proletarius101 <proletarius101@protonmail.com>
This commit is contained in:
parent
afae89e279
commit
d7e758aa00
|
|
@ -110,9 +110,7 @@ pageClass: routes
|
|||
|
||||
### 文章
|
||||
|
||||
<Route author="prnake" example="/blogs/wang54" path="/blogs/wang54/:id?" :paramsDesc="['RSS抓取地址:https://wangwusiwj.blogspot.com/:id?,默认为2020']">
|
||||
|
||||
</Route>
|
||||
<Route author="prnake" example="/blogs/wang54" path="/blogs/wang54/:id?" :paramsDesc="['RSS抓取地址:https://wangwusiwj.blogspot.com/:id?,默认为2020']"/>
|
||||
|
||||
## 王垠博客
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ Refer to [Boston.com's feed page](https://www.boston.com/rss-feeds) for tags. Fo
|
|||
Generates full-text that the official feed doesn't provide.
|
||||
Refer to [Chicago Tribune's feed page](https://www.chicagotribune.com/about/ct-chicago-tribune-rss-feeds-htmlstory.html) for categories. For instance, `https://www.chicagotribune.com/arcio/rss/category/nation-world/` corresponds to `/chicagotribune/nation-world`.
|
||||
|
||||
|
||||
</RouteEn>
|
||||
|
||||
## China Dialogue
|
||||
|
|
@ -89,6 +88,29 @@ Refer to [Chicago Tribune's feed page](https://www.chicagotribune.com/about/ct-c
|
|||
|
||||
<RouteEn author="Andiedie" example="/nhk/news_web_easy" path="/nhk/news_web_easy"/>
|
||||
|
||||
## Reuters
|
||||
|
||||
### Channel
|
||||
|
||||
<RouteEn author="HenryQW proletarius101" example="/reuters/channel/uk/personalFinance" path="/reuters/channel/:site/:channel" :paramsDesc="['sub-site, see the supported list below','channel, please note it\'s case-sensitive']">
|
||||
|
||||
Supported sub-sites:
|
||||
|
||||
- 中国分站 `cn`:
|
||||
See [路透社中国分站](../traditional-media.html#lu-tou-she)
|
||||
|
||||
- US site `us`:
|
||||
| Business | Markets | World | Politics | Tech | Breakingviews | Wealth | Life |
|
||||
| -------- | ------- | ----- | -------- | ---------- | ------------- | ------ | --------- |
|
||||
| business | markets | world | politics | technology | breakingviews | wealth | lifestyle |
|
||||
|
||||
- UK site `uk`:
|
||||
| Business | World | UK | Tech | Money | Breakingviews | Life |
|
||||
| -------- | ----- | --- | ---------- | --------------- | ------------- | --------- |
|
||||
| business | world | uk | technology | personalFinance | breakingviews | lifestyle |
|
||||
|
||||
</RouteEn>
|
||||
|
||||
## RTHK
|
||||
|
||||
### News
|
||||
|
|
|
|||
|
|
@ -191,8 +191,6 @@ pageClass: routes
|
|||
|
||||
<Route author="wolfyu1991" example="/mp4ba/复仇者联盟" path="/mp4ba/:keyword" :paramsDesc="['搜索关键字']" supportBT="1"/>
|
||||
|
||||
</Route>
|
||||
|
||||
## MQube
|
||||
|
||||
### 全站最近更新
|
||||
|
|
|
|||
|
|
@ -194,8 +194,6 @@ Category 列表:
|
|||
|
||||
<Route author="saury" example="/eastday/sh" path="/eastday/sh" />
|
||||
|
||||
</Route>
|
||||
|
||||
## 端传媒
|
||||
|
||||
### 端传媒
|
||||
|
|
@ -306,15 +304,55 @@ category 对应的关键词有
|
|||
|
||||
### 标签
|
||||
|
||||
<Route author="Naiqus" example="/wired/tag/bitcoin" path="/wired/tag/:tag" :paramsDesc="['标签']">
|
||||
|
||||
</Route>
|
||||
<Route author="Naiqus" example="/wired/tag/bitcoin" path="/wired/tag/:tag" :paramsDesc="['标签']"/>
|
||||
|
||||
## 路透社
|
||||
|
||||
### 实时资讯
|
||||
|
||||
<Route author="black-desk" example="/reuters/theWire" path="/reuters/theWire">
|
||||
<Route author="black-desk" example="/reuters/theWire" path="/reuters/theWire" />
|
||||
|
||||
### 频道
|
||||
|
||||
<Route author="HenryQW proletarius101" example="/reuters/channel/cn/analyses" path="/reuters/channel/:site/:channel" :paramsDesc="['语言,支持的分站列表如下','频道名,请注意大小写需与如下表格中一致。']">
|
||||
|
||||
支持语言列表
|
||||
|
||||
- 中国分站 `cn`:
|
||||
|
||||
- 主频道:
|
||||
|
||||
| 深度分析 | 时事要闻 | 生活 | 投资 |
|
||||
| -------- | ----------- | ---- | --------- |
|
||||
| analyses | generalnews | life | investing |
|
||||
|
||||
- 资讯子频道:
|
||||
|
||||
| 中国财经 | 国际财经 | 新闻人物 | 财经视点 |
|
||||
| -------- | --------------------- | --------- | -------- |
|
||||
| china | internationalbusiness | newsmaker | opinions |
|
||||
|
||||
- 专栏子频道:
|
||||
|
||||
| 中国财经专栏 | 国际财经专栏 | 大宗商品专栏 |
|
||||
| ------------ | ------------ | ------------ |
|
||||
| CnColumn | IntColumn | ComColumn |
|
||||
|
||||
- 美国分站 `us`:
|
||||
|
||||
- 主频道:
|
||||
|
||||
| Business | Markets | World | Politics | Tech | Breakingviews | Wealth | Life |
|
||||
| -------- | ------- | ----- | -------- | ---------- | ------------- | ------ | --------- |
|
||||
| business | markets | world | politics | technology | breakingviews | wealth | lifestyle |
|
||||
|
||||
- 英国分站 `uk`:
|
||||
|
||||
- 主频道:
|
||||
|
||||
| Business | Markets | World | UK | Tech | Money | Breakingviews | Sport | Life |
|
||||
| -------- | ------- | ----- | -- | ---------- | --------------- | ------------- | ------ | --------- |
|
||||
| business | markets | world | uk | technology | personalFinance | breakingviews | sports | lifestyle |
|
||||
|
||||
</Route>
|
||||
|
||||
|
|
|
|||
|
|
@ -1358,15 +1358,11 @@ type 列表:
|
|||
|
||||
### 信息与工程学院动态公告列表
|
||||
|
||||
<Route author="talenHuang" example="/sctu/xgxy" path="/sctu/information-engineer-faculty/index">
|
||||
|
||||
</Route>
|
||||
<Route author="talenHuang" example="/sctu/xgxy" path="/sctu/information-engineer-faculty/index"/>
|
||||
|
||||
### 信息与工程学院公告详情
|
||||
|
||||
<Route author="talenHuang" example="/sctu/xgxy/652" path="/sctu/information-engineer-faculty/context/:id" :paramsDesc="['文章id']">
|
||||
|
||||
</Route>
|
||||
<Route author="talenHuang" example="/sctu/xgxy/652" path="/sctu/information-engineer-faculty/context/:id" :paramsDesc="['文章id']"/>
|
||||
|
||||
### 教务处
|
||||
|
||||
|
|
@ -1380,9 +1376,7 @@ type 列表:
|
|||
|
||||
### 教务处通告详情
|
||||
|
||||
<Route author="talenHuang" example="/sctu/jwc/13/645" path="/sctu/jwc/context/:type/:id" :paramsDesc="['通知类型','文章id']">
|
||||
|
||||
</Route>
|
||||
<Route author="talenHuang" example="/sctu/jwc/13/645" path="/sctu/jwc/context/:type/:id" :paramsDesc="['通知类型','文章id']"/>
|
||||
|
||||
## 天津大学
|
||||
|
||||
|
|
|
|||
|
|
@ -2062,6 +2062,9 @@ router.get('/netease/dy/:id', require('./routes/netease/dy'));
|
|||
// 海猫吧
|
||||
router.get('/haimaoba/:id?', require('./routes/haimaoba/comics'));
|
||||
|
||||
// 路透社
|
||||
router.get('/reuters/channel/:site/:channel', require('./routes/reuters/channel'));
|
||||
|
||||
// 蒲公英
|
||||
router.get('/pgyer/:app?', require('./routes/pgyer/app'));
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,164 @@
|
|||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { site } = ctx.params || 'cn';
|
||||
const homePage = `https://${site === 'us' ? 'www' : site}.reuters.com`;
|
||||
|
||||
let title = 'Reuters ',
|
||||
link = `https://${site === 'us' ? 'www' : site}.reuters.com/news/`,
|
||||
linkSelector;
|
||||
|
||||
const { channel } = ctx.params;
|
||||
|
||||
if (channel) {
|
||||
if (site === 'cn') {
|
||||
title = '路透社 ';
|
||||
linkSelector = '.inlineLinks a';
|
||||
switch (channel) {
|
||||
case 'china':
|
||||
title += '中国财经';
|
||||
break;
|
||||
case 'internationalbusiness':
|
||||
title += '国际财经';
|
||||
break;
|
||||
case 'newsmaker':
|
||||
title += '新闻人物';
|
||||
break;
|
||||
case 'opinions':
|
||||
title += '财经视点';
|
||||
break;
|
||||
case 'analyses':
|
||||
title += '深度分析';
|
||||
break;
|
||||
case 'generalnews':
|
||||
title += '时事要闻';
|
||||
break;
|
||||
case 'CnColumn':
|
||||
title += '中国财经专栏';
|
||||
break;
|
||||
case 'ComColumn':
|
||||
title += '大宗商品专栏';
|
||||
break;
|
||||
case 'IntColumn':
|
||||
title += '国际财经专栏';
|
||||
break;
|
||||
case 'investing':
|
||||
title += '投资';
|
||||
link = homePage;
|
||||
break;
|
||||
case 'life':
|
||||
title += '生活';
|
||||
link = homePage;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (site === 'uk') {
|
||||
title += 'UK ';
|
||||
linkSelector = '.story-content a';
|
||||
switch (channel) {
|
||||
case 'business':
|
||||
title += 'Business';
|
||||
link = homePage;
|
||||
break;
|
||||
case 'markets':
|
||||
linkSelector = '.moduleBody a, .story-content a';
|
||||
title += 'Markets';
|
||||
link = 'https://uk.reuters.com/business/';
|
||||
break;
|
||||
case 'world':
|
||||
title += 'World';
|
||||
break;
|
||||
case 'uk':
|
||||
title += 'UK';
|
||||
break;
|
||||
case 'technology':
|
||||
title += 'Tech';
|
||||
break;
|
||||
case 'personalFinance':
|
||||
title += 'Money';
|
||||
link = 'https://uk.reuters.com/business';
|
||||
break;
|
||||
case 'breakingviews':
|
||||
title += 'Breakingviews';
|
||||
link = homePage;
|
||||
break;
|
||||
case 'sports':
|
||||
linkSelector = '.story-content a, .story-title a';
|
||||
title += 'Sport';
|
||||
break;
|
||||
case 'lifestyle':
|
||||
title += 'Life';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (site === 'us') {
|
||||
linkSelector = '.story-content a,';
|
||||
switch (channel) {
|
||||
case 'business':
|
||||
title += 'Business';
|
||||
link = homePage;
|
||||
break;
|
||||
case 'markets':
|
||||
linkSelector = '.moduleBody a, .story-content a';
|
||||
title += 'Markets';
|
||||
link = 'https://www.reuters.com/finance/';
|
||||
break;
|
||||
case 'world':
|
||||
title += 'World';
|
||||
break;
|
||||
case 'politics':
|
||||
title += 'Politics';
|
||||
link = 'https://www.reuters.com/';
|
||||
break;
|
||||
case 'technology':
|
||||
title += 'Tech';
|
||||
break;
|
||||
case 'breakingviews':
|
||||
title += 'Breakingviews';
|
||||
link = homePage;
|
||||
break;
|
||||
case 'wealth':
|
||||
linkSelector = '.story-content a, .story-title a';
|
||||
title += 'Wealth';
|
||||
link = 'https://www.reuters.com/finance/';
|
||||
break;
|
||||
case 'lifestyle':
|
||||
title += 'Life';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
link += channel;
|
||||
}
|
||||
|
||||
const response = await got.get(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const links = $(linkSelector).map((i, e) => homePage + e.attribs.href);
|
||||
|
||||
const items = await Promise.all(
|
||||
links.splice(0, 10).map(async (link) => {
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
}
|
||||
|
||||
const single = await utils.ProcessFeed(link);
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title,
|
||||
link,
|
||||
description: title,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const ProcessFeed = async (link) => {
|
||||
const response = await got.get(link);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const pubDate = $('meta[property="og:article:published_time"]')[0].attribs.content;
|
||||
const title = $('meta[property="og:title"]')[0].attribs.content;
|
||||
const author = $('meta[property="og:article:author"]')[0].attribs.content;
|
||||
const cover = $('meta[property="og:image"]')[0].attribs.content;
|
||||
const description = $('.StandardArticleBody_body');
|
||||
|
||||
// if the article's cover photo is not the meaningless logo
|
||||
if (cover !== 'https://s4.reutersmedia.net/resources_v2/images/rcom-default.png') {
|
||||
const image = $('.PrimaryAsset_container img');
|
||||
|
||||
if (image.length > 0) {
|
||||
image[0].attribs.src = cover;
|
||||
}
|
||||
}
|
||||
|
||||
// handle slideshows and videos
|
||||
const pageDataPattern = new RegExp(`(?<=<script type="text/javascript">window.RCOM_Data = ){.*}(?=;</script>)`);
|
||||
const pageData = JSON.parse(response.data.match(pageDataPattern)[0]);
|
||||
|
||||
// keys of this json has random tails, so we have to iterate through them
|
||||
Object.keys(pageData).forEach((key) => {
|
||||
// videos and slideshow appear only in `article_list`
|
||||
if (!key.startsWith('article_list')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add full-res pictures at the end
|
||||
const slideshowData = pageData[key].first_article.images;
|
||||
slideshowData &&
|
||||
slideshowData.forEach((imgData) => {
|
||||
description.insertAfter(`<figure>
|
||||
<img src="${'https:' + imgData.url}"
|
||||
alt="${imgData.title}">
|
||||
<figcaption>${imgData.caption}</figcaption>
|
||||
</figure>`);
|
||||
});
|
||||
|
||||
// add full-res pictures at the beginning
|
||||
const videoData = pageData[key].first_article.videos;
|
||||
videoData &&
|
||||
videoData.forEach((videoData) => {
|
||||
description.insertBefore(`<video controls width="250" autoPictureInPicture=true poster=${'https:' + videoData.thumbnail}>
|
||||
<source src="${'https:' + videoData.url}"
|
||||
type="video/mp4">
|
||||
Sorry, your browser doesn't support embedded videos.
|
||||
</video>
|
||||
<caption>${videoData.caption}</caption>`);
|
||||
});
|
||||
});
|
||||
|
||||
// remove useless DOMs
|
||||
description.find('.Image_expand-button, .LazyImage_fallback, .Slideshow_container, .Slideshow_caption, .Slideshow_expand-button, .Attribution_container, .StandardArticleBody_trustBadgeContainer').remove();
|
||||
|
||||
return { link, author, pubDate, title, description: description.html() };
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
ProcessFeed,
|
||||
};
|
||||
Loading…
Reference in New Issue