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),
+ };
+};