diff --git a/docs/en/traditional-media.md b/docs/en/traditional-media.md index eaf751b336..94af9d6673 100644 --- a/docs/en/traditional-media.md +++ b/docs/en/traditional-media.md @@ -37,6 +37,12 @@ Refer to [Boston.com's feed page](https://www.boston.com/rss-feeds) for tags. Fo +## CBC + +Provide full article RSS for CBC topics. + + + ## Chicago Tribune ### News diff --git a/docs/traditional-media.md b/docs/traditional-media.md index 6d686949b5..cc927561e6 100644 --- a/docs/traditional-media.md +++ b/docs/traditional-media.md @@ -43,6 +43,12 @@ pageClass: routes +## CBC + +通过提取文章全文,以提供比官方源更佳的阅读体验。 + + + ## Chicago Tribune ### 新闻 diff --git a/lib/router.js b/lib/router.js index 1391d2e55a..c4edf13c72 100644 --- a/lib/router.js +++ b/lib/router.js @@ -2363,6 +2363,9 @@ router.get('/gbcc/trust', require('./routes/gbcc/trust')); // Associated Press router.get('/apnews/topics/:topic', require('./routes/apnews/topics')); +// CBC +router.get('/cbc/topics/:topic?', require('./routes/cbc/topics')); + // discuz router.get('/discuz/:ver([7|x])/:cid([0-9]{2})/:link(.*)', require('./routes/discuz/discuz')); router.get('/discuz/:ver([7|x])/:link(.*)', require('./routes/discuz/discuz')); diff --git a/lib/routes/cbc/topics.js b/lib/routes/cbc/topics.js new file mode 100644 index 0000000000..44281094fd --- /dev/null +++ b/lib/routes/cbc/topics.js @@ -0,0 +1,72 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); + +module.exports = async (ctx) => { + const baseUrl = 'https://www.cbc.ca'; + const topic = ctx.params.topic || ''; + const url = `${baseUrl}/news/${topic.replace('-', '/')}`; + + const response = await got({ + method: 'get', + url: url, + }); + + const data = response.data; + + const $ = cheerio.load(data); + const links = []; + + function pushLinks(index, item) { + const link = item.attribs.href; + if (link.startsWith('/')) { + links.push(baseUrl + link); + } + } + + $('a.contentWrapper').each(pushLinks); + $('a.card').each(pushLinks); + + const out = await Promise.all( + links.map(async (link) => { + const [title, author, pubDate, description] = await ctx.cache.tryGet(link, async () => { + const result = await got.get(link); + + const $ = cheerio.load(result.data); + + const head = JSON.parse($('script[type="application/ld+json"]').html()); + if (!head) { + return []; + } + + const title = head.headline; + let author = ''; + if (head.author) { + author = head.author.map((author) => author.name).join(' & '); + } + const pubDate = head.datePublished; + const description = $('div.storyWrapper').html(); + + return [title, author, pubDate, description]; + }); + + if (!title) { + return Promise.resolve(undefined); + } + + const item = { + title: title, + description: description, + pubDate: pubDate, + link: link, + author: author, + }; + return Promise.resolve(item); + }) + ); + + ctx.state.data = { + title: $('title').text(), + link: url, + item: out.filter((x) => x), + }; +};