diff --git a/docs/other.md b/docs/other.md index ea0dcdf2a9..afa5bd7ade 100644 --- a/docs/other.md +++ b/docs/other.md @@ -1145,3 +1145,29 @@ type 为 all 时,category 参数不支持 cost 和 free ### 全文 + +## 站酷 + +### 推荐 + + + +推荐类型 + +| all | home | edit | +| -------- | -------- | -------- | +| 全部推荐 | 首页推荐 | 编辑推荐 | + + + +### 作品总榜单 + + + +### 用户作品 + + + +例如: 站酷的个人主页 `https://baiyong.zcool.com.cn` 对应 rss 路径 `/zcool/user/baiyong` + + diff --git a/lib/router.js b/lib/router.js index 121b971c37..b047abe1da 100644 --- a/lib/router.js +++ b/lib/router.js @@ -1562,6 +1562,11 @@ router.get('/10000link/news/:category?', require('./routes/10000link/news')); // Artand router.get('/artand/user/work/:uid', require('./routes/artand/user/work')); +// 站酷 +router.get('/zcool/recommend/:type', require('./routes/zcool/recommend')); +router.get('/zcool/top', require('./routes/zcool/top')); +router.get('/zcool/user/:uname', require('./routes/zcool/user')); + // 第一财经 router.get('/yicai/brief', require('./routes/yicai/brief.js')); diff --git a/lib/routes/zcool/recommend.js b/lib/routes/zcool/recommend.js new file mode 100644 index 0000000000..507a6324b1 --- /dev/null +++ b/lib/routes/zcool/recommend.js @@ -0,0 +1,71 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); + +module.exports = async (ctx) => { + let typeUrl = '0!0!0!0!0!!!!1!-1!1'; + let typeName = '全部推荐'; + + const type = ctx.params.type; + if (type === 'home') { + typeUrl = '0!0!0!0!0!!!!3!-1!1'; + typeName = '首页推荐'; + } else if (type === 'edit') { + typeUrl = '0!0!0!0!0!!!!2!-1!1'; + typeName = '编辑推荐'; + } + + const url = 'https://www.zcool.com.cn/discover/' + typeUrl; + const response = await got({ method: 'get', url }); + const $ = cheerio.load(response.data); + + const list = $('.work-list-box > .card-box') + .map((i, e) => { + const element = $(e); + const title = element + .find('.card-info-title') + .find('a') + .attr('title') + .trim(); + const link = element + .find('.card-info-title') + .find('a') + .attr('href') + .trim(); + const author = element + .find('.user-avatar') + .find('a') + .attr('title'); + + return { + title: title, + description: '', + link: link, + author: author, + }; + }) + .get(); + + const result = await Promise.all( + list.map(async (item) => { + const link = item.link; + + const cache = await ctx.cache.get(link); + if (cache) { + return Promise.resolve(JSON.parse(cache)); + } + + const itemReponse = await got.get(link); + const itemElement = cheerio.load(itemReponse.data); + item.description = itemElement('.work-content-wrap').html(); + + ctx.cache.set(link, JSON.stringify(item)); + return Promise.resolve(item); + }) + ); + + ctx.state.data = { + title: '站酷 - ' + typeName, + link: url, + item: result.reverse(), + }; +}; diff --git a/lib/routes/zcool/top.js b/lib/routes/zcool/top.js new file mode 100644 index 0000000000..b4ed66fa9f --- /dev/null +++ b/lib/routes/zcool/top.js @@ -0,0 +1,58 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); + +module.exports = async (ctx) => { + const url = 'https://www.zcool.com.cn/top/index.do'; + const response = await got({ method: 'get', url }); + const $ = cheerio.load(response.data); + + const list = $('.author') + .map((i, e) => { + const element = $(e); + + const title = element + .find('.title') + .find('a') + .text(); + const link = element + .find('.title') + .find('a') + .attr('href'); + const author = element + .find('.nick') + .find('a') + .text(); + + return { + title: title, + description: '', + link: link, + author: author, + }; + }) + .get(); + + const result = await Promise.all( + list.map(async (item) => { + const link = item.link; + + const cache = await ctx.cache.get(link); + if (cache) { + return Promise.resolve(JSON.parse(cache)); + } + + const itemReponse = await got.get(link); + const itemElement = cheerio.load(itemReponse.data); + item.description = itemElement('.work-content-wrap').html(); + + ctx.cache.set(link, JSON.stringify(item)); + return Promise.resolve(item); + }) + ); + + ctx.state.data = { + title: '站酷 - 作品总榜单', + link: url, + item: result.reverse(), + }; +}; diff --git a/lib/routes/zcool/user.js b/lib/routes/zcool/user.js new file mode 100644 index 0000000000..c907139691 --- /dev/null +++ b/lib/routes/zcool/user.js @@ -0,0 +1,59 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); + +module.exports = async (ctx) => { + const uname = ctx.params.uname; + + const url = 'https://' + uname + '.zcool.com.cn'; + const response = await got({ method: 'get', url }); + const $ = cheerio.load(response.data); + const author = $('.people-nick-name') + .text() + .trim(); + + const list = $('.work-list-box > .card-box') + .map((i, e) => { + const element = $(e); + const title = element + .find('.card-info-title') + .find('a') + .attr('title') + .trim(); + const link = element + .find('.card-info-title') + .find('a') + .attr('href') + .trim(); + return { + title: title, + description: '', + link: link, + author: author, + }; + }) + .get(); + + const result = await Promise.all( + list.map(async (item) => { + const link = item.link; + + const cache = await ctx.cache.get(link); + if (cache) { + return Promise.resolve(JSON.parse(cache)); + } + + const itemReponse = await got.get(link); + const itemElement = cheerio.load(itemReponse.data); + item.description = itemElement('.work-content-wrap').html(); + + ctx.cache.set(link, JSON.stringify(item)); + return Promise.resolve(item); + }) + ); + + ctx.state.data = { + title: '站酷 - ' + author, + link: url, + item: result.reverse(), + }; +};