| 校区要闻 | 媒体报道 | 通知公告 | 综合新闻 | 校园动态 | 讲座论坛 | 热点专题 |
| -------- | -------- | -------- | -------- | -------- | -------- | -------- |
@@ -973,6 +973,14 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS
+### 电子与信息学院 - 新闻速递
+
+
+
+::: warning 注意
+由于学院官网对非大陆 IP 的访问存在限制,需自行部署。
+:::
+
## 华南师范大学
### 软件学院通知公告
@@ -1922,6 +1930,20 @@ type 列表:
+### 就业创业中心
+
+
+
+栏目类型
+
+| 中心通告 | 选调生及公务员 | 国际组织实习 | 新闻资讯 | 活动与讲座 |
+| -------- | -------------- | ------------ | -------- | ---------- |
+| zxtg | xdsgwy | gjzzsx | xwzx | hdyjz |
+
+### 电气学院
+
+
+
## 西北工业大学
### 翱翔门户
diff --git a/lib/router.js b/lib/router.js
index 429f3905f2..de2059e9b1 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -493,6 +493,7 @@ router.get('/xueqiu/fund/:id', require('./routes/xueqiu/fund'));
router.get('/xueqiu/stock_info/:id/:type?', require('./routes/xueqiu/stock_info'));
router.get('/xueqiu/snb/:id', require('./routes/xueqiu/snb'));
router.get('/xueqiu/hots', require('./routes/xueqiu/hots'));
+router.get('/xueqiu/stock_comments/:id/:titleLength?', require('./routes/xueqiu/stock_comments'));
// Greasy Fork
router.get('/greasyfork/:language/:domain?', require('./routes/greasyfork/scripts'));
@@ -597,7 +598,9 @@ router.get('/novel/zhaishuyuan/:id', require('./routes/novel/zhaishuyuan'));
router.get('/weatheralarm/:province?', require('./routes/weatheralarm'));
// Gitlab
-router.get('/gitlab/explore/:type', require('./routes/gitlab/explore'));
+router.get('/gitlab/explore/:type/:host?', require('./routes/gitlab/explore'));
+router.get('/gitlab/release/:namespace/:project/:host?', require('./routes/gitlab/release'));
+router.get('/gitlab/tag/:namespace/:project/:host?', require('./routes/gitlab/tag'));
// 忧郁的loli
router.get('/mygalgame', require('./routes/galgame/hhgal')); // 废弃
@@ -1134,6 +1137,9 @@ router.get('/tencentvideo/playlist/:id', require('./routes/tencent/video/playlis
// 看漫画
router.get('/manhuagui/comic/:id', require('./routes/manhuagui/comic'));
+router.get('/mhgui/comic/:id', require('./routes/mhgui/comic'));
+router.get('/twmanhuagui/comic/:id', require('./routes/twmanhuagui/comic'));
+
// 動漫狂
router.get('/cartoonmad/comic/:id', require('./routes/cartoonmad/comic'));
// Vol
@@ -2007,11 +2013,11 @@ router.get('/getitfree/search/:keyword?', require('./routes/getitfree/search.js'
router.get('/10000link/news/:category?', require('./routes/10000link/news'));
// 站酷
-router.get('/zcool/recommend/:type', require('./routes/zcool/recommend'));
+router.get('/zcool/discover/:query?/:subCate?/:hasVideo?/:city?/:collage?/:recommendLevel?/:sort?', require('./routes/zcool/discover'));
+router.get('/zcool/recommend/:query?/:subCate?/:hasVideo?/:city?/:collage?/:recommendLevel?/:sort?', require('./routes/zcool/discover')); // 兼容老版本
router.get('/zcool/top/:type', require('./routes/zcool/top'));
router.get('/zcool/top', require('./routes/zcool/top')); // 兼容老版本
router.get('/zcool/user/:uid', require('./routes/zcool/user'));
-router.get('/zcool/discovery/:query?', require('./routes/zcool/discovery'));
// 第一财经
router.get('/yicai/brief', require('./routes/yicai/brief.js'));
@@ -2160,6 +2166,7 @@ router.get('/sse/disclosure/:query?', require('./routes/sse/disclosure'));
router.get('/szse/notice', require('./routes/szse/notice'));
router.get('/szse/inquire/:type', require('./routes/szse/inquire'));
router.get('/szse/rule', require('./routes/szse/rule'));
+router.get('/szse/projectdynamic/:type?/:stage?/:status?', require('./routes/szse/projectdynamic'));
// 前端艺术家每日整理&&飞冰早报
router.get('/jskou/:type?', require('./routes/jskou/index'));
@@ -2651,6 +2658,8 @@ router.get('/wolley/host/:host', require('./routes/wolley/host'));
router.get('/xjtu/gs/tzgg', require('./routes/universities/xjtu/gs/tzgg'));
router.get('/xjtu/dean/:subpath+', require('./routes/universities/xjtu/dean'));
router.get('/xjtu/international/:subpath+', require('./routes/universities/xjtu/international'));
+router.get('/xjtu/job/:subpath?', require('./routes/universities/xjtu/job'));
+router.get('/xjtu/ee/:id?', require('./routes/universities/xjtu/ee'));
// booksource
router.get('/booksource', require('./routes/booksource/index'));
@@ -2977,7 +2986,7 @@ router.get('/grubstreet', require('./routes/grubstreet/index'));
router.get('/manhuadui/manhua/:name/:serial?', require('./routes/manhuadui/manhua'));
// 风之漫画
-router.get('/fzdm/manhua/:id/:nums?', require('./routes/fzdm/manhua'));
+router.get('/fzdm/manhua/:id', require('./routes/fzdm/manhua'));
// Aljazeera 半岛网
router.get('/aljazeera/news', require('./routes/aljazeera/news'));
@@ -3149,7 +3158,7 @@ router.get('/erbingapp/news', require('./routes/erbingapp/news'));
router.get('/dsb/area/:area', require('./routes/dsb/area'));
// 靠谱新闻
-router.get('/kaopunews/all', require('./routes/kaopunews/all'));
+router.get('/kaopunews/:language?', require('./routes/kaopunews'));
// Reuters
router.get('/reuters/theWire', require('./routes/reuters/theWire'));
@@ -3236,6 +3245,9 @@ router.get('/scvtc/xygg', require('./routes/universities/scvtc/xygg'));
// 华南理工大学土木与交通学院
router.get('/scut/scet/notice', require('./routes/universities/scut/scet/notice'));
+// 华南理工大学电子与信息学院
+router.get('/scut/seie/news_center', require('./routes/universities/scut/seie/news_center'));
+
// OneJAV
router.get('/onejav/:type/:key?', require('./routes/onejav/one'));
@@ -4116,10 +4128,34 @@ router.get('/bibgame/:category?/:type?', require('./routes/bibgame/category'));
// 澳門特別行政區政府各公共部門獎助貸學金服務平台
router.get('/macau-bolsas/:lang?', require('./routes/macau-bolsas/index'));
+// PotPlayer
+router.get('/potplayer/update/:language?', require('./routes/potplayer/update'));
+
+// 综艺秀
+router.get('/zyshow/:name', require('./routes/zyshow'));
+
// 加美财经
router.get('/caus/:category?', require('./routes/caus'));
// 摩点
router.get('/modian/zhongchou/:category?/:sort?/:status?', require('./routes/modian/zhongchou'));
+// 世界计划 多彩舞台 feat.初音未来 (ProjectSekai)
+router.get('/pjsk/news', require('./routes/pjsk/news'));
+
+// 人民论坛网
+router.get('/rmlt/idea/:category?', require('./routes/rmlt/idea'));
+
+// CBNData
+router.get('/cbndata/information/:category?', require('./routes/cbndata/information'));
+
+// TANC 艺术新闻
+router.get('/tanchinese/:category?', require('./routes/tanchinese'));
+
+// Harvard
+router.get('/harvard/health/blog', require('./routes/universities/harvard/health/blog'));
+
+// dykszx
+router.get('/dykszx/news/:type?', require('./routes/dykszx/news'));
+
module.exports = router;
diff --git a/lib/routes/cbndata/information.js b/lib/routes/cbndata/information.js
new file mode 100644
index 0000000000..db3bf21d09
--- /dev/null
+++ b/lib/routes/cbndata/information.js
@@ -0,0 +1,53 @@
+const got = require('@/utils/got');
+
+module.exports = async (ctx) => {
+ const category = ctx.params.category || '';
+
+ const rootUrl = 'https://www.cbndata.com';
+ const apiUrl = `${rootUrl}/api/v3/informations?page=1&per_page=10${category ? `&tag_id=${category}` : ''}`;
+
+ const response = await got({
+ method: 'get',
+ url: apiUrl,
+ });
+
+ const list = response.data.data.map((item) => ({
+ title: item.id,
+ link: `${rootUrl}/api/v3/informations/show?id=${item.id}`,
+ pubDate: Date.parse(item.date),
+ }));
+
+ const items = await Promise.all(
+ list.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+
+ item.link = `${rootUrl}/information/${item.title}`;
+
+ item.title = detailResponse.data.data.title;
+ item.author = detailResponse.data.data.author;
+ item.description = detailResponse.data.data.content;
+
+ return item;
+ })
+ )
+ );
+
+ let title = '看点';
+
+ for (const tag of response.data.home_tags) {
+ if (tag.id.toString() === category) {
+ title = tag.name;
+ break;
+ }
+ }
+ ctx.state.data = {
+ title: `${title} - CBNData消费站`,
+ link: `${rootUrl}/information${category ? `?tag_id=${category}` : ''}`,
+ item: items,
+ };
+};
diff --git a/lib/routes/dykszx/news.js b/lib/routes/dykszx/news.js
new file mode 100644
index 0000000000..604a24050f
--- /dev/null
+++ b/lib/routes/dykszx/news.js
@@ -0,0 +1,57 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const timezone = require('@/utils/timezone');
+const host = 'https://www.dykszx.com';
+
+const getContent = (href, caches) => {
+ const newsPage = `${host}${href}`;
+ return caches.tryGet(newsPage, async () => {
+ const response = await got.get(newsPage);
+ const data = response.data;
+ const $ = cheerio.load(data);
+ const newsTime = $('body > div:nth-child(3) > div.page.w > div.shuxing.w')
+ .text()
+ .trim()
+ .match(/时间:(.*?)点击/g)[0];
+ // 移除二维码
+ $('.sjlook').remove();
+ const content = $('#show-body').html();
+ return { newsTime, content, newsPage };
+ });
+};
+
+const newsTypeObj = {
+ all: { selector: '#nrs > li > b', name: '新闻中心' },
+ gwy: { selector: 'body > div:nth-child(3) > div:nth-child(8) > ul > li', name: '公务员考试' },
+ sydw: { selector: 'body > div:nth-child(3) > div:nth-child(9) > ul > li', name: '事业单位考试' },
+ zyzc: { selector: 'body > div:nth-child(3) > div:nth-child(10) > ul > li', name: '执(职)业资格、职称考试' },
+ other: { selector: 'body > div:nth-child(3) > div:nth-child(11) > ul > li', name: '其他考试' },
+};
+
+module.exports = async (ctx) => {
+ const newsType = ctx.params.type || 'all';
+ const response = await got.get(host);
+ const data = response.data;
+ const $ = cheerio.load(data);
+ const newsList = $(newsTypeObj[newsType].selector).toArray();
+
+ const newsDetail = await Promise.all(
+ newsList.map(async (item) => {
+ const href = item.children[0].attribs.href;
+ const newsContent = await getContent(href, ctx.cache);
+ return {
+ title: item.children[0].children[0].data,
+ description: newsContent.content,
+ link: newsContent.newsPage,
+ pubDate: timezone(parseDate(newsContent.newsTime, '时间:YYYY-MM-DD HH:mm:ss'), +8),
+ };
+ })
+ );
+ ctx.state.data = {
+ title: `德阳人事考试网 - ${newsTypeObj[newsType].name}`,
+ link: host,
+ description: '德阳人事考试网 考试新闻发布',
+ item: newsDetail,
+ };
+};
diff --git a/lib/routes/erbingapp/news.js b/lib/routes/erbingapp/news.js
index b09d19920c..411474b34e 100644
--- a/lib/routes/erbingapp/news.js
+++ b/lib/routes/erbingapp/news.js
@@ -1,42 +1,51 @@
const got = require('@/utils/got');
+const timezone = require('@/utils/timezone');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const response = await got({
method: 'get',
url: `https://api.diershoubing.com:5001/feed/tag/?pn=0&rn=20&tag_type=0&src=ios`,
- resolveBodyOnly: true,
- responseType: 'json',
});
- const data = response.feeds;
+ const data = JSON.parse(response.body).feeds;
+ const items = data.map((item) => {
+ let description = `${item.content}
`;
+ const acontent = item.acontent.toString();
+ const ProcessDesc = (link, type) => {
+ if (type) {
+ description += `More
`;
+ } else {
+ for (const item of link) {
+ description += `
`;
+ }
+ }
+ };
+
+ if (item.video_img !== null) {
+ ProcessDesc([item.video_img]);
+ } else if (acontent.indexOf('104129') !== -1) {
+ ProcessDesc([item.article.humb.split('?')[0]]);
+ } else if (acontent.indexOf('.html') !== -1) {
+ ProcessDesc([acontent], 'html');
+ } else if (acontent.indexOf('"imgs') !== -1) {
+ const imgs = JSON.parse(acontent).imgs.split(',');
+ ProcessDesc(imgs);
+ } else {
+ const imgs = acontent.split(',');
+ ProcessDesc(imgs);
+ }
+ return {
+ title: item.title,
+ link: item.share.url,
+ description,
+ pubDate: timezone(parseDate(item.create_time), +8),
+ };
+ });
ctx.state.data = {
title: `二柄APP`,
- link: `https://www.diershoubing.com/`,
+ link: `https://www.diershoubing.com`,
description: `二柄APP新闻`,
- item: data.map((item) => {
- let description = item.content;
- if (item.video_img !== null) {
- description += `
`;
- } else if (item.acontent.indexOf('104129') !== -1) {
- description += `
`;
- } else if (item.acontent.indexOf('.html') !== -1) {
- description += `
More`;
- } else if (item.acontent.indexOf('"imgs') !== -1) {
- const imgs = item.acontent.split(',');
- for (let i = 1; i < imgs.length; i++) {
- description += `
`;
- }
- } else {
- const imgs = item.acontent.split(',');
- for (let i = 0; i < imgs.length; i++) {
- description += `
`;
- }
- }
- return {
- description,
- link: item.share.url,
- title: item.title,
- };
- }),
+ item: items,
};
};
diff --git a/lib/routes/ff14/ff14_zh.js b/lib/routes/ff14/ff14_zh.js
index 0a3dd45a4f..b638f01874 100644
--- a/lib/routes/ff14/ff14_zh.js
+++ b/lib/routes/ff14/ff14_zh.js
@@ -1,5 +1,5 @@
const got = require('@/utils/got');
-
+const timezone = require('@/utils/timezone');
module.exports = async (ctx) => {
const referer = 'http://ff.sdo.com/web8/index.html';
const type = ctx.params.type;
@@ -29,10 +29,8 @@ module.exports = async (ctx) => {
item: data.map(({ Title, Summary, Author, PublishDate, HomeImagePath }) => ({
title: Title,
link: Author,
- description: `
- 
- ${Summary}
- ${PublishDate}`,
+ description: `
${Summary}`,
+ pubDate: timezone(new Date(PublishDate), +8),
})),
};
};
diff --git a/lib/routes/fzdm/manhua.js b/lib/routes/fzdm/manhua.js
index b28fa5ad5d..7368cdab1a 100644
--- a/lib/routes/fzdm/manhua.js
+++ b/lib/routes/fzdm/manhua.js
@@ -1,27 +1,22 @@
const got = require('@/utils/got');
-const host = 'https://manhua.fzdm.com';
+const domain = 'manhua.fffdm.com';
+const host = `https://${domain}`;
+const picHost = 'https://p5.fzacg.com';
const cheerio = require('cheerio');
const get_pic = (id, chapert, caches) => {
- const picUrlPattern = RegExp(/var (mhurl1|mhurl)="(.*?)";/);
+ const picUrlPattern = RegExp(/var mhurl = "(.*?)";/);
return caches.tryGet(`${host}/${id}/${chapert}/`, async () => {
let is_last_page = false;
let index = 0;
let pic_content = '';
while (!is_last_page) {
// eslint-disable-next-line no-await-in-loop
- const response = await got.get(`${host}/${id}/${chapert}/index_${index}.html`, {
- headers: {
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36',
- Host: 'manhua.fzdm.com',
- 'Accept-Encoding': 'gzip, deflate, br',
- Connection: 'keep-alive',
- },
- });
+ const response = await got.get(`${host}/${id}/${chapert}/index_${index}.html`);
const data = response.data;
if (response.data !== undefined) {
const picurl = data.match(picUrlPattern);
- pic_content += `
`;
+ pic_content += `
`;
if (data.match('最后一页了') !== null) {
is_last_page = true;
}
@@ -38,7 +33,7 @@ const get_pic = (id, chapert, caches) => {
module.exports = async (ctx) => {
const id = ctx.params.id;
- const nums = ctx.params.nums || 1;
+ const count = ctx.query.limit || 99999;
const comicPage = host + `/${id}/`;
const response = await got({
method: 'get',
@@ -46,15 +41,15 @@ module.exports = async (ctx) => {
});
const data = response.data;
const $ = cheerio.load(data);
- const list = $('div#content > li > a');
+ const list = $('div#content > li > a').toArray();
const comicTitle = $('div#content > img').attr('alt').replace(/漫画/, '');
const chapter_detail = await Promise.all(
- list.splice(0, nums).map(async (item) => {
+ list.splice(0, count).map(async (item) => {
const pic_content = await get_pic(id, $(item).attr('href').replace('/', ''), ctx.cache);
return {
title: $(item).text().trim(),
description: pic_content,
- link: item.link,
+ link: `${comicPage}${item.attribs.href}`,
};
})
);
@@ -62,10 +57,6 @@ module.exports = async (ctx) => {
title: '风之动漫 - ' + comicTitle,
link: comicPage,
description: '风之动漫',
- item: chapter_detail.map((item) => ({
- title: item.title,
- description: item.description,
- link: item.link,
- })),
+ item: chapter_detail,
};
};
diff --git a/lib/routes/gamer/gnn_index.js b/lib/routes/gamer/gnn_index.js
index f77f843af7..0d1e48be9b 100644
--- a/lib/routes/gamer/gnn_index.js
+++ b/lib/routes/gamer/gnn_index.js
@@ -1,5 +1,7 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const timezone = require('@/utils/timezone');
module.exports = async (ctx) => {
const category = ctx.params.category;
@@ -47,37 +49,25 @@ module.exports = async (ctx) => {
const list = $('div.BH-lbox.GN-lbox2')
.children()
- .not('.GN-lbox2A,.GN-lbox2G')
+ .not('p,a,img,span')
.map((index, item) => {
item = $(item);
- const position = item.attr('class') === 'GN-lbox2F' ? 0 : 1;
- const ElementA = item.find('a').eq(position);
- const tagTable = {
- 'IMG-Gmuti': 'General',
- 'IMG-GA19': 'PC',
- 'IMG-GB3': 'NS',
- 'IMG-GB4': 'PS5',
- 'IMG-GB1': 'PS4',
- 'IMG-GB2': 'xone',
- 'IMG-GB5': 'Xbox',
- 'IMG-GA14': 'ARC',
- 'IMG-GAC': 'AC',
- 'IMG-GA13': 'ETC',
- 'IMG-GA1': 'OLG',
- 'IMG-Gmobi': 'MOBI',
- 'IMG-GA20': 'WEB',
- 'IMG-GA25': 'Google',
- 'IMG-GA24': 'Apple',
- 'IMG-GA28': 'Facebook',
- 'IMG-GA17': 'Other',
- 'IMG-GA23': 'Other',
- 'IMG-Gother': 'Other',
- };
- const tagValue = tagTable[item.find('img').eq(position).attr('class')];
- const tag = tagValue ? tagValue : 'Unclassified';
+ let aLabelNode;
+ let tag;
+ // a label with div
+ if (item.children().length !== 0) {
+ aLabelNode = item.find('a').eq(1);
+ tag = item.find('div.platform-tag_list').text();
+ }
+ // a label without div
+ else {
+ aLabelNode = item.next();
+ tag = item.text();
+ }
+
return {
- title: '[' + tag + '] ' + ElementA.text(),
- link: ElementA.attr('href').replace('//', 'https://'),
+ title: '[' + tag + '] ' + aLabelNode.text(),
+ link: aLabelNode.attr('href').replace('//', 'https://'),
};
})
.get();
@@ -88,21 +78,44 @@ module.exports = async (ctx) => {
const response = await got.get(item.link);
let component = '';
const urlReg = /window.location.replace\('.*'/g;
+
+ let pubInfo;
+ let dateStr;
if (response.body.search(urlReg) < 0) {
const $ = cheerio.load(response.data);
- item.author = $('span.GN-lbox3C').text().split(')')[0].split(' 報導')[0].split(' 提供')[0].split(' 同意授權轉載')[0].replace('(', '');
+ if ($('span.GN-lbox3C').length > 0) {
+ // official publish 1
+ pubInfo = $('span.GN-lbox3C').text().split(')');
+ item.author = pubInfo[0].replace('(', '').replace(' 報導', '');
+ dateStr = pubInfo[1].trim();
+ } else {
+ // official publish 2
+ pubInfo = $('span.GN-lbox3CA').text().split(')');
+ item.author = pubInfo[0].replace('(', '').replace(' 報導', '');
+ dateStr = pubInfo[1].replace('原文出處', '').trim();
+ }
component = $('div.GN-lbox3B').html();
} else {
+ // url redirect
const newUrl = response.body.match(urlReg)[0].split('(')[1].replace(/'/g, '');
const _response = await got.get(newUrl);
const _$ = cheerio.load(_response.data);
- item.author = _$('span.ST1').text().split('│', 2)[0].split('作者:')[1];
- component = _$('div.MSG-list8C').html();
- if (!component) {
- item.author = _$('a.caption-text.primary').text();
+
+ if (_$('div.MSG-list8C').length > 0) {
+ // personal publish 1
+ pubInfo = _$('span.ST1').text().split('│');
+ item.author = pubInfo[0].replace('作者:', '');
+ dateStr = pubInfo[_$('span.ST1').find('a').length > 0 ? 2 : 1];
+ component = _$('div.MSG-list8C').html();
+ } else {
+ // personal publish 2
+ pubInfo = _$('div.article-intro').text().replace(/\n/g, '').split('|');
+ item.author = pubInfo[0];
+ dateStr = pubInfo[1];
component = _$('div.text-paragraph').html();
}
}
+ item.pubDate = timezone(parseDate(dateStr, 'YYYY-MM-DD HH:mm:ss'), +8);
component = component.replace(/\b(data-src)\b/g, 'src');
return component;
});
diff --git a/lib/routes/gitlab/explore.js b/lib/routes/gitlab/explore.js
index 6feb623481..f77939b756 100644
--- a/lib/routes/gitlab/explore.js
+++ b/lib/routes/gitlab/explore.js
@@ -2,7 +2,9 @@ const got = require('@/utils/got');
const cheerio = require('cheerio');
module.exports = async (ctx) => {
- const type = ctx.params.type === 'all' ? '' : ctx.params.type;
+ let { type, host } = ctx.params;
+ type = type === 'all' ? '' : type;
+ host = host ? host : 'gitlab.com';
const typename = {
trending: 'Trending',
starred: 'Most stars',
@@ -11,14 +13,14 @@ module.exports = async (ctx) => {
const res = await got({
method: 'get',
- url: `https://gitlab.com/explore/projects/${type}`,
+ url: `https://${host}/explore/projects/${type}`,
});
const $ = cheerio.load(res.data);
const list = $('ul.projects-list').find('li');
ctx.state.data = {
title: `${typename[ctx.params.type]} - Explore - Gitlab`,
- link: `https://gitlab.com/explore/projects/${type}`,
+ link: `https://${host}/explore/projects/${type}`,
item:
list &&
list
@@ -28,7 +30,7 @@ module.exports = async (ctx) => {
title: item.find('.project-full-name').text(),
author: item.find('.namespace-name').text().slice(0, -1).split('\n').join('').trim(),
description: item.find('.description').text(),
- link: `https://gitlab.com${item.find('a.text-plain').attr('href')}`,
+ link: `https://${host}${item.find('a.text-plain').attr('href')}`,
};
})
.get(),
diff --git a/lib/routes/gitlab/release.js b/lib/routes/gitlab/release.js
new file mode 100644
index 0000000000..ee734df265
--- /dev/null
+++ b/lib/routes/gitlab/release.js
@@ -0,0 +1,30 @@
+const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const { namespace, project, host } = ctx.params;
+
+ const host_ = host ? host : 'gitlab.com';
+ const namespace_ = encodeURIComponent(namespace);
+
+ const api_url = `https://${host_}/api/v4/projects/${namespace_}%2F${project}/releases`;
+
+ const response = await got({
+ method: 'get',
+ url: api_url,
+ });
+ const data = response.data;
+
+ ctx.state.data = {
+ title: `${project} - Releases - Gitlab`,
+ link: `https://${host_}/${namespace}/${project}/-/releases`,
+ description: `${namespace}/${project} Releases`,
+ item: data.map((item) => ({
+ title: item.name,
+ author: item.author.name,
+ description: item.description_html,
+ pubDate: parseDate(item.released_at),
+ link: item._links.self,
+ })),
+ };
+};
diff --git a/lib/routes/gitlab/tag.js b/lib/routes/gitlab/tag.js
new file mode 100644
index 0000000000..6e267be525
--- /dev/null
+++ b/lib/routes/gitlab/tag.js
@@ -0,0 +1,30 @@
+const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const { namespace, project, host } = ctx.params;
+
+ const host_ = host ? host : 'gitlab.com';
+ const namespace_ = encodeURIComponent(namespace);
+
+ const api_url = `https://${host_}/api/v4/projects/${namespace_}%2F${project}/repository/tags`;
+
+ const response = await got({
+ method: 'get',
+ url: api_url,
+ });
+ const data = response.data;
+
+ ctx.state.data = {
+ title: `${project} - Tags - Gitlab`,
+ link: `https://${host_}/${namespace}/${project}/-/tags`,
+ description: `${namespace}/${project} Tags`,
+ item: data.map((item) => ({
+ title: item.name,
+ author: item.commit.author_name,
+ description: item.message,
+ pubDate: parseDate(item.commit.created_at),
+ link: item.commit.web_url,
+ })),
+ };
+};
diff --git a/lib/routes/kaopunews/all.js b/lib/routes/kaopunews/all.js
deleted file mode 100644
index 8085a9f93f..0000000000
--- a/lib/routes/kaopunews/all.js
+++ /dev/null
@@ -1,30 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-
-module.exports = async (ctx) => {
- const response = await got({
- method: 'get',
- url: 'https://kaopu.news/',
- });
-
- const data = response.data;
-
- const $ = cheerio.load(data);
- const list = $('a[target="_blank"]');
- ctx.state.data = {
- title: '靠谱新闻',
- link: 'https://kaopu.news/',
- item:
- list &&
- list
- .map((index, item) => {
- item = $(item);
- return {
- title: `${item.find('h3').text()}(${item.attr('class').substring(8)})`,
- description: item.find('h3').next().next().text(),
- link: item.attr('href'),
- };
- })
- .get(),
- };
-};
diff --git a/lib/routes/kaopunews/index.js b/lib/routes/kaopunews/index.js
new file mode 100644
index 0000000000..e848e9c55d
--- /dev/null
+++ b/lib/routes/kaopunews/index.js
@@ -0,0 +1,28 @@
+const got = require('@/utils/got');
+
+module.exports = async (ctx) => {
+ const language = ctx.params.language || '';
+
+ const rootUrl = 'https://kaopu.news';
+ const currentUrl = `${rootUrl}/${language === 'zh-hant' ? 'zh-hant' : 'index'}.html`;
+ const apiUrl = `https://kaopucdn.azureedge.net/jsondata/news_han${language === 'zh-hant' ? 't' : 's'}_0.json`;
+
+ const response = await got({
+ method: 'get',
+ url: apiUrl,
+ });
+
+ const items = response.data.map((item) => ({
+ link: item.link,
+ title: item.title,
+ author: item.publisher,
+ pubDate: new Date(item.first_seen * 1000),
+ description: `${item.story_summary}
`,
+ }));
+
+ ctx.state.data = {
+ title: language === 'zh-hant' ? '靠譜新聞' : '靠谱新闻',
+ link: currentUrl,
+ item: items,
+ };
+};
diff --git a/lib/routes/mhgui/comic.js b/lib/routes/mhgui/comic.js
new file mode 100644
index 0000000000..ae28a18591
--- /dev/null
+++ b/lib/routes/mhgui/comic.js
@@ -0,0 +1,53 @@
+const { resolve } = require('url');
+const cheerio = require('cheerio');
+const got = require('@/utils/got');
+const LZString = require('lz-string');
+
+const getChapters = ($) =>
+ $('.chapter-list > ul')
+ .toArray()
+ .reverse()
+ .reduce((acc, curr) => acc.concat($(curr).children('li').toArray()), [])
+ .map((ele) => {
+ const a = $(ele).children('a');
+ return {
+ link: resolve('https://www.mhgui.com/', a.attr('href')),
+ title: a.attr('title'),
+ num: a.find('i').text(),
+ };
+ });
+
+module.exports = async (ctx) => {
+ const { id } = ctx.params;
+
+ const { data } = await got.get(`https://www.mhgui.com/comic/${id}/`);
+ const $ = cheerio.load(data);
+
+ if ($('#__VIEWSTATE').length > 0) {
+ const n = LZString.decompressFromBase64($('#__VIEWSTATE').val());
+ if (n) {
+ $('#erroraudit_show').replaceWith(n);
+ $('#__VIEWSTATE').remove();
+ }
+ }
+
+ const bookTitle = $('.book-title > h1').text();
+ const bookIntro = $('#intro-all').text();
+ const coverImgSrc = $('.book-cover img').attr('src');
+ const chapters = getChapters($);
+
+ const genResult = (chapter) => ({
+ link: chapter.link,
+ title: chapter.title,
+ description: `
+ ${chapter.num}
+
+ `.trim(),
+ });
+ ctx.state.data = {
+ title: `看漫画 - ${bookTitle}`,
+ link: `https://www.mhgui.com/comic/${id}/`,
+ description: bookIntro,
+ item: chapters.map(genResult),
+ };
+};
diff --git a/lib/routes/netease/dy.js b/lib/routes/netease/dy.js
index 51364c675a..da60a8472a 100644
--- a/lib/routes/netease/dy.js
+++ b/lib/routes/netease/dy.js
@@ -7,7 +7,7 @@ module.exports = async (ctx) => {
const { id } = ctx.params;
const response = await got.get(`http://dy.163.com/v2/article/list.do?pageNo=1&wemediaId=${id}&size=10`);
-
+ const charset = response.headers['content-type'].split('=')[1];
const list = response.data.data.list;
let author, link;
@@ -26,7 +26,7 @@ module.exports = async (ctx) => {
responseType: 'buffer',
})
).data,
- 'gbk'
+ charset
)
);
const $ = cheerio.load(html, { decodeEntities: false });
diff --git a/lib/routes/netease/dy2.js b/lib/routes/netease/dy2.js
index c9344bbf59..9821cdb97d 100644
--- a/lib/routes/netease/dy2.js
+++ b/lib/routes/netease/dy2.js
@@ -8,7 +8,8 @@ module.exports = async (ctx) => {
const response = await got.get(url, { responseType: 'buffer' });
- const data = iconv.decode(response.data, 'gbk');
+ const charset = response.headers['content-type'].split('=')[1];
+ const data = iconv.decode(response.data, charset);
const $ = cheerio.load(data, { decodeEntities: false });
const list = $('.media_articles ul li')
@@ -39,7 +40,7 @@ module.exports = async (ctx) => {
responseType: 'buffer',
})
).data,
- 'gbk'
+ charset
)
);
content = cheerio.load(itemData, { decodeEntities: false });
diff --git a/lib/routes/nytimes/daily_briefing_chinese.js b/lib/routes/nytimes/daily_briefing_chinese.js
index 663877dd0a..5e241699b8 100644
--- a/lib/routes/nytimes/daily_briefing_chinese.js
+++ b/lib/routes/nytimes/daily_briefing_chinese.js
@@ -28,15 +28,26 @@ module.exports = async (ctx) => {
async (item) =>
await ctx.cache.tryGet(item.link, async () => {
const response = await got.get(item.link);
- const $ = cheerio.load(response.data);
+ const data = response.data;
+ const arr = data.match(/"url":"https:\\u002F\\u002Fstatic(\S*)"articleLarge"/g);
+ const imageLink = arr.map((e) => JSON.parse(`{${e}}`).url);
+
+ const $ = cheerio.load(data);
$('.css-pncxxs.etfikam0').remove();
- $('.css-1xdhyk6.erfvjey0').each((_, item) => {
- item = $(item);
- const link = item.find('img').attr('src');
- item.replaceWith(`
`);
+ // remove 'Credit...'
+ $('.css-1ly73wi.e1tej78p0').remove();
+ $('.css-1xdhyk6.erfvjey0').each((i, e) => $(e).replaceWith(`
`));
+
+ $('.css-1l44abu.ewdxa0s0').each((i, e) => {
+ const figureNote = $(e)
+ .children()
+ .map((i, e) => $(e).text())
+ .get();
+ $(e).replaceWith(`${figureNote.join(' ')}
`);
});
+ const date = $('time').attr('datetime');
+
item.description = $('.meteredContent.css-1r7ky0e').html();
- const date = $('.css-x7rtpa.e16638kd0').attr('datetime');
item.pubDate = parseDate(date);
return item;
})
diff --git a/lib/routes/pjsk/news.js b/lib/routes/pjsk/news.js
new file mode 100644
index 0000000000..8861ced20a
--- /dev/null
+++ b/lib/routes/pjsk/news.js
@@ -0,0 +1,49 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const timezone = require('@/utils/timezone');
+module.exports = async (ctx) => {
+ // 从仓库 Sekai-World/sekai-master-db-diff 获取最新公告
+ const response = await got.get(`https://cdn.jsdelivr.net/gh/Sekai-World/sekai-master-db-diff@master/userInformations.json`);
+ const posts = response.data || [];
+ const list = await Promise.all(
+ posts.map(async (post) => {
+ let link = '';
+ let description = '';
+ const guid = post.displayOrder.toString() + post.id.toString(); // 双ID
+ if (post.path.startsWith('information/')) {
+ // information 公告
+ const path = post.path.replace(/information\/index.html\?id=/, '');
+ link = `https://production-web.sekai.colorfulpalette.org/${post.path}`;
+ try {
+ description = await ctx.cache.tryGet(guid, async () => {
+ const result = await got.get(`https://production-web.sekai.colorfulpalette.org/html/${path}.html`);
+ const $ = cheerio.load(result.data);
+ return $('body').html();
+ });
+ } catch {
+ description = link;
+ }
+ } else {
+ // 外链
+ link = post.path;
+ description = post.title;
+ }
+
+ const item = {
+ title: post.title,
+ link: link,
+ pubDate: timezone(new Date(post.startAt), +8), // +8时区
+ description: description,
+ category: post.informationTag, // event,gacha,music,bug,information
+ guid: guid,
+ };
+ return Promise.resolve(item);
+ })
+ );
+ ctx.state.data = {
+ title: 'Project Sekai - News',
+ link: 'https://pjsekai.sega.jp/',
+ description: 'プロジェクトセカイ カラフルステージ! feat.初音ミク',
+ item: list,
+ };
+};
diff --git a/lib/routes/potplayer/update.js b/lib/routes/potplayer/update.js
new file mode 100644
index 0000000000..a47fdffc1d
--- /dev/null
+++ b/lib/routes/potplayer/update.js
@@ -0,0 +1,42 @@
+const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const language = ctx.params.language || 'en';
+ const bar = '-'.repeat(language.length > 2 ? 74 : 58);
+
+ const rootUrl = 'https://potplayer.daum.net';
+ const currentUrl = `${rootUrl}/?lang=${language}`;
+
+ const link = await ctx.cache.tryGet(currentUrl, async () => {
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+ return response.data.match(//)[1];
+ });
+
+ const response = await got({
+ method: 'get',
+ url: link,
+ });
+
+ const list = response.data.split(`\r\n\r\n${bar}\r\n`);
+
+ const items = list.slice(1, 10).map((item) => {
+ const pubDate = parseDate(item.substr(1, 6), 'YYMMDD');
+
+ return {
+ pubDate,
+ link: currentUrl,
+ title: item.substr(1, 6),
+ description: `${item.split(`\r\n${bar}\r\n`)[1].replace(/\r\n/g, '
')}
`,
+ };
+ });
+
+ ctx.state.data = {
+ title: list[0].split('\r\n\r\n').pop(),
+ link: currentUrl,
+ item: items,
+ };
+};
diff --git a/lib/routes/zcool/discovery.js b/lib/routes/rmlt/idea.js
similarity index 53%
rename from lib/routes/zcool/discovery.js
rename to lib/routes/rmlt/idea.js
index f0f05fb559..b8747bdac4 100644
--- a/lib/routes/zcool/discovery.js
+++ b/lib/routes/rmlt/idea.js
@@ -1,22 +1,29 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
+const timezone = require('@/utils/timezone');
+const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
- const query = ctx.params.query || '0!0!0!0!0!!!!2!-1!1';
+ const category = ctx.params.category || '';
+
+ const rootUrl = 'http://www.rmlt.com.cn';
+ const currentUrl = `${rootUrl}/idea/${category}`;
- const rootUrl = `https://www.zcool.com.cn/discover/${query}`;
const response = await got({
method: 'get',
- url: rootUrl,
+ url: currentUrl,
});
+
const $ = cheerio.load(response.data);
- const list = $('.work-list-box > .card-box')
+ const list = $(category ? '.txt-list' : '.hot-news')
+ .find('a')
+ .slice(0, 15)
.map((_, item) => {
item = $(item);
+
return {
- link: item.find('.card-info-title a[title]').attr('href'),
- author: item.find('.user-avatar').find('a').attr('title'),
+ link: item.attr('href'),
};
})
.get();
@@ -31,9 +38,9 @@ module.exports = async (ctx) => {
});
const content = cheerio.load(detailResponse.data);
- item.title = content('h2').text();
- item.pubDate = new Date(content('.title-time').attr('title').split('创建时间:')[1]).toUTCString();
- item.description = item.link.indexOf('article') < 0 ? content('.work-content-wrap').html() : content('.article-content-wraper').html();
+ item.title = content('.article-title').text();
+ item.description = content('.article-content').html();
+ item.pubDate = timezone(parseDate(content('.date').text(), 'YYYY-MM-DD HH:ss'), +8);
return item;
})
@@ -41,8 +48,8 @@ module.exports = async (ctx) => {
);
ctx.state.data = {
- title: `站酷 - ${query}`,
- link: rootUrl,
+ title: $('title').text(),
+ link: currentUrl,
item: items,
};
};
diff --git a/lib/routes/sspai/author.js b/lib/routes/sspai/author.js
index a5f17f417b..327493520a 100644
--- a/lib/routes/sspai/author.js
+++ b/lib/routes/sspai/author.js
@@ -48,7 +48,7 @@ module.exports = async (ctx) => {
title: item.title.trim(),
description: description,
link: link,
- pubDate: new Date(item.released_at * 1000).toUTCString(),
+ pubDate: new Date(item.released_at * 1000),
author: item.author.nickname,
};
})
diff --git a/lib/routes/sspai/column.js b/lib/routes/sspai/column.js
index 82766c600e..2e5d803ec4 100644
--- a/lib/routes/sspai/column.js
+++ b/lib/routes/sspai/column.js
@@ -50,7 +50,7 @@ module.exports = async (ctx) => {
link: itemUrl,
author: author,
description: description,
- pubDate: new Date(date * 1000).toUTCString(),
+ pubDate: new Date(date * 1000),
};
ctx.cache.set(itemUrl, JSON.stringify(single));
return Promise.resolve(single);
diff --git a/lib/routes/sspai/matrix.js b/lib/routes/sspai/matrix.js
index 1102fbf5c8..65241f90d1 100644
--- a/lib/routes/sspai/matrix.js
+++ b/lib/routes/sspai/matrix.js
@@ -29,7 +29,7 @@ module.exports = async (ctx) => {
title: item.title.trim(),
description: description,
link: link,
- pubDate: new Date(item.released_at * 1000).toUTCString(),
+ pubDate: new Date(item.released_at * 1000),
author: item.author.nickname,
};
})
diff --git a/lib/routes/sspai/shortcutsGallery.js b/lib/routes/sspai/shortcutsGallery.js
index c86f04d804..668d940d12 100644
--- a/lib/routes/sspai/shortcutsGallery.js
+++ b/lib/routes/sspai/shortcutsGallery.js
@@ -12,7 +12,7 @@ module.exports = async (ctx) => {
items.push({
title: shortcut.name,
description: `作者:${shortcut.author_id}
${decodeURIComponent((shortcut.description || '').replace(/\+/g, '%20'))}`,
- pubDate: new Date(shortcut.utime * 1000).toUTCString(),
+ pubDate: new Date(shortcut.utime * 1000),
guid: shortcut.id,
link: shortcut.url,
});
diff --git a/lib/routes/sspai/tag.js b/lib/routes/sspai/tag.js
index 6d337b6b68..906252639b 100644
--- a/lib/routes/sspai/tag.js
+++ b/lib/routes/sspai/tag.js
@@ -3,7 +3,7 @@ const cheerio = require('cheerio');
module.exports = async (ctx) => {
const keyword = ctx.params.keyword;
- const keyword_encode = encodeURIComponent(keyword);
+ const keyword_encode = encodeURIComponent(decodeURIComponent(keyword));
const api_url = `https://sspai.com/api/v1/articles?offset=0&limit=50&has_tag=1&tag=${keyword_encode}&include_total=false`;
const host = `https://beta.sspai.com/tag/${keyword_encode}`;
const resp = await got({
@@ -25,14 +25,14 @@ module.exports = async (ctx) => {
} else {
const response = await got({ method: 'get', url: link, headers: { Referer: host } });
const $ = cheerio.load(response.data);
- description = $('div.content.wangEditor-txt.clock').html();
+ description = $('div.content.wangEditor-txt').html();
ctx.cache.set(key, description);
}
return {
title: item.title.trim(),
description: description,
link: link,
- pubDate: new Date(item.released_at * 1000).toUTCString(),
+ pubDate: new Date(item.released_at * 1000),
author: item.author.nickname,
};
})
diff --git a/lib/routes/sspai/topic.js b/lib/routes/sspai/topic.js
index e9ccd86f16..d1599cb06b 100644
--- a/lib/routes/sspai/topic.js
+++ b/lib/routes/sspai/topic.js
@@ -37,7 +37,7 @@ module.exports = async (ctx) => {
link: itemUrl,
author: author,
description: description,
- pubDate: new Date(date * 1000).toUTCString(),
+ pubDate: new Date(date * 1000),
};
ctx.cache.set(itemUrl, JSON.stringify(single));
return Promise.resolve(single);
diff --git a/lib/routes/sspai/topics.js b/lib/routes/sspai/topics.js
index bc9d2a138a..440e4c2965 100644
--- a/lib/routes/sspai/topics.js
+++ b/lib/routes/sspai/topics.js
@@ -26,7 +26,7 @@ module.exports = async (ctx) => {
title: item.title.trim(),
description: description,
link: link,
- pubDate: new Date(item.released_at * 1000).toUTCString(),
+ pubDate: new Date(item.released_at * 1000),
author: item.author.nickname,
};
})
diff --git a/lib/routes/szse/projectdynamic.js b/lib/routes/szse/projectdynamic.js
new file mode 100644
index 0000000000..9c734f579d
--- /dev/null
+++ b/lib/routes/szse/projectdynamic.js
@@ -0,0 +1,104 @@
+const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const typeMap = {
+ 1: 'IPO',
+ 2: '再融资',
+ 3: '重大资产重组',
+ };
+
+ const stageMap = {
+ 10: '受理',
+ 20: '问询',
+ 30: '上市委会议',
+ 35: '提交注册',
+ 40: '注册结果',
+ 50: '中止',
+ 60: '终止',
+ };
+
+ const statusMap = {
+ 20: '新受理',
+ 30: '已问询',
+ 45: '通过',
+ 44: '未通过',
+ 46: '暂缓审议',
+ 56: '复审通过',
+ 54: '复审不通过',
+ 60: '提交注册',
+ 70: '注册生效',
+ 74: '不予注册',
+ 78: '补充审核',
+ 76: '终止注册',
+ 80: '中止',
+ 90: '审核不通过',
+ 95: '撤回',
+ };
+
+ const type = ctx.params.type || '1';
+ const stage = ctx.params.stage || '0';
+ const status = ctx.params.status || '0';
+
+ const rootUrl = 'http://listing.szse.cn';
+ const apiUrl = `${rootUrl}/api/ras/projectrends/query?bizType=${type}${stage === '0' ? '' : `&stage=${stage}`}${status === '0' ? '' : `&status=${status}`}&pageIndex=0&pageSize=20`;
+
+ const response = await got({
+ method: 'get',
+ url: apiUrl,
+ });
+
+ const list = response.data.data.map((item) => ({
+ title: item.prjid,
+ link: `${rootUrl}/api/ras/projectrends/details?id=${item.prjid}`,
+ }));
+
+ const items = await Promise.all(
+ list.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+
+ const data = detailResponse.data.data;
+ const current = JSON.parse(data.pjdot)['-1'];
+
+ item.link = `${rootUrl}/projectdynamic/ipo/detail/index.html?id=${item.title}`;
+ item.title = `[${data.prjst}] ${data.cmpnm} (${data.cmpsnm})- ${data.csrcind}`;
+
+ item.description =
+ `
${data.cmpnm}
${current.startTime} ${current.name}项目基本信息
| 公司全称 | ` +
+ `${data.cmpnm} | ` +
+ `公司简称 | ${data.cmpsnm} |
` +
+ `| 受理日期 | ${data.acptdt} | ` +
+ `更新日期 | ${data.updtdt} |
` +
+ `| 审核状态 | ${data.prjst} | ` +
+ `预计融资金额(亿元) | ${data.maramt} |
` +
+ `| 保荐机构 | ` +
+ `${data.sprinst} | ` +
+ `保荐代表人 | ${data.sprrep} |
` +
+ `| 会计师事务所 | ` +
+ `${data.acctfm} | ` +
+ `签字会计师 | ${data.acctsgnt} |
` +
+ `| 律师事务所 | ` +
+ `${data.lawfm} | ` +
+ `签字律师 | ${data.lglsgnt} |
` +
+ `| 评估机构 | ${data.evalinst} | ` +
+ `签字评估师 | ${data.evalsgnt} |
` +
+ `| 最近一期审计基准日 | ${data.lastestAuditEndDate} |
`;
+
+ item.pubDate = parseDate(current.startTime, 'YYYY-MM-DD HH:mm:ss');
+
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: `${typeMap[type]}项目动态${status !== '0' ? ` (${statusMap[status]}) ` : stage !== '0' ? ` (${stageMap[stage]}) ` : ''} - 创业板发行上市审核信息公开网站 - 深圳证券交易所`,
+ link: `${rootUrl}/projectdynamic/${type}/index.html`,
+ item: items,
+ };
+};
diff --git a/lib/routes/tanchinese/index.js b/lib/routes/tanchinese/index.js
new file mode 100644
index 0000000000..4ccda29075
--- /dev/null
+++ b/lib/routes/tanchinese/index.js
@@ -0,0 +1,54 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const timezone = require('@/utils/timezone');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const category = ctx.params.category || '';
+
+ const rootUrl = 'http://www.tanchinese.com';
+ const currentUrl = `${rootUrl}${category ? `/archives/${category}` : ''}`;
+
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+
+ const $ = cheerio.load(response.data);
+
+ const list = $('.archive-grid-caption .h2')
+ .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 () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+ const content = cheerio.load(detailResponse.data);
+
+ item.description = content('.article-content').html();
+ item.pubDate = timezone(parseDate(content('#page-content .row .col-xs-12 small').eq(0).text(), 'MMM DD, YYYY'), +8);
+
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: $('title').text(),
+ link: currentUrl,
+ item: items,
+ description: $('meta[name="description"]').attr('content'),
+ };
+};
diff --git a/lib/routes/tieba/user.js b/lib/routes/tieba/user.js
index bbe5c54512..1913c2e15e 100644
--- a/lib/routes/tieba/user.js
+++ b/lib/routes/tieba/user.js
@@ -1,31 +1,36 @@
const got = require('@/utils/got');
+const cheerio = require('cheerio');
module.exports = async (ctx) => {
const uid = ctx.params.uid;
-
- const rootUrl = 'https://tieba.baidu.com';
- const userUrl = `${rootUrl}/home/get/getthread?un=${uid}&pn=1&ie=utf8`;
const response = await got({
method: 'get',
- url: userUrl,
+ url: `https://tieba.baidu.com/home/main?un=${uid}`,
});
+ const data = response.data;
+
+ const $ = cheerio.load(data);
+ const name = $('span.userinfo_username').text();
+ const list = $('div.n_right.clearfix');
+ let imgurl;
+
ctx.state.data = {
- title: `${uid}的贴子 - 百度贴吧`,
- link: `${rootUrl}/home/main?un=${uid}`,
- item: response.data.data.thread_list.map((item) => {
- let media = '';
- if (item.media) {
- for (const m of item.media) {
- media += `
`;
- }
- }
- return {
- title: item.title,
- description: `${item.content}
${media}`,
- pubDate: new Date(item.create_time * 1000).toUTCString(),
- link: `https://tieba.baidu.com/p/${item.thread_id}?pid=${item.post_id}&cid=#${item.post_id}`,
- };
- }),
+ title: `${name} 的贴吧`,
+ link: `https://tieba.baidu.com/home/main?un=${uid}`,
+ item:
+ list &&
+ list
+ .map((index, item) => {
+ item = $(item).find('.n_contain');
+ imgurl = item.find('ul.n_media.clearfix img').attr('original');
+ return {
+ title: item.find('div.thread_name a').attr('title'),
+ pubDate: Date.parse(item.parent().find('div .n_post_time').text()),
+ description: `${item.find('div.n_txt').text()}
`,
+ link: item.find('div.thread_name a').attr('href'),
+ };
+ })
+ .get(),
};
};
diff --git a/lib/routes/twmanhuagui/comic.js b/lib/routes/twmanhuagui/comic.js
new file mode 100644
index 0000000000..090645acfe
--- /dev/null
+++ b/lib/routes/twmanhuagui/comic.js
@@ -0,0 +1,53 @@
+const { resolve } = require('url');
+const cheerio = require('cheerio');
+const got = require('@/utils/got');
+const LZString = require('lz-string');
+
+const getChapters = ($) =>
+ $('.chapter-list > ul')
+ .toArray()
+ .reverse()
+ .reduce((acc, curr) => acc.concat($(curr).children('li').toArray()), [])
+ .map((ele) => {
+ const a = $(ele).children('a');
+ return {
+ link: resolve('https://tw.manhuagui.com/', a.attr('href')),
+ title: a.attr('title'),
+ num: a.find('i').text(),
+ };
+ });
+
+module.exports = async (ctx) => {
+ const { id } = ctx.params;
+
+ const { data } = await got.get(`https://tw.manhuagui.com/comic/${id}/`);
+ const $ = cheerio.load(data);
+
+ if ($('#__VIEWSTATE').length > 0) {
+ const n = LZString.decompressFromBase64($('#__VIEWSTATE').val());
+ if (n) {
+ $('#erroraudit_show').replaceWith(n);
+ $('#__VIEWSTATE').remove();
+ }
+ }
+
+ const bookTitle = $('.book-title > h1').text();
+ const bookIntro = $('#intro-all').text();
+ const coverImgSrc = $('.book-cover img').attr('src');
+ const chapters = getChapters($);
+
+ const genResult = (chapter) => ({
+ link: chapter.link,
+ title: chapter.title,
+ description: `
+ ${chapter.num}
+
+ `.trim(),
+ });
+ ctx.state.data = {
+ title: `看漫画 - ${bookTitle}`,
+ link: `https://tw.manhuagui.com/comic/${id}/`,
+ description: bookIntro,
+ item: chapters.map(genResult),
+ };
+};
diff --git a/lib/routes/universities/harvard/health/blog.js b/lib/routes/universities/harvard/health/blog.js
new file mode 100644
index 0000000000..6f4dd59abc
--- /dev/null
+++ b/lib/routes/universities/harvard/health/blog.js
@@ -0,0 +1,52 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+module.exports = async (ctx) => {
+ const rootUrl = 'https://www.health.harvard.edu';
+ const currentUrl = `${rootUrl}/blog`;
+
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+
+ const $ = cheerio.load(response.data);
+
+ const list = $('.text-2xl')
+ .slice(0, 10)
+ .map((_, item) => {
+ item = $(item).parent();
+
+ 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 () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+ const content = cheerio.load(detailResponse.data);
+
+ const date = item.link.substr(item.link.length - 12, 8);
+
+ item.description = content('.content-repository-content').html();
+ item.pubDate = Date.parse(`${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`);
+
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: 'Harvard Health Blog',
+ link: currentUrl,
+ item: items,
+ };
+};
diff --git a/lib/routes/universities/scut/seie/news_center.js b/lib/routes/universities/scut/seie/news_center.js
new file mode 100644
index 0000000000..5ed2c01f18
--- /dev/null
+++ b/lib/routes/universities/scut/seie/news_center.js
@@ -0,0 +1,58 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const rootUrl = 'https://www2.scut.edu.cn';
+ const url = `${rootUrl}/ee/16285/list.htm`;
+ const response = await got.get(url);
+ const $ = cheerio.load(response.data);
+
+ const list = $('.news_ul li');
+ const articleList = list
+ .map((_, item) => {
+ item = $(item);
+ const titleElement = item.find('.news_title a');
+ return {
+ title: titleElement.attr('title'),
+ link: titleElement.attr('href'),
+ pubDate: parseDate(item.find('.news_meta').text(), 'YYYY-MM-DD'),
+ };
+ })
+ .get();
+
+ const items = await Promise.all(
+ articleList.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: `${rootUrl}${item.link}`,
+ });
+ const content = cheerio.load(detailResponse.data, { decodeEntities: false });
+
+ content('.wp_articlecontent *').each((_, child) => {
+ const childElem = content(child);
+ childElem.removeAttr('style');
+ childElem.removeAttr('lang');
+ childElem.removeAttr('original-src');
+ childElem.removeAttr('sudyfile-attr');
+ childElem.removeAttr('data-layer');
+ if ((!childElem.text().replace('\n', '').trim().length && !childElem.has('img')) || childElem.attr('name') === '_GoBack' || childElem.is('style')) {
+ childElem.remove();
+ }
+ });
+
+ const contentHTML = content('.wp_articlecontent').html();
+ item.description = contentHTML.replace(/^(
)+|(
)+$/g, '').trim();
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: '华南理工大学电子与信息学院 - 新闻速递',
+ link: url,
+ item: items,
+ };
+};
diff --git a/lib/routes/universities/xjtu/ee.js b/lib/routes/universities/xjtu/ee.js
new file mode 100644
index 0000000000..7cba69ac8b
--- /dev/null
+++ b/lib/routes/universities/xjtu/ee.js
@@ -0,0 +1,45 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const timezone = require('@/utils/timezone');
+
+module.exports = async (ctx) => {
+ const id = ctx.params.id || '1124';
+ const rootUrl = `http://ee.xjtu.edu.cn/list.jsp?urltype=tree.TreeTempUrl&wbtreeid=${id}`;
+ const baseUrl = 'http://ee.xjtu.edu.cn';
+
+ const list_response = await got.get(rootUrl);
+ const $ = cheerio.load(list_response.data);
+
+ const feed_title = $('span.windowstyle67278', "div[class='list_right fr']").text().trim();
+
+ const list = $("div[class='list_right fr'] ul li")
+ .slice(0, 10)
+ .map((_, item) => {
+ item = $(item);
+ const a = item.find('a');
+ const date = parseDate(item.find('span').text());
+ return {
+ title: a.text(),
+ link: new URL(a.attr('href'), baseUrl),
+ pubDate: timezone(date, +8),
+ };
+ })
+ .get();
+
+ ctx.state.data = {
+ title: `西安交通大学电气学院 - ${feed_title}`,
+ link: baseUrl,
+ item: await Promise.all(
+ list.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ const res = await got.get(item.link);
+ const content = cheerio.load(res.data);
+ item.description = content('td.contentstyle67362', 'form').html();
+ return item;
+ })
+ )
+ ),
+ };
+};
diff --git a/lib/routes/universities/xjtu/job.js b/lib/routes/universities/xjtu/job.js
new file mode 100644
index 0000000000..ce2da33838
--- /dev/null
+++ b/lib/routes/universities/xjtu/job.js
@@ -0,0 +1,51 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const timezone = require('@/utils/timezone');
+
+module.exports = async (ctx) => {
+ const subpath = ctx.params.subpath || 'zxtg';
+ const arr = {
+ zxtg: '中心通告',
+ xdsgwy: '选调生|公务员',
+ gjzzsx: '国际组织实习',
+ xwzx: '新闻资讯',
+ hdyjz: '活动与讲座',
+ };
+ const rootUrl = `https://job.xjtu.edu.cn/news.do;?ext=${arr[subpath]}`;
+ const baseUrl = 'https://job.xjtu.edu.cn';
+
+ const list_response = await got.get(rootUrl);
+ const $ = cheerio.load(list_response.data);
+
+ const list = $('div.jsnr ul li')
+ .slice(0, 10)
+ .map((_, item) => {
+ item = $(item);
+ const a = item.find('a');
+ return {
+ title: a.find('span').text(),
+ link: new URL(a.attr('href'), baseUrl),
+ };
+ })
+ .get();
+
+ ctx.state.data = {
+ title: `西安交通大学就业网-${arr[subpath]}`,
+ link: baseUrl,
+ item: await Promise.all(
+ list.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ const res = await got.get(item.link);
+ const content = cheerio.load(res.data);
+ item.description = content('div.jsnr').html();
+ const dateStr = content('div.jsnrly span').eq(1).text();
+ const date = parseDate(dateStr, 'YYYY MM DD HH mm', 'zh-cn');
+ item.pubDate = timezone(date, +8);
+ return item;
+ })
+ )
+ ),
+ };
+};
diff --git a/lib/routes/xueqiu/stock_comments.js b/lib/routes/xueqiu/stock_comments.js
new file mode 100644
index 0000000000..47e4550c9f
--- /dev/null
+++ b/lib/routes/xueqiu/stock_comments.js
@@ -0,0 +1,61 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const template = require('art-template');
+const { parseDate } = require('@/utils/parse-date');
+
+const description_template = `
+
+ {{item.user.screen_name}}:
+
+
+{{item.text}}
+
+{{if item.retweeted_status}}
+
+{{item.retweeted_status.text}}
+{{else}}
+
+{{/if}}
+
+ ----来源于:{{item.source}}
+
`;
+
+module.exports = async (ctx) => {
+ const id = ctx.params.id;
+ const titleLength = ctx.params.titleLength || 30;
+
+ const res = await got({
+ method: 'get',
+ url: `https://xueqiu.com/query/v1/symbol/search/status?u=11111&count=100&comment=0&symbol=${id}&source=all&sort=time`,
+ });
+
+ // 获取stock_name
+ const stock_name = await ctx.cache.tryGet(`stock_name_${id}`, async () => {
+ const res = await got({
+ method: 'get',
+ url: `https://xueqiu.com/S/${id}`,
+ });
+ const $ = cheerio.load(res.data); // 使用 cheerio 加载返回的 HTML
+ return $('.stock-name').text().split('(')[0];
+ });
+
+ const data = res.data.list;
+ ctx.state.data = {
+ title: `${id} ${stock_name} - 评论`,
+ link: `https://xueqiu.com/S/${id}`,
+ description: `${stock_name} - 评论`,
+ item: data.map((item) => {
+ let link = `https://xueqiu.com${item.target}`;
+ if (item.quote_cards) {
+ link = item.quote_cards[0].target_url;
+ }
+ const description = template.render(description_template, { item: item });
+ return {
+ title: item.title !== '' ? item.title : item.text.replace(/<[^>]+>/g, '').slice(0, titleLength),
+ description: description,
+ pubDate: parseDate(item.created_at),
+ link,
+ };
+ }),
+ };
+};
diff --git a/lib/routes/yomiuri/news.js b/lib/routes/yomiuri/news.js
index e61dcabc96..18cc5ef55c 100644
--- a/lib/routes/yomiuri/news.js
+++ b/lib/routes/yomiuri/news.js
@@ -1,5 +1,6 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
+const timezone = require('@/utils/timezone');
module.exports = async (ctx) => {
const category = ctx.params.category;
@@ -12,30 +13,99 @@ module.exports = async (ctx) => {
const data = response.data;
const $ = cheerio.load(data);
- let category_name = '';
+ let categoryName;
let list = null;
if (category === 'news') {
- category_name = '総合';
- list = $('ul.news-top-upper-content-topics-content-list.p-list').children('li').not('.p-member-only');
+ categoryName = '新着・速報';
+ const urlPrefix = 'https://www.yomiuri.co.jp/y_ajax/';
+
+ // get list1
+ const param1 = $('input#latest_list_news_other_params').val();
+ const response1 = await got({
+ method: 'get',
+ url: urlPrefix + 'latest_list_news/' + param1 + '/?action=latest_list_news&others=' + param1,
+ });
+ const data1 = response1.data;
+ const firstArticleList = cheerio.load(data1);
+
+ // get list2
+ const param2 = $('input#latest_list_news_other_params2').val();
+ const response2 = await got({
+ method: 'get',
+ url: urlPrefix + 'latest_list_news2/' + param2 + '/?action=latest_list_news2&others=' + param2,
+ });
+ const data2 = response2.data;
+ const secondArticleList = cheerio.load(data2);
+ list = secondArticleList('article').add(firstArticleList('article'));
+
+ list = list.map((index, item) => {
+ item = $(item);
+ // remove matome title
+ const matomeTitle = item.find('div.c-matome-title');
+ if (matomeTitle.length !== 0) {
+ matomeTitle.remove();
+ }
+ // remove member only
+ const lockedIcon = item.find('svg[class=icon-locked]');
+ if (lockedIcon.length === 0) {
+ return item;
+ } else {
+ return null;
+ }
+ });
} else {
- category_name = $('h1.p-header-category-current-title').text();
- list = $('div.p-category-organization,.p-category-time-series').find('li').not('.p-member-only').not('.p-ad-list-item');
+ let parentSelector = 'div.p-category-organization,.p-category-time-series';
+ // igoshougi channel sepcial div selector
+ if (category === 'igoshougi') {
+ parentSelector = 'div.uni-news-igoshougi-top';
+ }
+ categoryName = $('h1.p-header-category-current-title,h1.p-header-category-content-title').text();
+ // p-header-category-content-title
+ list = $(parentSelector).find('li').not('.p-member-only').not('.p-ad-list-item');
+ list = list.map((index, item) => {
+ item = $(item);
+ // remove matome title
+ const matomeTitle = item.find('div.c-matome-title');
+ if (matomeTitle.length !== 0) {
+ matomeTitle.remove();
+ }
+ return item;
+ });
+ }
+
+ // format category name
+ if (categoryName !== '') {
+ categoryName = ' - ' + categoryName.trim();
}
const items = await Promise.all(
list
.map(async (index, item) => {
item = $(item);
- const link = item.find('a').attr('href');
+
+ let link = '';
+ if (categoryName === '新着・速報') {
+ link = item.find('h3').children('a').attr('href');
+ } else {
+ link = item.find('a').attr('href');
+ }
+
const description = await ctx.cache.tryGet(link, async () => {
const response = await got.get(link);
const $ = cheerio.load(response.data);
- return $('div.p-main-contents').html();
+ const mainContent = $('div.p-main-contents');
+ // remove articles recomended
+ const recommendNode = mainContent.find('aside.ev-article-manual-related__article-inline');
+ if (recommendNode.length !== 0) {
+ recommendNode.remove();
+ }
+ return mainContent.html();
});
+
let tag = '';
- if (category_name === '総合') {
+ if (categoryName === '新着・速報') {
const tag_table = {
- news: '総合',
+ news: '新着・速報',
national: '社会',
politics: '政治',
economy: '経済',
@@ -49,14 +119,17 @@ module.exports = async (ctx) => {
local: '地域',
editorial: '社説',
medical: '医療・健康',
+ olympic: 'オリンピック',
};
const tag_value = tag_table[link.split('/')[3]];
tag = tag_value ? tag_value : 'その他';
tag = '[' + tag + '] ';
}
+
return {
title: tag + item.find('a').text(),
description,
+ pubDate: timezone(new Date(item.find('time').prop('datetime')), +9),
link,
};
})
@@ -64,7 +137,7 @@ module.exports = async (ctx) => {
);
ctx.state.data = {
- title: '読売新聞-' + category_name,
+ title: '読売新聞' + categoryName,
link: url,
item: items,
};
diff --git a/lib/routes/zcool/discover.js b/lib/routes/zcool/discover.js
new file mode 100644
index 0000000000..8d02b47393
--- /dev/null
+++ b/lib/routes/zcool/discover.js
@@ -0,0 +1,140 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const locations = require('./locations');
+
+module.exports = async (ctx) => {
+ const categories = {
+ 0: '精选',
+ 8: '平面',
+ 1: '插画',
+ 17: 'UI',
+ 607: '网页',
+ 33: '摄影',
+ 24: '三维',
+ 610: '影视',
+ 609: '空间',
+ 499: '工业/产品',
+ 608: '动漫',
+ 612: '纯艺术',
+ 611: '手工艺',
+ 613: '服装',
+ 44: '其他',
+ };
+
+ const subCategories = {
+ 0: { 617: '运营设计', 9: '包装', 30: '动画/影视', 34: '人像摄影', 2: '商业插画', 616: '电商', 757: 'APP界面', 292: '艺术插画', 637: '家装设计', 10: '海报', 809824: '文章' },
+ 8: { 9: '包装', 10: '海报', 15: '品牌', 779: 'IP形象', 14: '字体/字形', 13: 'Logo', 12: '书籍/画册', 534: '宣传物料', 624: '图案', 625: '信息图表', 626: 'PPT/Keynote', 11: '其他平面', 809: '文章' },
+ 1: { 2: '商业插画', 5: '概念设定', 685: '游戏原画', 631: '绘本', 684: '儿童插画', 292: '艺术插画', 7: '创作习作', 3: '新锐潮流插画', 4: '像素画', 819: '文章' },
+ 17: { 757: 'APP界面', 692: '游戏UI', 621: '软件界面', 20: '图标', 19: '主题/皮肤', 623: '交互/UE', 797: '动效设计', 21: '闪屏/壁纸', 23: '其他UI ', 822: '文章' },
+ 607: { 616: '电商', 614: '企业官网', 693: '游戏/娱乐', 617: '运营设计', 777: '移动端网页', 615: '门户网站', 618: '个人网站', 620: '其他网页', 823: '文章' },
+ 33: { 34: '人像摄影', 35: '风光摄影', 36: '人文/纪实摄影', 825: '美食摄影', 686: '产品摄影', 38: '环境/建筑摄影', 800: '时尚/艺术摄影', 687: '修图/后期', 40: '宠物摄影', 808: '婚礼摄影', 43: '其他摄影', 810: '文章' },
+ 24: { 30: '动画/影视', 25: '机械/交通', 27: '人物/生物', 807: '产品', 26: '场景', 29: '建筑/空间', 32: '其他三维', 818: '文章' },
+ 610: { 645: '短片', 649: 'Motion Graphic', 804: '宣传片', 646: '影视后期', 647: '栏目片头', 644: 'MV', 650: '设定/分镜', 651: '其他影视', 817: '文章' },
+ 609: { 637: '家装设计', 811: '酒店餐饮设计', 641: '商业空间设计', 636: '建筑设计', 638: '舞台美术', 639: '展陈设计', 640: '景观设计', 642: '其他空间', 812: '文章' },
+ 499: { 508: '生活用品', 506: '电子产品', 509: '交通工具', 511: '工业用品/机械', 510: '人机交互', 689: '玩具', 514: '其他工业/产品', 813: '文章' },
+ 608: { 628: '短篇/格漫', 629: '中/长篇漫画', 632: '网络表情', 627: '单幅漫画', 633: '动画片', 635: '其他动漫', 820: '文章' },
+ 612: { 659: '绘画', 662: '雕塑', 668: '书法', 657: '实验艺术', 821: '文章' },
+ 611: { 654: '工艺品设计', 656: '手办/模玩', 756: '首饰设计', 658: '其他手工艺', 816: '文章' },
+ 613: { 672: '休闲/流行服饰', 671: '正装/礼服', 814: '传统/民族服饰', 677: '配饰', 676: '鞋履设计', 673: '儿童服饰', 680: '其他服装', 815: '文章' },
+ 44: { 417: '文案/策划', 798: 'VR设计', 683: '独立游戏', 45: '其他', 824: '文章' },
+ };
+
+ const queries = {
+ cate: '0',
+ subCate: ctx.params.subCate || '0',
+ city: ctx.params.city || '0',
+ college: ctx.params.college || '0',
+ recommendLevel: ctx.params.recommendLevel || '2',
+ sort: ctx.params.sort || '9',
+ };
+
+ let query = ctx.params.query || '';
+
+ if (query.indexOf('=') > -1) {
+ for (const q of query.split('&')) {
+ const kv = q.split('=');
+ queries[kv[0]] = kv[1];
+ }
+ queries.limit = '20';
+ queries.page = '1';
+ } else {
+ switch (query) {
+ case 'home':
+ queries.recommendLevel = '3';
+ break;
+ case 'all':
+ queries.recommendLevel = '1';
+ break;
+ case 'article':
+ queries.subCate = '809824';
+ queries.recommendLevel = '2';
+ break;
+ case 'editor' || 'edit':
+ queries.recommendLevel = '2';
+ break;
+ default:
+ queries.cate = ctx.params.query || '0';
+ }
+ }
+
+ query = '';
+
+ for (const q in queries) {
+ if (q === 'city') {
+ queries[q] = queries[q] in locations ? locations[queries.city].toString() : (queries[q] = '0');
+ }
+ query += `${q}=${queries[q]}&`;
+ }
+
+ query = query.substr(0, query.length - 1);
+
+ const rootUrl = 'https://www.zcool.com.cn';
+ const currentUrl = `${rootUrl}/discover.json?${query}`;
+
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+
+ const list = response.data.data.data.map((item) => ({
+ title: item.object.title,
+ link: item.object.pageUrl,
+ pubDate: new Date(item.object.publishTime),
+ author: item.object.creatorObj.username,
+ }));
+
+ const items = await Promise.all(
+ list.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+ const content = cheerio.load(detailResponse.data);
+
+ content('.prism-player, .image-info-icons').remove();
+
+ const videos = detailResponse.data.match(/source: '(https:\/\/video\.zcool\.cn\/.*)',/g);
+
+ let i = 0;
+ content('.video-content-box').each(function () {
+ if (i >= videos.length) {
+ return;
+ }
+ content(this).append(`