diff --git a/assets/radar-rules.js b/assets/radar-rules.js
index 0fc904ae97..59aedff580 100644
--- a/assets/radar-rules.js
+++ b/assets/radar-rules.js
@@ -248,6 +248,12 @@
source: '/trending',
target: '/github/trending/:since',
},
+ {
+ title: 'Trending',
+ docs: 'https://docs.rsshub.app/programming.html#github',
+ source: '/topics',
+ target: '/github/topics/:name/:qs?',
+ },
{
title: '仓库 Issue',
docs: 'https://docs.rsshub.app/programming.html#github',
diff --git a/docs/en/programming.md b/docs/en/programming.md
index e388ff8bc2..5a047117e3 100644
--- a/docs/en/programming.md
+++ b/docs/en/programming.md
@@ -37,6 +37,20 @@ GitHub provides some official RSS feeds:
+### Topics
+
+
+
+| Parameter | Description | Values |
+| ---- | ---- | ---- |
+| `l` | Language | For instance `php`, which can be found in the URL of the corresponding [Topics page](https://github.com/topics/framework?l=php) |
+| `o` | Sorting Order | `asc`, `desc` |
+| `s` | Sorting Criteria | `stars`, `forks`, `updated` |
+
+For instance, the `/github/topics/framework/l=php&o=desc&s=stars` route will generate the RSS feed corresponding to this [page](https://github.com/topics/framework?l=php&o=desc&s=stars).
+
+
+
### Repo Issues
diff --git a/docs/programming.md b/docs/programming.md
index 493aa2bfb8..a12794e21b 100644
--- a/docs/programming.md
+++ b/docs/programming.md
@@ -93,6 +93,20 @@ GitHub 官方也提供了一些 RSS:
+### Topics
+
+
+
+| 参数名 | 描述 | 可选值 |
+| ------ | -------- | ----------------------------------------------------------------------------------------- |
+| `l` | 编程语言 | 例如 `php`,可以在相关 [Topics 页](https://github.com/topics/framework?l=php) URL 中找到 |
+| `o` | 排序方法 | `asc`(升序)
`desc`(降序) |
+| `s` | 排序标准 | `stars`(按 star 数量排序)
`forks`(按 fork 数量排序)
`updated`(按更新日期排序) |
+
+例如 `/github/topics/framework/l=php&o=desc&s=stars` 会生成对应[此页面](https://github.com/topics/framework?l=php&o=desc&s=stars)的 RSS。
+
+
+
### 仓库 Issues
diff --git a/lib/router.js b/lib/router.js
index 885c193a35..8eb98ff1fd 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -307,6 +307,7 @@ router.get('/github/branches/:user/:repo', require('./routes/github/branches'));
router.get('/github/file/:user/:repo/:branch/:filepath+', require('./routes/github/file'));
router.get('/github/starred_repos/:user', require('./routes/github/starred_repos'));
router.get('/github/contributors/:user/:repo/:order?/:anon?', require('./routes/github/contributors'));
+router.get('/github/topics/:name/:qs?', require('./routes/github/topic'));
// f-droid
router.get('/fdroid/apprelease/:app', require('./routes/fdroid/apprelease'));
diff --git a/lib/routes/github/topic.js b/lib/routes/github/topic.js
new file mode 100644
index 0000000000..55287fddac
--- /dev/null
+++ b/lib/routes/github/topic.js
@@ -0,0 +1,25 @@
+const cheerio = require('cheerio');
+const got = require('@/utils/got');
+
+module.exports = async (ctx) => {
+ const link = `https://github.com/topics/${ctx.params.name}?${ctx.params.qs}`;
+ const { data } = await got(link);
+ const $ = cheerio.load(data);
+
+ ctx.state.data = {
+ title: $('title').text(),
+ link,
+ item: $('article.my-4')
+ .map((_, item) => {
+ item = $(item);
+
+ const title = $(item.find('h1 a').get(1)).attr('href').slice(1);
+ const author = title.split('/')[0];
+ const description = `${item.find('div.border-bottom > div > p + div').text()}`;
+ const link = `https://github.com/${title}`;
+
+ return { title, author, description, link };
+ })
+ .get(),
+ };
+};