feat(route): acfun article (#10110)

This commit is contained in:
Tony
2022-07-04 15:10:54 +01:00
committed by GitHub
parent 7823d4d97e
commit fc648b5471
12 changed files with 211 additions and 81 deletions
-7
View File
@@ -809,13 +809,6 @@
},
],
},
'acfun.cn': {
_name: 'AcFun',
www: [
{ tilte: '番剧', docs: 'https://docs.rsshub.app/anime.html#acfun-fan-ju', source: '/bangumi/:id', target: (params) => `/acfun/bangumi/${params.id.replace('aa', '')}` },
{ title: '用户投稿', docs: 'https://docs.rsshub.app/anime.html#acfun-yong-hu-tou-gao', source: '/u/:id', target: '/acfun/user/video/:id' },
],
},
'jjmhw.cc': { _name: '漫小肆', www: [{ title: '漫画更新', docs: 'https://docs.rsshub.app/anime.html#man-xiao-si', source: '/book/:id', target: '/manxiaosi/book/:id' }] },
'wenxuecity.com': {
_name: '文学城',
+18
View File
@@ -100,6 +100,24 @@ pageClass: routes
<Route author="wdssmq" example="/acfun/user/video/14450522" path="/acfun/user/video/:id" :paramsDesc="['用户 UID']" radar="1" rssbud="1"/>
### 文章
<Route author="TonyRL" example="/acfun/article/110" path="/acfun/article/:categoryId/:sortType?/:timeRange?" :paramsDesc="['分区 ID,见下表', '排序,见下表,默认为 `createTime`', '时间范围,见下表,仅在排序是 `hotScore` 有效,默认为 `all`']" radar="1" rssbud="1">
| 二次元画师 | 综合 | 生活情感 | 游戏 | 动漫文化 | 漫画文学 |
| ----- | --- | ---- | --- | ---- | ---- |
| 184 | 110 | 73 | 164 | 74 | 75 |
| 最新发表 | 最新动态 | 最热文章 |
| ---------- | --------------- | -------- |
| createTime | lastCommentTime | hotScore |
| 时间不限 | 24 小时 | 三天 | 一周 | 一个月 |
| ---- | ------ | -------- | ------- | -------- |
| all | oneDay | threeDay | oneWeek | oneMonth |
</Route>
## AGE 动漫
### 最近更新
-17
View File
@@ -1610,23 +1610,6 @@ module.exports = {
},
],
},
'acfun.cn': {
_name: 'AcFun',
www: [
{
tilte: '番剧',
docs: 'https://docs.rsshub.app/anime.html#acfun-fan-ju',
source: '/bangumi/:id',
target: (params) => `/acfun/bangumi/${params.id.replace('aa', '')}`,
},
{
title: '用户投稿',
docs: 'https://docs.rsshub.app/anime.html#acfun-yong-hu-tou-gao',
source: '/u/:id',
target: '/acfun/user/video/:id',
},
],
},
'jjmhw.cc': {
_name: '漫小肆',
www: [
+3 -3
View File
@@ -939,9 +939,9 @@ router.get('/nhentai/:key/:keyword/:mode?', lazyloadRouteHandler('./routes/nhent
// 龙腾网
router.get('/ltaaa/:category?', lazyloadRouteHandler('./routes/ltaaa/index'));
// AcFun
router.get('/acfun/bangumi/:id', lazyloadRouteHandler('./routes/acfun/bangumi'));
router.get('/acfun/user/video/:uid', lazyloadRouteHandler('./routes/acfun/video'));
// AcFun migrated to v2
// router.get('/acfun/bangumi/:id', lazyloadRouteHandler('./routes/acfun/bangumi'));
// router.get('/acfun/user/video/:uid', lazyloadRouteHandler('./routes/acfun/video'));
// Auto Trader
router.get('/autotrader/:query', lazyloadRouteHandler('./routes/autotrader'));
-44
View File
@@ -1,44 +0,0 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
module.exports = async (ctx) => {
const uid = ctx.params.uid;
const url = `http://www.acfun.cn/u/${uid}.aspx`;
const host = 'http://www.acfun.cn';
const response = await got({
method: 'get',
url,
headers: {
Referer: host,
},
});
const data = response.data;
const $ = cheerio.load(data);
const title = $('title').text();
const description = $('.preview').text();
const list = $('#ac-space-video-list a').get();
ctx.state.data = {
title,
link: url,
description,
item: list
.map((item) => {
const $ = cheerio.load(item);
const itemTitle = $('p.title').text();
const itemImg = $('figure img').attr('src');
const itemUrl = $('a').attr('href');
const itemDate = $('.date').text();
return {
title: itemTitle,
description: `<img src="${itemImg}">`,
link: host + itemUrl,
pubDate: new Date(itemDate).toUTCString(),
};
})
.reverse(),
};
};
+100
View File
@@ -0,0 +1,100 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
const baseUrl = 'https://www.acfun.cn';
const categoryMap = {
184: {
title: '二次元画师',
realmId: 'realmId=18' + '&realmId=14' + '&realmId=51',
},
110: {
title: '综合',
realmId: 'realmId=5' + '&realmId=22' + '&realmId=28' + '&realmId=3' + '&realmId=4',
},
73: {
title: '生活情感',
realmId: 'realmId=50' + '&realmId=25' + '&realmId=34' + '&realmId=7' + '&realmId=6' + '&realmId=17' + '&realmId=1' + '&realmId=2' + '&realmId=49',
},
164: {
title: '游戏',
realmId: 'realmId=8' + '&realmId=53' + '&realmId=52' + '&realmId=11' + '&realmId=43' + '&realmId=44' + '&realmId=45' + '&realmId=46' + '&realmId=47',
},
74: {
title: '动漫文化',
realmId: 'realmId=13' + '&realmId=31' + '&realmId=48',
},
75: {
title: '漫画文学',
realmId: 'realmId=15' + '&realmId=23' + '&realmId=16',
},
};
const sortTypeEnum = ['createTime', 'lastCommentTime', 'hotScore'];
const timeRangeEnum = ['all', 'oneDay', 'threeDay', 'oneWeek', 'oneMonth'];
module.exports = async (ctx) => {
const { categoryId, sortType = 'createTime', timeRange = 'all' } = ctx.params;
if (!categoryMap[categoryId]) {
throw `Invalid category Id: ${categoryId}`;
}
if (!sortTypeEnum.includes(sortType)) {
throw `Invalid sort type: ${sortType}`;
}
if (!timeRangeEnum.includes(timeRange)) {
throw `Invalid time range: ${timeRange}`;
}
const url = `${baseUrl}/v/list${categoryId}/index.htm`;
const response = await got.post(
`${baseUrl}/rest/pc-direct/article/feed` +
'?cursor=first_page' +
'&onlyOriginal=false' +
'&limit=10' +
`&sortType=${sortType}` +
`&timeRange=${sortType === 'hotScore' ? timeRange : 'all'}` +
`&${categoryMap[categoryId].realmId}`,
{
headers: {
referer: url,
},
}
);
const list = response.data.data.map((item) => ({
title: item.title,
link: `${baseUrl}/a/ac${item.articleId}`,
author: item.userName,
pubDate: parseDate(item.createTime, 'x'),
category: item.realmName,
}));
const items = await Promise.all(
list.map((item) =>
ctx.cache.tryGet(item.link, async () => {
const response = await got(item.link, {
headers: {
referer: url,
},
});
const $ = cheerio.load(response.data);
const articleInfo = $('.main script')
.text()
.match(/window.articleInfo = (.*);\n\s*window.likeDomain/)[1];
const data = JSON.parse(articleInfo);
item.description = data.parts[0].content;
if (data.tagList) {
item.category = [item.category, ...data.tagList.map((tag) => tag.name)];
}
return item;
})
)
);
ctx.state.data = {
title: categoryMap[categoryId].title,
link: url,
item: items,
};
};
@@ -1,14 +1,13 @@
const got = require('@/utils/got');
const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const { id } = ctx.params;
const url = `http://www.acfun.cn/bangumi/aa${id}`;
const url = `https://www.acfun.cn/bangumi/aa${id}`;
const bangumiPage = await got({
method: 'get',
url,
const bangumiPage = await got(url, {
headers: {
Referer: 'http://www.acfun.cn',
Referer: 'https://www.acfun.cn',
},
});
const bangumiData = JSON.parse(bangumiPage.data.match(/window.bangumiData = (.*?);\n/)[1]);
@@ -18,11 +17,12 @@ module.exports = async (ctx) => {
title: bangumiData.bangumiTitle,
link: url,
description: bangumiData.bangumiIntro,
image: bangumiData.belongResource.coverImageV,
item: bangumiList.items.map((item) => ({
title: `${item.episodeName} - ${item.title}`,
description: `<img src="${item.image.split('?')[0]}">`,
description: `<img src="${item.imgInfo.thumbnailImage.cdnUrls[0].url.split('?')[0]}">`,
link: `http://www.acfun.cn/bangumi/aa${id}_36188_${item.itemId}`,
pubDate: new Date(item.updateTime).toUTCString(),
pubDate: parseDate(item.updateTime, 'x'),
})),
};
};
+5
View File
@@ -0,0 +1,5 @@
module.exports = {
'/article/:categoryId/:sortType?/:timeRange?': ['TonyRL'],
'/bangumi/:id': ['xyqfer'],
'/user/video/:uid': ['wdssmq'],
};
+25
View File
@@ -0,0 +1,25 @@
module.exports = {
'acfun.cn': {
_name: 'AcFun',
www: [
{
tilte: '番剧',
docs: 'https://docs.rsshub.app/anime.html#acfun-fan-ju',
source: '/bangumi/:id',
target: (params) => `/acfun/bangumi/${params.id.replace('aa', '')}`,
},
{
title: '用户投稿',
docs: 'https://docs.rsshub.app/anime.html#acfun-yong-hu-tou-gao',
source: '/u/:id',
target: '/acfun/user/video/:id',
},
{
title: '文章',
docs: 'https://docs.rsshub.app/anime.html#acfun',
source: '/v/:categoryId/index.htm',
target: (params) => `/acfun/article/${params.categoryId.replace('list', '')}`,
},
],
},
};
+5
View File
@@ -0,0 +1,5 @@
module.exports = (router) => {
router.get('/article/:categoryId/:sortType?/:timeRange?', require('./article'));
router.get('/bangumi/:id', require('./bangumi'));
router.get('/user/video/:uid', require('./video'));
};
+45
View File
@@ -0,0 +1,45 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const uid = ctx.params.uid;
const url = `https://www.acfun.cn/u/${uid}`;
const host = 'https://www.acfun.cn';
const response = await got(url, {
headers: {
Referer: host,
},
});
const data = response.data;
const $ = cheerio.load(data);
const title = $('title').text();
const description = $('.signature .complete').text();
const list = $('#ac-space-video-list a').get();
const image = $('head style')
.text()
.match(/.user-photo{\n\s*background:url\((.*)\) 0% 0% \/ 100% no-repeat;/)[1];
ctx.state.data = {
title,
link: url,
description,
image,
item: list.map((item) => {
item = $(item);
const itemTitle = item.find('p.title').text();
const itemImg = item.find('figure img').attr('src');
const itemUrl = item.attr('href');
const itemDate = item.find('.date').text();
return {
title: itemTitle,
description: `<img src="${itemImg.split('?')[0]}">`,
link: host + itemUrl,
pubDate: parseDate(itemDate, 'YYYY/MM/DD'),
};
}),
};
};
+3 -3
View File
@@ -130,19 +130,19 @@ module.exports = {
{
title: '软微-通知公告',
docs: 'https://docs.rsshub.app/university.html#bei-jing-da-xue',
source: ['index.php/newscenter/notice', '/'],
source: ['/index.php/newscenter/notice', '/'],
target: '/pku/ss/notice',
},
{
title: '软微-招生通知',
docs: 'https://docs.rsshub.app/university.html#bei-jing-da-xue',
source: ['admission/admnotice', '/'],
source: ['/admission/admnotice', '/'],
target: '/pku/ss/admission',
},
{
title: '软微-硕士统考招生',
docs: 'https://docs.rsshub.app/university.html#bei-jing-da-xue',
source: ['admission/admbrochure/admission01', '/'],
source: ['/admission/admbrochure/admission01', '/'],
target: '/pku/ss/pgadmin',
},
],