diff --git a/docs/programming.md b/docs/programming.md
index c1b814cdb..5402fc16d 100644
--- a/docs/programming.md
+++ b/docs/programming.md
@@ -367,6 +367,7 @@ GitHub 官方也提供了一些 RSS:
| xxiaobian |
+
### 数字型账号用户博客
@@ -377,6 +378,10 @@ GitHub 官方也提供了一些 RSS:
+### 问答主题
+
+
+
## 看雪
### 论坛
diff --git a/lib/router.js b/lib/router.js
index eafd85ee7..72b1c6b22 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -420,6 +420,7 @@ router.get('/linkedkeeper/:type/:id?', require('./routes/linkedkeeper/index'));
router.get('/oschina/news/:category?', require('./routes/oschina/news'));
router.get('/oschina/user/:id', require('./routes/oschina/user'));
router.get('/oschina/u/:id', require('./routes/oschina/u'));
+router.get('/oschina/topic/:topic', require('./routes/oschina/topic'));
// 安全客
router.get('/aqk/vul', require('./routes/aqk/vul'));
diff --git a/lib/routes/oschina/topic.js b/lib/routes/oschina/topic.js
new file mode 100644
index 000000000..413b592e8
--- /dev/null
+++ b/lib/routes/oschina/topic.js
@@ -0,0 +1,54 @@
+const url = require('url');
+const got = require('@/utils/got');
+const date = require('@/utils/date');
+const cheerio = require('cheerio');
+
+async function load(link) {
+ const res = await got({
+ method: 'get',
+ url: link,
+ });
+ const content = cheerio.load(res.data);
+ content('.ad-wrap').remove();
+ return content;
+}
+
+module.exports = async (ctx) => {
+ const topic = ctx.params.topic;
+ const topicUrl = `https://www.oschina.net/question/topic/${topic}?show=time`;
+
+ const $ = await load(topicUrl);
+ const topicName = $('.topic-info > .topic-header > h3').text();
+ const list = $('#questionList').find('.question-item');
+ const count = [];
+ for (let i = 0; i < Math.min(list.length, 10); i++) {
+ count.push(i);
+ }
+
+ const resultItem = await Promise.all(
+ count.map(async (i) => {
+ const each = $(list[i]);
+ const originalUrl = each.find('.header').attr('href');
+
+ const item = {
+ title: each.find('.header').text(),
+ link: url.resolve('https://www.oschina.net', encodeURI(originalUrl)),
+ author: date(each.find('.extra > .list > .item:nth-of-type(1)').text()),
+ pubDate: date(each.find('.extra > .list > .item:nth-of-type(2)').text()),
+ };
+
+ item.description = await ctx.cache.tryGet(originalUrl, async () => {
+ const content = await load(item.link);
+ return content('#articleContent').html();
+ });
+
+ return Promise.resolve(item);
+ })
+ );
+
+ ctx.state.data = {
+ title: `开源中国-${topicName}`,
+ link: topicUrl,
+ item: resultItem,
+ };
+};