diff --git a/docs/reading.md b/docs/reading.md
index ec0f6895b..e69390e4b 100644
--- a/docs/reading.md
+++ b/docs/reading.md
@@ -180,11 +180,11 @@ For instance, when doing search at and you get url
+
-### 排行榜
+### 排行
-
+
| 文章点击排行 | 最近更新文章 | 文章推荐排行 |
| ------------ | ------------ | ------------ |
@@ -194,11 +194,10 @@ For instance, when doing search at and you get url
+
-| 论文 | 时评 | 随笔 | 演讲 | 访谈 | 著作 | 读书 | 史论 | 译作 | 诗歌 | 书信 | 科学 |
-| ---- | ---- | ----- | ---- | ----- | ------ | ----- | ------ | ----- | ----- | ------ | ----- |
-| lunw | ship | shuib | yanj | fangt | zhuanz | dushu | shilun | yizuo | shige | shuxin | kexue |
+| 论文 | 时评 | 随笔 | 演讲 | 访谈 | 著作 | 读书 | 史论 | 译作 | 诗歌 | 书信 | 科学 |
+| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
diff --git a/lib/router.js b/lib/router.js
index f4d8021c6..bac7a8344 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -1297,9 +1297,9 @@ router.get('/whalegogo/home', lazyloadRouteHandler('./routes/whalegogo/home'));
router.get('/whalegogo/portal/:type_id/:tagid?', lazyloadRouteHandler('./routes/whalegogo/portal'));
// 爱思想
-router.get('/aisixiang/column/:id', lazyloadRouteHandler('./routes/aisixiang/column'));
-router.get('/aisixiang/ranking/:type?/:range?', lazyloadRouteHandler('./routes/aisixiang/ranking'));
-router.get('/aisixiang/thinktank/:name/:type?', lazyloadRouteHandler('./routes/aisixiang/thinktank'));
+// router.get('/aisixiang/column/:id', lazyloadRouteHandler('./routes/aisixiang/column'));
+// router.get('/aisixiang/ranking/:type?/:range?', lazyloadRouteHandler('./routes/aisixiang/ranking'));
+// router.get('/aisixiang/thinktank/:name/:type?', lazyloadRouteHandler('./routes/aisixiang/thinktank'));
// Hacker News
// router.get('/hackernews/:section/:type?', lazyloadRouteHandler('./routes/hackernews/story'));
diff --git a/lib/routes/aisixiang/column.js b/lib/routes/aisixiang/column.js
deleted file mode 100644
index c864cbb78..000000000
--- a/lib/routes/aisixiang/column.js
+++ /dev/null
@@ -1,37 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const iconv = require('iconv-lite');
-
-const util = require('./utils');
-
-module.exports = async (ctx) => {
- const { id } = ctx.params;
-
- const host = `http://www.aisixiang.com/data/search.php?lanmu=${id}`;
-
- const response = await got.get(host, {
- responseType: 'buffer',
- });
-
- response.data = iconv.decode(response.data, 'gbk');
-
- const $ = cheerio.load(response.data);
-
- const list = $('.search_list > ul > li > a:nth-child(2)').slice(0, 10).get();
-
- const columnName = $('.search_list > ul > li:nth-child(1) > a:nth-child(1)').text();
-
- const items = await Promise.all(
- list.map((e) => {
- const link = $(e).attr('href');
- return ctx.cache.tryGet(link, () => util.ProcessFeed(link));
- })
- );
-
- ctx.state.data = {
- title: `爱思想栏目 - ${columnName}`,
- link: host,
- description: `爱思想栏目 - ${columnName}`,
- item: items,
- };
-};
diff --git a/lib/routes/aisixiang/ranking.js b/lib/routes/aisixiang/ranking.js
deleted file mode 100644
index 53341401b..000000000
--- a/lib/routes/aisixiang/ranking.js
+++ /dev/null
@@ -1,37 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const iconv = require('iconv-lite');
-
-const util = require('./utils');
-
-module.exports = async (ctx) => {
- const { type = 1, range = 1 } = ctx.params;
-
- const host = `http://www.aisixiang.com/toplist/index.php?id=${type}&period=${range}`;
-
- const response = await got.get(host, {
- responseType: 'buffer',
- });
-
- response.data = iconv.decode(response.data, 'gbk');
-
- const $ = cheerio.load(response.data);
-
- const list = $('.tops_list > .tips > a').slice(0, 10).get();
-
- const columnName = $('.tops_text > h3')[0].firstChild.nodeValue;
-
- const items = await Promise.all(
- list.map((e) => {
- const link = $(e).attr('href');
- return ctx.cache.tryGet(link, () => util.ProcessFeed(link));
- })
- );
-
- ctx.state.data = {
- title: `爱思想 - ${columnName}`,
- link: host,
- description: `爱思想 - ${columnName}`,
- item: items,
- };
-};
diff --git a/lib/routes/aisixiang/thinktank.js b/lib/routes/aisixiang/thinktank.js
deleted file mode 100644
index 85bb36f04..000000000
--- a/lib/routes/aisixiang/thinktank.js
+++ /dev/null
@@ -1,40 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const iconv = require('iconv-lite');
-const util = require('./utils');
-
-module.exports = async (ctx) => {
- const { name, type = 'lunw' } = ctx.params;
-
- const host = `http://www.aisixiang.com/thinktank/${name}.html`;
-
- const response = await got.get(host, {
- responseType: 'buffer',
- });
- response.data = iconv.decode(response.data, 'gbk');
-
- const $ = cheerio.load(response.data);
-
- const tds = $('td > img').filter(function () {
- return $(this).attr('src') === `images/${type}.gif`;
- });
- if (tds.length === 0) {
- throw `Type Not Found - ${type}`;
- }
-
- const list = tds.parent().next().find('a').slice(0, 5).get();
-
- const items = await Promise.all(
- list.map((e) => {
- const link = $(e).attr('href');
- return ctx.cache.tryGet(link, () => util.ProcessFeed(link));
- })
- );
-
- ctx.state.data = {
- title: $('title').text(),
- link: host,
- description: $('meta[name="description"]').attr('content'),
- item: items,
- };
-};
diff --git a/lib/routes/aisixiang/utils.js b/lib/routes/aisixiang/utils.js
deleted file mode 100644
index 5f87240f2..000000000
--- a/lib/routes/aisixiang/utils.js
+++ /dev/null
@@ -1,39 +0,0 @@
-const cheerio = require('cheerio');
-const iconv = require('iconv-lite');
-const got = require('@/utils/got');
-const date = require('@/utils/date');
-
-const ProcessFeed = async (link) => {
- const id = link.split('/').pop().split('.')[0];
-
- let response;
- response = await got.get(`http://www.aisixiang.com/data/view_json.php?id=${id}`, {
- responseType: 'json',
- });
- const description = response.data.content;
-
- link = `http://www.aisixiang.com${link}`;
- response = await got.get(link, {
- responseType: 'buffer',
- });
-
- response.data = iconv.decode(response.data, 'gbk');
-
- const $ = cheerio.load(response.data);
-
- const title = $('.show_text > h3').text();
-
- const pubDate = date($('.show_text > .info').text().split(':').pop(), 8);
-
- return {
- title: title.split(':')[1] || title,
- author: title.split(':')[0] || '',
- description,
- pubDate,
- link,
- };
-};
-
-module.exports = {
- ProcessFeed,
-};
diff --git a/lib/v2/aisixiang/column.js b/lib/v2/aisixiang/column.js
new file mode 100644
index 000000000..863ce1ccd
--- /dev/null
+++ b/lib/v2/aisixiang/column.js
@@ -0,0 +1,36 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { rootUrl, ProcessFeed } = require('./utils');
+
+module.exports = async (ctx) => {
+ const id = ctx.params.id;
+ const limit = ctx.query.limit ? parseInt(ctx.query.limit) : 30;
+
+ const currentUrl = `${rootUrl}/data/search?column=${id}`;
+
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+
+ const $ = cheerio.load(response.data);
+
+ const title = $('div.article-title a').first().text().replace(/\[|\]/g, '');
+
+ const items = $('div.search_list a[title]')
+ .toArray()
+ .map((item) => {
+ item = $(item);
+
+ return {
+ title: item.text().split(':').pop(),
+ link: new URL(item.attr('href'), rootUrl).href,
+ };
+ });
+
+ ctx.state.data = {
+ title: `爱思想 - ${title}`,
+ link: currentUrl,
+ item: await ProcessFeed(limit, ctx.cache.tryGet, items),
+ };
+};
diff --git a/lib/v2/aisixiang/maintainer.js b/lib/v2/aisixiang/maintainer.js
new file mode 100644
index 000000000..1b6175522
--- /dev/null
+++ b/lib/v2/aisixiang/maintainer.js
@@ -0,0 +1,6 @@
+module.exports = {
+ '/column/:id': ['HenryQW', 'nczitzk'],
+ '/ranking/:id?/:period?': ['HenryQW', 'nczitzk'],
+ '/toplist/:id?/:period?': ['nczitzk'],
+ '/thinktank/:id/:type?': ['hoilc', 'nczitzk'],
+};
diff --git a/lib/v2/aisixiang/radar.js b/lib/v2/aisixiang/radar.js
new file mode 100644
index 000000000..0e1b9306f
--- /dev/null
+++ b/lib/v2/aisixiang/radar.js
@@ -0,0 +1,29 @@
+module.exports = {
+ 'aisixiang.com': {
+ _name: '爱思想',
+ '.': [
+ {
+ title: '栏目',
+ docs: 'https://docs.rsshub.app/reading.html#ai-si-xiang',
+ source: ['/data/search', '/'],
+ target: (params, url) => `/aisixiang/column/${new URL(url).searchParams.get('column')}`,
+ },
+ {
+ title: '排行',
+ docs: 'https://docs.rsshub.app/reading.html#ai-si-xiang',
+ source: ['/toplist', '/'],
+ target: (params, url) => {
+ const id = new URL(url).searchParams.get('id');
+ const period = new URL(url).searchParams.get('period');
+ return `/aisixiang/toplist${id ? `/${id}${(id === '1' || !id) && period ? `/${period}` : ''}` : ''}`;
+ },
+ },
+ {
+ title: '思想库(专栏)',
+ docs: 'https://docs.rsshub.app/reading.html#ai-si-xiang',
+ source: ['/thinktank', '/'],
+ target: (params, url) => `/aisixiang/thinktank/${new URL(url).href.match(/thinktank\/(.*)\.html/)[1]}`,
+ },
+ ],
+ },
+};
diff --git a/lib/v2/aisixiang/router.js b/lib/v2/aisixiang/router.js
new file mode 100644
index 000000000..8cbf64048
--- /dev/null
+++ b/lib/v2/aisixiang/router.js
@@ -0,0 +1,6 @@
+module.exports = function (router) {
+ router.get('/column/:id', require('./column'));
+ router.get('/ranking/:id?/:period?', require('./toplist'));
+ router.get('/toplist/:id?/:period?', require('./toplist'));
+ router.get('/thinktank/:id/:type?', require('./thinktank'));
+};
diff --git a/lib/v2/aisixiang/thinktank.js b/lib/v2/aisixiang/thinktank.js
new file mode 100644
index 000000000..38732a250
--- /dev/null
+++ b/lib/v2/aisixiang/thinktank.js
@@ -0,0 +1,49 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { rootUrl, ProcessFeed } = require('./utils');
+
+module.exports = async (ctx) => {
+ const id = ctx.params.id;
+ const type = ctx.params.type ?? '';
+ const limit = ctx.query.limit ? parseInt(ctx.query.limit) : 30;
+
+ const currentUrl = `${rootUrl}/thinktank/${id}.html`;
+
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+
+ const $ = cheerio.load(response.data);
+
+ const title = `${$('h2').first().text().trim()}${type}`;
+
+ let items = [];
+
+ const targetList = $('h3')
+ .toArray()
+ .filter((h) => (type ? $(h).text() === type : true));
+ if (!targetList) {
+ throw `Not found ${type} in ${id}: ${currentUrl}`;
+ }
+
+ for (const l of targetList) {
+ items = [...items, ...$(l).parent().find('ul li a').toArray()];
+ }
+
+ items = items.map((item) => {
+ item = $(item);
+
+ return {
+ title: item.text().split(':').pop(),
+ link: new URL(item.attr('href'), rootUrl).href,
+ };
+ });
+
+ ctx.state.data = {
+ title: `爱思想 - ${title}`,
+ link: currentUrl,
+ item: await ProcessFeed(limit, ctx.cache.tryGet, items),
+ description: $('div.thinktank-author-description-box p').text(),
+ };
+};
diff --git a/lib/v2/aisixiang/toplist.js b/lib/v2/aisixiang/toplist.js
new file mode 100644
index 000000000..2d855e702
--- /dev/null
+++ b/lib/v2/aisixiang/toplist.js
@@ -0,0 +1,37 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { rootUrl, ProcessFeed } = require('./utils');
+
+module.exports = async (ctx) => {
+ const id = ctx.params.id ?? '1';
+ const period = ctx.params.period ?? '1';
+ const limit = ctx.query.limit ? parseInt(ctx.query.limit) : 30;
+
+ const currentUrl = `${rootUrl}/toplist${id ? `?id=${id}${id === '1' ? `&period=${period}` : ''}` : ''}`;
+
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+
+ const $ = cheerio.load(response.data);
+
+ const title = `${$('.hl').text() || ''}${$('title').text().split('_')[0]}`;
+
+ const items = $('div.tips a')
+ .toArray()
+ .map((item) => {
+ item = $(item);
+
+ return {
+ title: item.text().split(':').pop(),
+ link: new URL(item.attr('href'), rootUrl).href,
+ };
+ });
+
+ ctx.state.data = {
+ title: `爱思想 - ${title}`,
+ link: currentUrl,
+ item: await ProcessFeed(limit, ctx.cache.tryGet, items),
+ };
+};
diff --git a/lib/v2/aisixiang/utils.js b/lib/v2/aisixiang/utils.js
new file mode 100644
index 000000000..48fca95c7
--- /dev/null
+++ b/lib/v2/aisixiang/utils.js
@@ -0,0 +1,37 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const timezone = require('@/utils/timezone');
+const { parseDate } = require('@/utils/parse-date');
+
+const rootUrl = 'http://www.aisixiang.com';
+
+const ProcessFeed = (limit, tryGet, items) =>
+ Promise.all(
+ items.slice(0, limit).map((item) =>
+ tryGet(item.link, async () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+
+ const content = cheerio.load(detailResponse.data);
+
+ item.author = content('strong').first().text();
+ item.description = content('.article-content').html();
+ item.pubDate = timezone(parseDate(content('.info').text().split('时间:').pop()), +8);
+ item.category = content('u')
+ .first()
+ .parent()
+ .find('u')
+ .toArray()
+ .map((a) => content(a).text());
+
+ return item;
+ })
+ )
+ );
+
+module.exports = {
+ rootUrl,
+ ProcessFeed,
+};