diff --git a/lib/router.js b/lib/router.js
index 0eb14c176f0854..8c5fcbc70eb664 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -775,11 +775,6 @@ router.get('/paidai/news', lazyloadRouteHandler('./routes/paidai/news'));
// 漫画db
router.get('/manhuadb/comics/:id', lazyloadRouteHandler('./routes/manhuadb/comics'));
-// Hpoi 手办维基
-router.get('/hpoi/info/:type?', lazyloadRouteHandler('./routes/hpoi/info'));
-router.get('/hpoi/:category/:words', lazyloadRouteHandler('./routes/hpoi'));
-router.get('/hpoi/user/:user_id/:caty', lazyloadRouteHandler('./routes/hpoi/user'));
-
// 通用CurseForge
router.get('/curseforge/:gameid/:catagoryid/:projectid/files', lazyloadRouteHandler('./routes/curseforge/generalfiles'));
diff --git a/lib/routes/hpoi/index.js b/lib/routes/hpoi/index.js
deleted file mode 100644
index faedc1f75a7405..00000000000000
--- a/lib/routes/hpoi/index.js
+++ /dev/null
@@ -1,47 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-
-const host = 'https://www.hpoi.net';
-
-const MAPs = {
- charactar: {
- url: `${host}/hobby/all?charactar={words}&order=release`,
- title: '角色手办',
- },
- works: {
- url: `${host}/hobby/all?works={words}&order=release`,
- title: '作品手办',
- },
-};
-
-module.exports = async (ctx) => {
- const category = ctx.params && ctx.params.category;
- const words = ctx.params && ctx.params.words;
- const link = MAPs[category].url.replace(/{words}/, words);
- const response = await got({
- method: 'get',
- url: link,
- headers: {
- Referer: host,
- },
- });
- const $ = cheerio.load(response.data);
- ctx.state.data = {
- title: 'Hpoi 手办维基' + ' - ' + $(`#${category}`).text().trim(),
- link,
- item: $('.bs-glyphicons-list .detail-grid')
- .map((_index, _item) => {
- _item = $(_item);
- return {
- title: _item.find('.detail-grid-title').text(),
- link: host + '/' + _item.find('.detail-grid-title a').attr('href'),
- description: `${_item.find('.detail-grid-info span').eq(0).text()}
${_item.find('.detail-grid-info span').eq(1).text()}
${_item
- .find('.detail-grid-info span')
- .eq(2)
- .text()}`,
- };
- })
- .get()
- .reverse(),
- };
-};
diff --git a/lib/routes/hpoi/user.js b/lib/routes/hpoi/user.js
deleted file mode 100644
index abcd0340012e74..00000000000000
--- a/lib/routes/hpoi/user.js
+++ /dev/null
@@ -1,37 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-
-const root_url = 'https://www.hpoi.net';
-
-module.exports = async (ctx) => {
- const { user_id, caty } = ctx.params;
-
- const url = `${root_url}/user/${user_id}/hobby?order=actionDate&favState=${caty}&view=5&category=100&sortType=2`;
- const response = await got({
- method: 'get',
- url,
- });
-
- const $ = cheerio.load(response.data);
- const list = $('#content > div.action-box div.action-detail')
- .map((_, item) => {
- item = $(item);
- const img = item.find('div.list-5-left > a > img').attr('src');
- const a = item.find('div.list-5-right > a.action-title');
- return {
- title: a.text(),
- link: 'https://www.hpoi.net/' + a.attr('href'),
- description: `
制作:${item.find('.badge').eq(0).text()}
发售:${item.find('.badge').eq(1).text()}`,
- };
- })
- .get();
-
- const title = $('div.col-md-15.col-sm-15 > div:nth-child(2)').text() + $('.navbar-nav .active').eq(0).text() + '的手办';
-
- ctx.state.data = {
- title,
- link: url,
- item: list,
- allowEmpty: true,
- };
-};
diff --git a/lib/v2/hpoi/all.js b/lib/v2/hpoi/all.js
new file mode 100644
index 00000000000000..593123a1109f22
--- /dev/null
+++ b/lib/v2/hpoi/all.js
@@ -0,0 +1,3 @@
+const { ProcessFeed } = require('./utils');
+
+module.exports = async (ctx) => (ctx.state.data = await ProcessFeed('all', 0, ctx.params.order));
diff --git a/lib/v2/hpoi/bannerItem.js b/lib/v2/hpoi/bannerItem.js
new file mode 100644
index 00000000000000..2a4df24bbb4caa
--- /dev/null
+++ b/lib/v2/hpoi/bannerItem.js
@@ -0,0 +1,26 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+module.exports = async (ctx) => {
+ const link = 'https://www.hpoi.net/bannerItem/list?categoryId=0&bannerItemType=0&subType=0&page=1';
+ const response = await got({
+ method: 'get',
+ url: link,
+ });
+ const $ = cheerio.load(response.data);
+ ctx.state.data = {
+ title: `Hpoi 手办维基 - 热门推荐`,
+ link,
+ item: $('#content .item')
+ .map((_index, _item) => {
+ _item = $(_item);
+ return {
+ title: _item.find('.title').text(),
+ link: 'https://www.hpoi.net/' + _item.find('a').attr('href'),
+ description: ``,
+ pubDate: new Date(_item.find('.time').text().replace('发布时间:', '')).toUTCString(),
+ };
+ })
+ .get(),
+ };
+};
diff --git a/lib/v2/hpoi/character.js b/lib/v2/hpoi/character.js
new file mode 100644
index 00000000000000..5e6e67e6a2087a
--- /dev/null
+++ b/lib/v2/hpoi/character.js
@@ -0,0 +1,3 @@
+const { ProcessFeed } = require('./utils');
+
+module.exports = async (ctx) => (ctx.state.data = await ProcessFeed('character', ctx.params.id, ctx.params.order));
diff --git a/lib/routes/hpoi/info.js b/lib/v2/hpoi/info.js
similarity index 100%
rename from lib/routes/hpoi/info.js
rename to lib/v2/hpoi/info.js
diff --git a/lib/v2/hpoi/maintainer.js b/lib/v2/hpoi/maintainer.js
new file mode 100644
index 00000000000000..2dccb10bcce6ea
--- /dev/null
+++ b/lib/v2/hpoi/maintainer.js
@@ -0,0 +1,8 @@
+module.exports = {
+ '/info/:type?': ['sanmmm DIYgod'],
+ '/items/all/:order?': ['DIYgod'],
+ '/items/character/:id/:order?': ['DIYgod'],
+ '/items/work/:id/:order?': ['DIYgod'],
+ '/user/:user_id/:caty': ['DIYgod', 'luyuhuang'],
+ '/bannerItem': ['DIYgod'],
+};
diff --git a/lib/v2/hpoi/radar.js b/lib/v2/hpoi/radar.js
new file mode 100644
index 00000000000000..53a25bc55a498e
--- /dev/null
+++ b/lib/v2/hpoi/radar.js
@@ -0,0 +1,37 @@
+module.exports = {
+ 'hpoi.net': {
+ _name: 'Hpoi手办维基',
+ www: [
+ {
+ title: '情报',
+ docs: 'https://docs.rsshub.app/routes/anime#hpoi-shou-ban-wei-ji',
+ source: ['/user/home'],
+ target: '/hpoi/info/all',
+ },
+ {
+ title: '所有周边',
+ docs: 'https://docs.rsshub.app/routes/anime#hpoi-shou-ban-wei-ji',
+ source: ['/hobby/all'],
+ target: '/hpoi/items/all',
+ },
+ {
+ title: '角色周边',
+ docs: 'https://docs.rsshub.app/routes/anime#hpoi-shou-ban-wei-ji',
+ },
+ {
+ title: '作品周边',
+ docs: 'https://docs.rsshub.app/routes/anime#hpoi-shou-ban-wei-ji',
+ },
+ {
+ title: '用户动态',
+ docs: 'https://docs.rsshub.app/routes/anime#hpoi-shou-ban-wei-ji',
+ },
+ {
+ title: '热门推荐',
+ docs: 'https://docs.rsshub.app/routes/anime#hpoi-shou-ban-wei-ji',
+ source: ['/bannerItem/list'],
+ target: '/hpoi/bannerItem',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/hpoi/router.js b/lib/v2/hpoi/router.js
new file mode 100644
index 00000000000000..bcbe542fbd16af
--- /dev/null
+++ b/lib/v2/hpoi/router.js
@@ -0,0 +1,8 @@
+module.exports = function (router) {
+ router.get('/info/:type?', require('./info'));
+ router.get('/items/all/:order?', require('./all'));
+ router.get('/items/character/:id/:order?', require('./character'));
+ router.get('/items/work/:id/:order?', require('./work'));
+ router.get('/user/:user_id/:caty', require('./user'));
+ router.get('/bannerItem', require('./bannerItem'));
+};
diff --git a/lib/v2/hpoi/user.js b/lib/v2/hpoi/user.js
new file mode 100644
index 00000000000000..adcf14b68fae58
--- /dev/null
+++ b/lib/v2/hpoi/user.js
@@ -0,0 +1,43 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+const root_url = 'https://www.hpoi.net';
+
+const titleMap = {
+ want: '想买',
+ preorder: '预定',
+ buy: '已入',
+ care: '关注',
+ resell: '有过',
+};
+
+module.exports = async (ctx) => {
+ const { user_id, caty } = ctx.params;
+
+ const url = `${root_url}/user/${user_id}/hobby?order=actionDate&view=2&favState=${caty}`;
+ const response = await got({
+ method: 'get',
+ url,
+ });
+
+ const $ = cheerio.load(response.data);
+ const list = $('.collect-hobby-list-small')
+ .map((_, item) => {
+ item = $(item);
+ return {
+ title: titleMap[caty] + ': ' + item.find('.name').text(),
+ link: 'https://www.hpoi.net/' + item.find('.name').attr('href'),
+ description: `
${item.find('.pay').text()}
${item.find('.score').text()}`,
+ };
+ })
+ .get();
+
+ const title = $('.hpoi-collect-head .info p').eq(0).text() + '的手办 - ' + titleMap[caty];
+
+ ctx.state.data = {
+ title,
+ link: url,
+ item: list,
+ allowEmpty: true,
+ };
+};
diff --git a/lib/v2/hpoi/utils.js b/lib/v2/hpoi/utils.js
new file mode 100644
index 00000000000000..a3715b59a7a512
--- /dev/null
+++ b/lib/v2/hpoi/utils.js
@@ -0,0 +1,49 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+const host = 'https://www.hpoi.net';
+
+const MAPs = {
+ character: {
+ url: `${host}/hobby/all?order={order}&r18=-1&charactar={id}`,
+ title: '角色周边',
+ },
+ work: {
+ url: `${host}/hobby/all?order={order}&r18=-1&works={id}`,
+ title: '作品周边',
+ },
+ all: {
+ url: `${host}/hobby/all?order={order}&r18=-1`,
+ title: '全部周边',
+ },
+};
+
+const ProcessFeed = async (type, id, order) => {
+ const link = MAPs[type].url.replace(/{id}/, id).replace(/{order}/, order || 'add');
+ const response = await got({
+ method: 'get',
+ url: link,
+ headers: {
+ Referer: host,
+ },
+ });
+ const $ = cheerio.load(response.data);
+ return {
+ title: `Hpoi 手办维基 - ${MAPs[type].title}${id ? ` ${id}` : ''}`,
+ link,
+ item: $('.hpoi-glyphicons-list li')
+ .map((_index, _item) => {
+ _item = $(_item);
+ return {
+ title: _item.find('.hpoi-detail-grid-title a').text(),
+ link: host + '/' + _item.find('a').attr('href'),
+ description: `${_item.find('.hpoi-detail-grid-info').html().replace(/span>/g, 'p>')}`,
+ };
+ })
+ .get(),
+ };
+};
+
+module.exports = {
+ ProcessFeed,
+};
diff --git a/lib/v2/hpoi/work.js b/lib/v2/hpoi/work.js
new file mode 100644
index 00000000000000..5b9c1980b9cc62
--- /dev/null
+++ b/lib/v2/hpoi/work.js
@@ -0,0 +1,3 @@
+const { ProcessFeed } = require('./utils');
+
+module.exports = async (ctx) => (ctx.state.data = await ProcessFeed('work', ctx.params.id, ctx.params.order));
diff --git a/website/docs/routes/anime.mdx b/website/docs/routes/anime.mdx
index c7c1708ca7341a..d6710256d557fc 100644
--- a/website/docs/routes/anime.mdx
+++ b/website/docs/routes/anime.mdx
@@ -279,22 +279,42 @@
| all | hobby | model |
-### 浏览周边 {#hpoi-shou-ban-wei-ji-liu-lan-zhou-bian}
+### 所有周边 {#hpoi-shou-ban-wei-ji-suo-you-zhou-bian}
-
- | 角色手办 | 作品手办 |
- | --------- | -------- |
- | charactar | works |
+
+ | 发售 | 入库 | 总热度 | 一周热度 | 一天热度 | 评价 |
+ | ------- | ---- | ------ | -------- | -------- | ------ |
+ | release | add | hits | hits7Day | hitsDay | rating |
+
+
+### 角色周边 {#hpoi-shou-ban-wei-ji-jue-se-zhou-bian}
+
+
+ | 发售 | 入库 | 总热度 | 一周热度 | 一天热度 | 评价 |
+ | ------- | ---- | ------ | -------- | -------- | ------ |
+ | release | add | hits | hits7Day | hitsDay | rating |
+
+
+### 作品周边 {#hpoi-shou-ban-wei-ji-zuo-pin-zhou-bian}
+
+
+ | 发售 | 入库 | 总热度 | 一周热度 | 一天热度 | 评价 |
+ | ------- | ---- | ------ | -------- | -------- | ------ |
+ | release | add | hits | hits7Day | hitsDay | rating |
### 用户动态 {#hpoi-shou-ban-wei-ji-yong-hu-dong-tai}
-
+
| 想买 | 预定 | 已入 | 关注 | 有过 |
| ---- | -------- | ---- | ---- | ------ |
| want | preorder | buy | care | resell |
+### 热门推荐 {#hpoi-shou-ban-wei-ji-re-men-tui-jian}
+
+
+
## IDOLY PRIDE 偶像荣耀 {#idoly-pride-ou-xiang-rong-yao}
### News {#idoly-pride-ou-xiang-rong-yao-news}