parent
7a89b9de5f
commit
fac1541ae6
|
|
@ -2049,16 +2049,14 @@ Category 列表:
|
|||
|
||||
### 纽约时报
|
||||
|
||||
<route name="全球纵览" author="HenryQW" example="/nytimes" path="/nytimes/index">
|
||||
|
||||
::: tip 提示
|
||||
|
||||
由于众所周知的原因,文章内的图片在中国大陆可能无法正常显示。
|
||||
|
||||
:::
|
||||
<route name="官方 RSS" author="HenryQW" example="/nytimes/dual" path="/nytimes/index/:lang?" :paramsDesc="['语言, 缺省中文']">
|
||||
|
||||
通过提取文章全文,以提供比官方源更佳的阅读体验。
|
||||
|
||||
| 默认中文 | 中英对照 | 英文 |
|
||||
| -------- | -------- | ---- |
|
||||
| (空) | dual | en |
|
||||
|
||||
</route>
|
||||
|
||||
<route name="每日简报" author="xyqfer" example="/nytimes/morning_post" path="/nytimes/morning_post"/>
|
||||
|
|
@ -2099,12 +2097,6 @@ Category 列表:
|
|||
|
||||
<route name="BBC" author="HenryQW" example="/bbc/chinese" path="/bbc/:channel?" :paramsDesc="['频道, 缺省为热门']">
|
||||
|
||||
::: tip 提示
|
||||
|
||||
由于众所周知的原因, 文章内的图片在中国大陆可能无法正常显示.
|
||||
|
||||
:::
|
||||
|
||||
通过提取文章全文, 以提供比官方源更佳的阅读体验.
|
||||
|
||||
支持大部分频道, 频道名称见[官方频道 RSS](https://www.bbc.co.uk/news/10628494).
|
||||
|
|
@ -2123,7 +2115,6 @@ Category 列表:
|
|||
|
||||
- 不支持付费文章.
|
||||
- 由于未知原因 FT 中文网的 SSL 证书不被信任 (参见[SSL Labs 报告](https://www.ssllabs.com/ssltest/analyze.html?d=www.ftchinese.com&latest)), 所有文章通过 http 协议获取.
|
||||
- 由于众所周知的原因, 文章内的图片在中国大陆可能无法正常显示.
|
||||
|
||||
:::
|
||||
|
||||
|
|
@ -2138,12 +2129,6 @@ Category 列表:
|
|||
|
||||
### 卫报 The Guardian
|
||||
|
||||
::: tip 提示
|
||||
|
||||
由于众所周知的原因,文章内的图片在中国大陆可能无法正常显示。
|
||||
|
||||
:::
|
||||
|
||||
通过提取文章全文,以提供比官方源更佳的阅读体验。
|
||||
|
||||
<route name="Editorial" author="HenryQW" example="/guardian/editorial" path="/guardian/editorial"/>
|
||||
|
|
|
|||
|
|
@ -345,7 +345,7 @@ router.get('/yande.re/post/popular_recent', require('./routes/yande.re/post_popu
|
|||
router.get('/yande.re/post/popular_recent/:period', require('./routes/yande.re/post_popular_recent'));
|
||||
|
||||
// 纽约时报
|
||||
router.get('/nytimes', require('./routes/nytimes/index'));
|
||||
router.get('/nytimes/:lang?', require('./routes/nytimes/index'));
|
||||
router.get('/nytimes/morning_post', require('./routes/nytimes/morning_post'));
|
||||
|
||||
// 3dm
|
||||
|
|
|
|||
|
|
@ -1,34 +1,100 @@
|
|||
const axios = require('../../utils/axios');
|
||||
const utils = require('./utils');
|
||||
const cheerio = require('cheerio');
|
||||
const Parser = require('rss-parser');
|
||||
const parser = new Parser();
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
let { lang = '' } = ctx.params;
|
||||
lang = lang.toLowerCase();
|
||||
|
||||
let title = '纽约时报中文网';
|
||||
|
||||
if (lang === 'dual') {
|
||||
title += ' - 中英对照版';
|
||||
} else if (lang === 'en') {
|
||||
title += ' - 英文原版';
|
||||
}
|
||||
|
||||
const feed = await parser.parseURL('https://cn.nytimes.com/rss/');
|
||||
const items = await Promise.all(
|
||||
feed.items.splice(0, 10).map(async (item) => {
|
||||
const response = await axios({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
let link = item.link;
|
||||
|
||||
const description = utils.ProcessFeed(response.data);
|
||||
let response,
|
||||
hasEnVersion = false,
|
||||
dual = false;
|
||||
|
||||
if (lang === 'dual') {
|
||||
link = link.replace('/?utm_source=RSS', '') + '/dual';
|
||||
|
||||
try {
|
||||
response = await ctx.cache.tryGet(`nyt: ${link}`, async () => {
|
||||
const response = await axios.get(link);
|
||||
|
||||
return response.data;
|
||||
});
|
||||
|
||||
dual = true;
|
||||
} catch (error) {
|
||||
response = await ctx.cache.tryGet(`nyt: ${item.link}`, async () => {
|
||||
const response = await axios.get(item.link);
|
||||
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
response = await ctx.cache.tryGet(`nyt: ${item.link}`, async () => {
|
||||
const response = await axios.get(item.link);
|
||||
|
||||
return response.data;
|
||||
});
|
||||
|
||||
if (lang === 'en') {
|
||||
const $ = cheerio.load(response);
|
||||
if ($('.dual-btn').length > 0) {
|
||||
hasEnVersion = true;
|
||||
link = $('.dual-btn a')
|
||||
.last()
|
||||
.attr().href;
|
||||
|
||||
response = await ctx.cache.tryGet(`nyt: ${link}`, async () => {
|
||||
const response = await axios.get(link);
|
||||
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const single = {
|
||||
title: item.title,
|
||||
description,
|
||||
pubDate: item.pubDate,
|
||||
link: item.link,
|
||||
link,
|
||||
author: item['dc:creator'],
|
||||
};
|
||||
|
||||
const result = utils.ProcessFeed(response, hasEnVersion);
|
||||
|
||||
single.description = result.description;
|
||||
|
||||
if (hasEnVersion) {
|
||||
single.title = result.title;
|
||||
single.author = result.author;
|
||||
}
|
||||
|
||||
if (dual) {
|
||||
single.title = `「中英」${single.title}`;
|
||||
}
|
||||
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '纽约时报中文网 国际纵览',
|
||||
title,
|
||||
link: 'https://cn.nytimes.com',
|
||||
description: '纽约时报中文网 国际纵览',
|
||||
description: title,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@ module.exports = async (ctx) => {
|
|||
post.map(async (item) => {
|
||||
const link = item.link;
|
||||
const description = await ctx.cache.tryGet(`nyt: ${link}`, async () => {
|
||||
const response = await axios({
|
||||
method: 'get',
|
||||
url: link,
|
||||
});
|
||||
const response = await axios.get(link);
|
||||
|
||||
return utils.ProcessFeed(response.data);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,27 +1,79 @@
|
|||
const cheerio = require('cheerio');
|
||||
|
||||
const ProcessFeed = (data) => {
|
||||
const ProcessImage = ($, e) => {
|
||||
const photo = $(e).find('figure');
|
||||
|
||||
let cover = `<figure><img src='${photo[0].attribs.itemid}'><br><figcaption>`;
|
||||
|
||||
const caption = $(e).find('figcaption');
|
||||
|
||||
cover += `${$(caption[0])
|
||||
.text()
|
||||
.trim()}</figcaption></figure>`;
|
||||
|
||||
return cover;
|
||||
};
|
||||
|
||||
const ProcessFeed = (data, hasEnVersion = false) => {
|
||||
const $ = cheerio.load(data);
|
||||
const content = $('section.article-body');
|
||||
|
||||
// remove useless DOMs
|
||||
content.find('div.big_ad, div.article-body-aside').each((i, e) => {
|
||||
$(e).remove();
|
||||
});
|
||||
let content;
|
||||
const result = {};
|
||||
|
||||
if ($('figure.article-span-photo').length > 0) {
|
||||
// there is a cover photo
|
||||
const cover = $('figure.article-span-photo');
|
||||
$(cover).insertBefore(content[0].firstChild);
|
||||
// 处理 www.nytimes.com
|
||||
if (hasEnVersion) {
|
||||
content = $('section[name="articleBody"]');
|
||||
result.title = `「英」${$('h1')
|
||||
.text()
|
||||
.trim()}`;
|
||||
result.author = $('article#story span[itemprop="name"]').text();
|
||||
|
||||
// 处理封面图片
|
||||
$('article#story > header')
|
||||
.find('div[data-testid="photoviewer-wrapper"]')
|
||||
.each((i, e) => {
|
||||
const cover = ProcessImage($, e);
|
||||
|
||||
$(cover).insertBefore(content[0].firstChild);
|
||||
});
|
||||
|
||||
// 处理图片
|
||||
content.find('div[data-testid="photoviewer-wrapper"]').each((i, e) => {
|
||||
const cover = ProcessImage($, e);
|
||||
$(cover).insertBefore(e);
|
||||
$(e).remove();
|
||||
});
|
||||
|
||||
// remove useless DOMs
|
||||
content.find('aside').each((i, e) => {
|
||||
$(e).remove();
|
||||
});
|
||||
}
|
||||
// 处理 cn.nytimes.com
|
||||
else {
|
||||
content = $('section.article-body');
|
||||
|
||||
// remove useless DOMs
|
||||
content.find('div.big_ad, div.article-body-aside').each((i, e) => {
|
||||
$(e).remove();
|
||||
});
|
||||
|
||||
if ($('figure.article-span-photo').length > 0) {
|
||||
// there is a cover photo
|
||||
const cover = $('figure.article-span-photo');
|
||||
$(cover).insertBefore(content[0].firstChild);
|
||||
}
|
||||
|
||||
if ($('footer.author-info').length > 0) {
|
||||
// credit to original author and translators
|
||||
const footer = $('footer.author-info');
|
||||
$(footer).insertAfter(content[0].lastChild);
|
||||
}
|
||||
}
|
||||
|
||||
if ($('footer.author-info').length > 0) {
|
||||
// credit to original author and translators
|
||||
const footer = $('footer.author-info');
|
||||
$(footer).insertAfter(content[0].lastChild);
|
||||
}
|
||||
result.description = content.html();
|
||||
|
||||
return content.html();
|
||||
return result;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue