diff --git a/docs/other.md b/docs/other.md
index 2315bbb9e9..23702f51c0 100644
--- a/docs/other.md
+++ b/docs/other.md
@@ -550,3 +550,11 @@ type 为 all 时,category 参数不支持 cost 和 free
+
+## 财新博客
+
+
+
+通过提取文章全文,以提供比官方源更佳的阅读体验.
+
+
diff --git a/lib/router.js b/lib/router.js
index 54eb997347..f762681baa 100755
--- a/lib/router.js
+++ b/lib/router.js
@@ -405,6 +405,8 @@ router.get('/mihoyo/bh2/:type', require('./routes/mihoyo/bh2'));
// 央视新闻
router.get('/cctv/:category', require('./routes/cctv/category'));
+// 财新博客
+router.get('/caixin/blog/:column', require('./routes/caixin/blog'));
// 财新
router.get('/caixin/:column/:category', require('./routes/caixin/category'));
diff --git a/lib/routes/caixin/blog.js b/lib/routes/caixin/blog.js
new file mode 100644
index 0000000000..bf48d86d6b
--- /dev/null
+++ b/lib/routes/caixin/blog.js
@@ -0,0 +1,60 @@
+const axios = require('../../utils/axios');
+const cheerio = require('cheerio');
+const { ua } = require('../../config');
+const Parser = require('rss-parser');
+const parser = new Parser({ headers: { 'User-Agent': ua } });
+
+async function load(link, need_feed_description) {
+ const response = await axios.get(link);
+ const $ = cheerio.load(response.data);
+ const article = $('.blog_content').removeAttr('style');
+ article.find('img').removeAttr('style');
+ article
+ .find('div')
+ // Non-breaking space U+00A0, ` ` in html
+ // element.children[0].data === $(element, article).text()
+ .filter((_, element) => element.children[0].data === String.fromCharCode(160))
+ .remove();
+ const description = article.html();
+
+ const item = { description };
+
+ if (need_feed_description) {
+ const author = $('div.widget.author_detail p:nth-child(2)');
+ // workaround to split author name and author article
+ const author_name = author.find('strong');
+ author_name.text(author_name.text() + ',');
+ item.feed_description = author.text();
+ }
+ return item;
+}
+
+module.exports = async (ctx) => {
+ const { column } = ctx.params;
+ const link = `http://${column}.blog.caixin.com`;
+ const feed_url = `${link}/feed`;
+ const feed = await parser.parseURL(feed_url);
+
+ const title = `财新博客 - ${/[^»]*$/.exec(feed.title)[0]}`;
+
+ const items = await Promise.all(
+ feed.items.slice(0, 10).map(async (item, index) => {
+ const link = item.link;
+ const single = {
+ title: item.title,
+ pubDate: item.pubDate,
+ link,
+ author: item['dc:creator'],
+ };
+ const other = await ctx.cache.tryGet(link, async () => await load(link, index === 0));
+ return Promise.resolve(Object.assign({}, single, other));
+ })
+ );
+
+ ctx.state.data = {
+ title,
+ link,
+ description: items[0].feed_description,
+ item: items,
+ };
+};