diff --git a/docs/en/traditional-media.md b/docs/en/traditional-media.md
index 98a3bb388e..02891c97a1 100644
--- a/docs/en/traditional-media.md
+++ b/docs/en/traditional-media.md
@@ -81,3 +81,21 @@ Provides a better reading experience (full text articles) over the official one.
| (空) | dual | en | dual-traditionalchinese | traditionalchinese |
+
+## Yahoo
+
+### News
+
+
+
+`Region`
+| Hong Kong | Taiwan | US |
+| -- | -- | -- |
+| hk | tw | en |
+
+`Category`
+| All | World | Business | Entertainment | Sports | Health |
+| -- | -- | -- | -- | -- | -- |
+| (Empty) | world | business | entertainment | sports | health |
+
+
diff --git a/docs/traditional-media.md b/docs/traditional-media.md
index 1099c28d7b..58c51cb692 100644
--- a/docs/traditional-media.md
+++ b/docs/traditional-media.md
@@ -96,6 +96,24 @@ Solidot 提供的 feed:
+## Yahoo
+
+### 新聞
+
+
+
+`地区`
+| 香港 | 台灣 | 美國 |
+| -- | -- | -- |
+| hk | tw | en |
+
+`类別`
+| 新聞總集 | 兩岸國際 | 財經 | 娛樂 | 體育 | 健康 |
+| -- | -- | -- | -- | -- | -- |
+| (空) | world | business | entertainment | sports | health |
+
+
+
## 半月谈
### 板块
diff --git a/lib/router.js b/lib/router.js
index 3c2cc5fbd6..ef58964b96 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -2101,6 +2101,9 @@ router.get('/mlog-club/projects', require('./routes/mlog-club/projects'));
// Chrome 网上应用店
router.get('/chrome/webstore/extensions/:id', require('./routes/chrome/extensions'));
+// yahoo
+router.get('/yahoo-news/:region/:category?', require('./routes/yahoo-news/index'));
+
// 白鲸出海
router.get('/baijing', require('./routes/baijing'));
diff --git a/lib/routes/yahoo-news/index.js b/lib/routes/yahoo-news/index.js
new file mode 100755
index 0000000000..9875cc7aa6
--- /dev/null
+++ b/lib/routes/yahoo-news/index.js
@@ -0,0 +1,44 @@
+const got = require('@/utils/got');
+const parser = require('@/utils/rss-parser');
+const cheerio = require('cheerio');
+
+module.exports = async (ctx) => {
+ const region = ctx.params.region === 'en' ? '' : ctx.params.region.toLowerCase() + '.';
+ const category = ctx.params.category ? ctx.params.category.toLowerCase() : '';
+ const rssUrl = `https://${region}news.yahoo.com/rss/${category}`;
+ const feed = await parser.parseURL(rssUrl);
+ const title = feed.title;
+ const link = feed.link;
+ const description = feed.description;
+ const filteredItems = feed.items.filter((item) => !item.link.includes('promotions') && item.link.includes('yahoo.com'));
+ const items = await Promise.all(
+ filteredItems.map(async (item) => {
+ const description = await ctx.cache.tryGet(item.link, async () => {
+ const response = await got({
+ method: 'get',
+ url: item.link,
+ });
+
+ const $ = cheerio.load(response.data);
+ const $descriptionRoot = cheerio.load('
');
+ $descriptionRoot('div.img-root').append($('article img'));
+ $descriptionRoot('div.content-root').append($('article p').removeAttr('content'));
+ return $descriptionRoot.html();
+ });
+ const single = {
+ title: item.title,
+ description,
+ pubDate: item.pubDate,
+ link: item.link,
+ };
+ return Promise.resolve(single);
+ })
+ );
+
+ ctx.state.data = {
+ title,
+ link,
+ description,
+ item: items,
+ };
+};