diff --git a/docs/picture.md b/docs/picture.md
index 4bb9cd8066..10d5741551 100644
--- a/docs/picture.md
+++ b/docs/picture.md
@@ -16,6 +16,20 @@ pageClass: routes
+## CNU 视觉联盟
+
+### 每日精选
+
+
+
+### 发现
+
+
+
+| 热门 | 推荐 | 最新 |
+| ---- | --------- | ------ |
+| hot | recommend | recent |
+
## Dilbert Comic Strip
diff --git a/lib/router.js b/lib/router.js
index ca0f7722f9..1eecfdc0d5 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -1763,4 +1763,8 @@ router.get('/taptap/review/:id/:order?', require('./routes/taptap/review'));
// lofter
router.get('/lofter/tag/:name/:type?', require('./routes/lofter/tag'));
+// CNU视觉联盟
+router.get('/cnu/selected', require('./routes/cnu/selected'));
+router.get('/cnu/discovery/:type?/:category?', require('./routes/cnu/discovery'));
+
module.exports = router;
diff --git a/lib/routes/cnu/discovery.js b/lib/routes/cnu/discovery.js
new file mode 100644
index 0000000000..1409cb7992
--- /dev/null
+++ b/lib/routes/cnu/discovery.js
@@ -0,0 +1,62 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const utils = require('./utils');
+
+const types = {
+ hot: '热门',
+ recommend: '推荐',
+ recent: '最新',
+};
+
+module.exports = async (ctx) => {
+ const type = ctx.params.type ? ctx.params.type : 'hot';
+ const category = ctx.params.category ? ctx.params.category : '0';
+ const category_name = category === '0' ? '全部' : category;
+
+ const url = `http://www.cnu.cc/discoveryPage/${type}-${encodeURIComponent(category)}`;
+
+ const list_response = await got.get(url);
+ const $ = cheerio.load(list_response.data);
+
+ const list = $('.grid-item.work-thumbnail').toArray();
+
+ const out = await Promise.all(
+ list.map(async (item) => {
+ const $ = cheerio.load(item);
+ const title = $('.title');
+ const link = $('a.thumbnail').attr('href');
+
+ const cache = await ctx.cache.get(link);
+ if (cache) {
+ return Promise.resolve(JSON.parse(cache));
+ }
+
+ const rssitem = {
+ title: title.text().trim(),
+ link: link,
+ };
+
+ try {
+ const response = await got.get(link);
+ const result = utils.parseContent(response.data);
+ if (!result) {
+ return Promise.resolve('');
+ }
+
+ rssitem.author = result.author;
+ rssitem.description = result.description;
+ rssitem.pubDate = result.pubDate;
+ } catch (err) {
+ return Promise.resolve('');
+ }
+ ctx.cache.set(link, JSON.stringify(rssitem));
+ return Promise.resolve(rssitem);
+ })
+ );
+
+ ctx.state.data = {
+ title: `CNU视觉联盟 - ${types[type]} - ${category_name}`,
+ link: url,
+ item: out.filter((item) => item !== ''),
+ };
+};
diff --git a/lib/routes/cnu/selected.js b/lib/routes/cnu/selected.js
new file mode 100644
index 0000000000..f51b14d756
--- /dev/null
+++ b/lib/routes/cnu/selected.js
@@ -0,0 +1,52 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const utils = require('./utils');
+
+module.exports = async (ctx) => {
+ const url = 'http://www.cnu.cc/selectedPage';
+
+ const list_response = await got.get(url);
+ const $ = cheerio.load(list_response.data);
+
+ const list = $('.selectedUL > .bannerLi').toArray();
+
+ const out = await Promise.all(
+ list.map(async (item) => {
+ const $ = cheerio.load(item);
+ const title = $('.workTitle');
+ const link = title.parent().attr('href');
+
+ const cache = await ctx.cache.get(link);
+ if (cache) {
+ return Promise.resolve(JSON.parse(cache));
+ }
+
+ const rssitem = {
+ title: title.text().trim(),
+ link: link,
+ };
+
+ try {
+ const response = await got.get(link);
+ const result = utils.parseContent(response.data);
+ if (!result) {
+ return Promise.resolve('');
+ }
+
+ rssitem.author = result.author;
+ rssitem.description = result.description;
+ rssitem.pubDate = result.pubDate;
+ } catch (err) {
+ return Promise.resolve('');
+ }
+ ctx.cache.set(link, JSON.stringify(rssitem));
+ return Promise.resolve(rssitem);
+ })
+ );
+
+ ctx.state.data = {
+ title: `CNU视觉联盟 - 每日精选`,
+ link: url,
+ item: out.filter((item) => item !== ''),
+ };
+};
diff --git a/lib/routes/cnu/utils.js b/lib/routes/cnu/utils.js
new file mode 100644
index 0000000000..9827ab58d2
--- /dev/null
+++ b/lib/routes/cnu/utils.js
@@ -0,0 +1,28 @@
+const cheerio = require('cheerio');
+
+const pic_base_url = 'http://img.cnu.cc/uploads/images/920/';
+
+const parseContent = (htmlString) => {
+ const $ = cheerio.load(htmlString);
+
+ const author = $('.author-info > a');
+ const time = $('.author-info > .timeago');
+ const content = $('#work_body');
+
+ const imgs_json = JSON.parse($('#imgs_json').text());
+ for (let k = 0; k < imgs_json.length; k++) {
+ content.append(`
`);
+ content.append(`${imgs_json[k].content}
`);
+ content.append(`${imgs_json[k].text}
`);
+ }
+
+ return {
+ author: author.text().trim(),
+ description: content.html(),
+ pubDate: new Date(time.text().trim()),
+ };
+};
+
+module.exports = {
+ parseContent,
+};