diff --git a/docs/README.md b/docs/README.md index dd52ebc7c..f0ad4847a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2049,16 +2049,14 @@ Category 列表: ### 纽约时报 - - -::: tip 提示 - -由于众所周知的原因,文章内的图片在中国大陆可能无法正常显示。 - -::: + 通过提取文章全文,以提供比官方源更佳的阅读体验。 +| 默认中文 | 中英对照 | 英文 | +| -------- | -------- | ---- | +| (空) | dual | en | + @@ -2099,12 +2097,6 @@ Category 列表: -::: 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 提示 - -由于众所周知的原因,文章内的图片在中国大陆可能无法正常显示。 - -::: - 通过提取文章全文,以提供比官方源更佳的阅读体验。 diff --git a/lib/router.js b/lib/router.js index 9e5ffb8cb..9e9e35b0a 100644 --- a/lib/router.js +++ b/lib/router.js @@ -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 diff --git a/lib/routes/nytimes/index.js b/lib/routes/nytimes/index.js index 4205732c3..37f0ec62d 100644 --- a/lib/routes/nytimes/index.js +++ b/lib/routes/nytimes/index.js @@ -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, }; }; diff --git a/lib/routes/nytimes/morning_post.js b/lib/routes/nytimes/morning_post.js index f7d15d8ff..065e32dda 100644 --- a/lib/routes/nytimes/morning_post.js +++ b/lib/routes/nytimes/morning_post.js @@ -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); }); diff --git a/lib/routes/nytimes/utils.js b/lib/routes/nytimes/utils.js index 6ffe6bcaa..8f4c3758b 100644 --- a/lib/routes/nytimes/utils.js +++ b/lib/routes/nytimes/utils.js @@ -1,27 +1,79 @@ const cheerio = require('cheerio'); -const ProcessFeed = (data) => { +const ProcessImage = ($, e) => { + const photo = $(e).find('figure'); + + let cover = `

`; + + const caption = $(e).find('figcaption'); + + cover += `${$(caption[0]) + .text() + .trim()}
`; + + 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 = {