diff --git a/docs/bbs.md b/docs/bbs.md
index 36af74eb57..fbcfe04305 100644
--- a/docs/bbs.md
+++ b/docs/bbs.md
@@ -208,6 +208,42 @@ pageClass: routes
+### 分类
+
+
+
+| 分类 | 名称 |
+| ------------ | -------- |
+| NBA 论坛 | nba |
+| CBA 论坛 | cba |
+| 运动和装备 | gear |
+| 国际足球论坛 | soccer |
+| 中国足球论坛 | csl |
+| 综合体育 | sports |
+| 步行街 | gambia |
+| 彩票中心 | lottery |
+| 自建版块 | boards |
+| 虎扑社团 | group |
+| 站务管理 | feedback |
+
+更多参见 [虎扑社区版块目录](https://bbs.hupu.com/boards.php) 左侧导航栏各板块分类页
+
+
+
+### 子站
+
+
+
+| 子站 | 名称 |
+| -------- | ------------ |
+| NBA | nba |
+| 国际足球 | soccer |
+| 中国足球 | soccer-china |
+| CBA | cba |
+| 电竞 | gg |
+
+
+
## 看雪
### 论坛
diff --git a/lib/router.js b/lib/router.js
index 1485669e45..42f00434e3 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -1344,6 +1344,8 @@ router.get('/segmentfault/user/:name', require('./routes/segmentfault/user'));
// 虎扑
router.get('/hupu/bxj/:id/:order?', require('./routes/hupu/bbs'));
router.get('/hupu/bbs/:id/:order?', require('./routes/hupu/bbs'));
+router.get('/hupu/all/:caty', require('./routes/hupu/all'));
+router.get('/hupu/dept/:dept', require('./routes/hupu/dept'));
// 牛客网
router.get('/nowcoder/discuss/:type/:order', require('./routes/nowcoder/discuss'));
diff --git a/lib/routes/hupu/all.js b/lib/routes/hupu/all.js
new file mode 100644
index 0000000000..4099f68b44
--- /dev/null
+++ b/lib/routes/hupu/all.js
@@ -0,0 +1,54 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+module.exports = async (ctx) => {
+ const rootUrl = 'https://bbs.hupu.com';
+ const currentUrl = `${rootUrl}/all-${ctx.params.caty}`;
+
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+ const $ = cheerio.load(response.data);
+
+ const list = $('div.list ul li')
+ .slice(0, 20)
+ .map((_, item) => {
+ item = $(item);
+ const a = item.find('span.textSpan a[title]');
+ return {
+ title: a.attr('title'),
+ link: `${rootUrl}${a.attr('href')}`,
+ };
+ })
+ .get();
+
+ const items = await Promise.all(
+ list.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ try {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+ const content = cheerio.load(detailResponse.data);
+
+ item.description = content('div.quote-content').html();
+ item.author = content('div.author div.left a.u').eq(0).text();
+ item.pubDate = new Date(content('span.stime').eq(0).text() + ' GMT+8').toUTCString();
+
+ return item;
+ } catch (error) {
+ return Promise.resolve('');
+ }
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: $('title').text(),
+ link: currentUrl,
+ item: items,
+ };
+};
diff --git a/lib/routes/hupu/dept.js b/lib/routes/hupu/dept.js
new file mode 100644
index 0000000000..4d7f5e85c2
--- /dev/null
+++ b/lib/routes/hupu/dept.js
@@ -0,0 +1,67 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+module.exports = async (ctx) => {
+ let currentUrl = '';
+ if (ctx.params.dept === 'soccer-china') {
+ currentUrl = `https://soccer.hupu.com/china`;
+ } else {
+ currentUrl = `https://${ctx.params.dept}.hupu.com`;
+ }
+
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+ const $ = cheerio.load(response.data);
+
+ const query = {
+ nba: 'div.list-item',
+ soccer: 'div.list-item',
+ 'soccer-china': '#focusNews',
+ cba: '#focusNews',
+ gg: 'div.fouce-news',
+ };
+
+ const list = $(query[ctx.params.dept])
+ .find('a[href!=""]')
+ .slice(0, 20)
+ .map((_, item) => {
+ item = $(item);
+
+ return {
+ title: item.text(),
+ link: item.attr('href'),
+ };
+ })
+ .get();
+
+ const items = await Promise.all(
+ list.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ try {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+ const content = cheerio.load(detailResponse.data);
+
+ item.description = content('div.quote-content').html();
+ item.author = content('div.author div.left a.u').eq(0).text();
+ item.pubDate = new Date(content('span.stime').eq(0).text() + ' GMT+8').toUTCString();
+
+ return item;
+ } catch (error) {
+ return Promise.resolve('');
+ }
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: $('title').text(),
+ link: currentUrl,
+ item: items,
+ };
+};