feat: 路透社分站:CN & UK (#5103)

Co-authored-by: proletarius101 <proletarius101@protonmail.com>
This commit is contained in:
Henry Wang 2020-07-28 16:29:43 +01:00 committed by GitHub
parent afae89e279
commit d7e758aa00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 304 additions and 21 deletions

View File

@ -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']"/>
## 王垠博客

View File

@ -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

View File

@ -191,8 +191,6 @@ pageClass: routes
<Route author="wolfyu1991" example="/mp4ba/复仇者联盟" path="/mp4ba/:keyword" :paramsDesc="['搜索关键字']" supportBT="1"/>
</Route>
## MQube
### 全站最近更新

View File

@ -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>

View File

@ -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']"/>
## 天津大学

View File

@ -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'));

View File

@ -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,
};
};

View File

@ -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,
};