mirror of
https://github.com/DIYgod/RSSHub.git
synced 2025-12-15 01:30:33 +08:00
feat(route): add yunnan normal university (#8097)
This commit is contained in:
@@ -2169,6 +2169,15 @@ type 列表:
|
||||
|
||||
</Route>
|
||||
|
||||
## 云南师范大学
|
||||
|
||||
### 继续教育学院
|
||||
|
||||
#### 新闻
|
||||
|
||||
<Route author="SettingDust" example="/ynnu/edu/news" path="/ynnu/edu/news" >
|
||||
</Route>
|
||||
|
||||
## 浙江大学
|
||||
|
||||
### 普通栏目 如学术 / 图片 / 新闻等
|
||||
|
||||
@@ -803,6 +803,9 @@ router.get('/ynu/grs/qttz/:category', lazyloadRouteHandler('./routes/universitie
|
||||
router.get('/ynu/jwc/:category', lazyloadRouteHandler('./routes/universities/ynu/jwc/zytz'));
|
||||
router.get('/ynu/home', lazyloadRouteHandler('./routes/universities/ynu/home/main'));
|
||||
|
||||
// 云南师范大学
|
||||
router.get('/ynnu/edu/news', lazyloadRouteHandler('./routes/universities/ynnu/edu/news'));
|
||||
|
||||
// 昆明理工大学
|
||||
router.get('/kmust/jwc/:type?', lazyloadRouteHandler('./routes/universities/kmust/jwc'));
|
||||
router.get('/kmust/job/careers/:type?', lazyloadRouteHandler('./routes/universities/kmust/job/careers'));
|
||||
|
||||
351
lib/routes/universities/ynnu/edu/base64.js
Normal file
351
lib/routes/universities/ynnu/edu/base64.js
Normal file
@@ -0,0 +1,351 @@
|
||||
// https://gitee.com/slice30k/base64-js
|
||||
|
||||
const BASE64_MAPPING = [
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F',
|
||||
'G',
|
||||
'H',
|
||||
'I',
|
||||
'J',
|
||||
'K',
|
||||
'L',
|
||||
'M',
|
||||
'N',
|
||||
'O',
|
||||
'P',
|
||||
'Q',
|
||||
'R',
|
||||
'S',
|
||||
'T',
|
||||
'U',
|
||||
'V',
|
||||
'W',
|
||||
'X',
|
||||
'Y',
|
||||
'Z',
|
||||
'a',
|
||||
'b',
|
||||
'c',
|
||||
'd',
|
||||
'e',
|
||||
'f',
|
||||
'g',
|
||||
'h',
|
||||
'i',
|
||||
'j',
|
||||
'k',
|
||||
'l',
|
||||
'm',
|
||||
'n',
|
||||
'o',
|
||||
'p',
|
||||
'q',
|
||||
'r',
|
||||
's',
|
||||
't',
|
||||
'u',
|
||||
'v',
|
||||
'w',
|
||||
'x',
|
||||
'y',
|
||||
'z',
|
||||
'0',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'+',
|
||||
'/',
|
||||
];
|
||||
const URLSAFE_BASE64_MAPPING = [
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F',
|
||||
'G',
|
||||
'H',
|
||||
'I',
|
||||
'J',
|
||||
'K',
|
||||
'L',
|
||||
'M',
|
||||
'N',
|
||||
'O',
|
||||
'P',
|
||||
'Q',
|
||||
'R',
|
||||
'S',
|
||||
'T',
|
||||
'U',
|
||||
'V',
|
||||
'W',
|
||||
'X',
|
||||
'Y',
|
||||
'Z',
|
||||
'a',
|
||||
'b',
|
||||
'c',
|
||||
'd',
|
||||
'e',
|
||||
'f',
|
||||
'g',
|
||||
'h',
|
||||
'i',
|
||||
'j',
|
||||
'k',
|
||||
'l',
|
||||
'm',
|
||||
'n',
|
||||
'o',
|
||||
'p',
|
||||
'q',
|
||||
'r',
|
||||
's',
|
||||
't',
|
||||
'u',
|
||||
'v',
|
||||
'w',
|
||||
'x',
|
||||
'y',
|
||||
'z',
|
||||
'0',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'-',
|
||||
'_',
|
||||
];
|
||||
|
||||
const _toBinary = function (ascii) {
|
||||
const binary = [];
|
||||
while (ascii > 0) {
|
||||
const b = ascii % 2;
|
||||
ascii = Math.floor(ascii / 2);
|
||||
binary.push(b);
|
||||
}
|
||||
binary.reverse();
|
||||
return binary;
|
||||
};
|
||||
|
||||
const _toDecimal = function (binary) {
|
||||
let dec = 0;
|
||||
let p = 0;
|
||||
for (let i = binary.length - 1; i >= 0; --i) {
|
||||
const b = binary[i];
|
||||
if (b === 1) {
|
||||
dec += Math.pow(2, p);
|
||||
}
|
||||
++p;
|
||||
}
|
||||
return dec;
|
||||
};
|
||||
|
||||
const _toUTF8Binary = function (c, binaryArray) {
|
||||
const mustLen = 8 - (c + 1) + (c - 1) * 6;
|
||||
const fatLen = binaryArray.length;
|
||||
let diff = mustLen - fatLen;
|
||||
while (--diff >= 0) {
|
||||
binaryArray.unshift(0);
|
||||
}
|
||||
const binary = [];
|
||||
let _c = c;
|
||||
while (--_c >= 0) {
|
||||
binary.push(1);
|
||||
}
|
||||
binary.push(0);
|
||||
let i = 0;
|
||||
const len = 8 - (c + 1);
|
||||
for (; i < len; ++i) {
|
||||
binary.push(binaryArray[i]);
|
||||
}
|
||||
|
||||
for (let j = 0; j < c - 1; ++j) {
|
||||
binary.push(1);
|
||||
binary.push(0);
|
||||
let sum = 6;
|
||||
while (--sum >= 0) {
|
||||
binary.push(binaryArray[i++]);
|
||||
}
|
||||
}
|
||||
return binary;
|
||||
};
|
||||
|
||||
const _toBinaryArray = function (str) {
|
||||
let binaryArray = [];
|
||||
let i = 0;
|
||||
const len = str.length;
|
||||
for (; i < len; ++i) {
|
||||
const unicode = str.charCodeAt(i);
|
||||
const _tmpBinary = _toBinary(unicode);
|
||||
if (unicode < 0x80) {
|
||||
let _tmpdiff = 8 - _tmpBinary.length;
|
||||
while (--_tmpdiff >= 0) {
|
||||
_tmpBinary.unshift(0);
|
||||
}
|
||||
binaryArray = binaryArray.concat(_tmpBinary);
|
||||
} else if (unicode >= 0x80 && unicode <= 0x7ff) {
|
||||
binaryArray = binaryArray.concat(_toUTF8Binary(2, _tmpBinary));
|
||||
} else if (unicode >= 0x800 && unicode <= 0xffff) {
|
||||
// UTF-8 3byte
|
||||
binaryArray = binaryArray.concat(_toUTF8Binary(3, _tmpBinary));
|
||||
} else if (unicode >= 0x10000 && unicode <= 0x1fffff) {
|
||||
// UTF-8 4byte
|
||||
binaryArray = binaryArray.concat(_toUTF8Binary(4, _tmpBinary));
|
||||
} else if (unicode >= 0x200000 && unicode <= 0x3ffffff) {
|
||||
// UTF-8 5byte
|
||||
binaryArray = binaryArray.concat(_toUTF8Binary(5, _tmpBinary));
|
||||
} else if (unicode >= 4000000 && unicode <= 0x7fffffff) {
|
||||
// UTF-8 6byte
|
||||
binaryArray = binaryArray.concat(_toUTF8Binary(6, _tmpBinary));
|
||||
}
|
||||
}
|
||||
return binaryArray;
|
||||
};
|
||||
|
||||
const _toUnicodeStr = function (binaryArray) {
|
||||
let unicode;
|
||||
let unicodeBinary = [];
|
||||
let str = '';
|
||||
let i = 0;
|
||||
const len = binaryArray.length;
|
||||
for (; i < len; i++) {
|
||||
if (binaryArray[i] === 0) {
|
||||
unicode = _toDecimal(binaryArray.slice(i, i + 8));
|
||||
str += String.fromCharCode(unicode);
|
||||
i += 8;
|
||||
} else {
|
||||
let sum = 0;
|
||||
while (i < len) {
|
||||
if (binaryArray[i] === 1) {
|
||||
++sum;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
unicodeBinary = unicodeBinary.concat(binaryArray.slice(i + 1, i + 8 - sum));
|
||||
i += 8 - sum;
|
||||
while (sum > 1) {
|
||||
unicodeBinary = unicodeBinary.concat(binaryArray.slice(i + 2, i + 8));
|
||||
i += 8;
|
||||
--sum;
|
||||
}
|
||||
unicode = _toDecimal(unicodeBinary);
|
||||
str += String.fromCharCode(unicode);
|
||||
unicodeBinary = [];
|
||||
}
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
const _encode = function (str, url_safe) {
|
||||
const base64_Index = [];
|
||||
const binaryArray = _toBinaryArray(str);
|
||||
const dictionary = url_safe ? URLSAFE_BASE64_MAPPING : BASE64_MAPPING;
|
||||
|
||||
let extra_Zero_Count = 0;
|
||||
for (let i = 0, len = binaryArray.length; i < len; i += 6) {
|
||||
const diff = i + 6 - len;
|
||||
if (diff === 2) {
|
||||
extra_Zero_Count = 2;
|
||||
} else if (diff === 4) {
|
||||
extra_Zero_Count = 4;
|
||||
}
|
||||
let _tmpExtra_Zero_Count = extra_Zero_Count;
|
||||
while (--_tmpExtra_Zero_Count >= 0) {
|
||||
binaryArray.push(0);
|
||||
}
|
||||
base64_Index.push(_toDecimal(binaryArray.slice(i, i + 6)));
|
||||
}
|
||||
|
||||
let base64 = '';
|
||||
for (let i = 0, len = base64_Index.length; i < len; ++i) {
|
||||
base64 += dictionary[base64_Index[i]];
|
||||
}
|
||||
|
||||
for (let i = 0, len = extra_Zero_Count / 2; i < len; ++i) {
|
||||
base64 += '=';
|
||||
}
|
||||
return base64;
|
||||
};
|
||||
|
||||
const _decode = function (_base64Str, url_safe) {
|
||||
const _len = _base64Str.length;
|
||||
let extra_Zero_Count = 0;
|
||||
const dictionary = url_safe ? URLSAFE_BASE64_MAPPING : BASE64_MAPPING;
|
||||
|
||||
if (_base64Str.charAt(_len - 1) === '=') {
|
||||
if (_base64Str.charAt(_len - 2) === '=') {
|
||||
// 两个等号说明补了4个0
|
||||
extra_Zero_Count = 4;
|
||||
_base64Str = _base64Str.substring(0, _len - 2);
|
||||
} else {
|
||||
// 一个等号说明补了2个0
|
||||
extra_Zero_Count = 2;
|
||||
_base64Str = _base64Str.substring(0, _len - 1);
|
||||
}
|
||||
}
|
||||
|
||||
let binaryArray = [];
|
||||
let i = 0;
|
||||
const len = _base64Str.length;
|
||||
for (; i < len; ++i) {
|
||||
const c = _base64Str.charAt(i);
|
||||
let j = 0;
|
||||
const size = dictionary.length;
|
||||
for (; j < size; ++j) {
|
||||
if (c === dictionary[j]) {
|
||||
const _tmp = _toBinary(j);
|
||||
|
||||
/* 不足6位的补0*/
|
||||
const _tmpLen = _tmp.length;
|
||||
if (6 - _tmpLen > 0) {
|
||||
for (let k = 6 - _tmpLen; k > 0; --k) {
|
||||
_tmp.unshift(0);
|
||||
}
|
||||
}
|
||||
binaryArray = binaryArray.concat(_tmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (extra_Zero_Count > 0) {
|
||||
binaryArray = binaryArray.slice(0, binaryArray.length - extra_Zero_Count);
|
||||
}
|
||||
const str = _toUnicodeStr(binaryArray);
|
||||
return str;
|
||||
};
|
||||
|
||||
const __BASE64 = {
|
||||
encode(str) {
|
||||
return _encode(str, false);
|
||||
},
|
||||
decode(base64Str) {
|
||||
return _decode(base64Str, false);
|
||||
},
|
||||
urlsafe_encode(str) {
|
||||
return _encode(str, true);
|
||||
},
|
||||
urlsafe_decode(base64Str) {
|
||||
return _decode(base64Str, true);
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = __BASE64;
|
||||
109
lib/routes/universities/ynnu/edu/news.js
Normal file
109
lib/routes/universities/ynnu/edu/news.js
Normal file
@@ -0,0 +1,109 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const { encode } = require('./base64');
|
||||
const timezone = require('@/utils/timezone');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const baseUrl = 'https://ostudy.ynnedu.cn/';
|
||||
const blacklist = ['ynnu-mv.html', 'https://chjiao.ynnu.edu.cn/zsgz/zsjz.htm', 'https://chjiao.ynnu.edu.cn/info/1006/1404.htm', 'https://chjiao.ynnu.edu.cn/zsgz/dksw.htm'];
|
||||
const { body } = await got(baseUrl);
|
||||
const $index = cheerio.load(body);
|
||||
ctx.state.data = {
|
||||
title: '云南师范大学继续教育学院 #通知',
|
||||
link: baseUrl,
|
||||
item: await Promise.all([
|
||||
// 顶部幻灯片抓取
|
||||
Promise.all(
|
||||
$index('div[carousel-item] > div')
|
||||
.filter((_, element) => !blacklist.includes($index(element).find('a').attr('href')))
|
||||
.map((_, element) => {
|
||||
const $element = $index(element);
|
||||
const $a = $element.find('a');
|
||||
let link = $a.attr('href');
|
||||
if (!$a.attr('href').startsWith('http')) {
|
||||
link = new URL(link, baseUrl).toString();
|
||||
}
|
||||
if (link.endsWith('.pdf')) {
|
||||
return Promise.resolve({
|
||||
title: $element.find('p').text(),
|
||||
link,
|
||||
});
|
||||
}
|
||||
return ctx.cache.tryGet(link, async () => {
|
||||
const { body: articleBody } = await got(link);
|
||||
const $article = cheerio.load(articleBody, { decodeEntities: false });
|
||||
return {
|
||||
title: $article('#noticeSubject, #inform-content > div:nth-child(1)').text(),
|
||||
link,
|
||||
description: $article('#noticeContent, .oinform-content').html() + $article('.notice-attachment').html(),
|
||||
};
|
||||
});
|
||||
})
|
||||
.get()
|
||||
),
|
||||
// 中部新闻抓取
|
||||
Promise.all(
|
||||
cheerio
|
||||
.load($index('#serviceInform-tpl').html())('.news-li:not(:last-child)')
|
||||
.filter((_, element) => !blacklist.includes($index(element).find('a').attr('href')))
|
||||
.map((_, element) => {
|
||||
const $element = $index(element);
|
||||
const $a = $element.find('a');
|
||||
let link = $a.attr('href');
|
||||
if (!$a.attr('href').startsWith('http')) {
|
||||
link = new URL(link, baseUrl).toString();
|
||||
}
|
||||
if (link.endsWith('.pdf')) {
|
||||
return Promise.resolve({
|
||||
title: $a.text(),
|
||||
link,
|
||||
pubDate: parseDate($element.find('span').text(), '发布时间: YYYY-MM-DD'),
|
||||
});
|
||||
}
|
||||
return ctx.cache.tryGet(link, async () => {
|
||||
const { body: articleBody } = await got(link);
|
||||
const $article = cheerio.load(articleBody, { decodeEntities: false });
|
||||
return {
|
||||
title: $article('#noticeSubject, #inform-content > div:nth-child(1)').text(),
|
||||
link,
|
||||
description: $article('#noticeContent, .oinform-content').html() + $article('.notice-attachment').html(),
|
||||
pubDate: parseDate($element.find('span').text(), '发布时间: YYYY-MM-DD'),
|
||||
};
|
||||
});
|
||||
})
|
||||
.get()
|
||||
),
|
||||
got(`${baseUrl}/serviceNotice/queryRecentServiceNotices`, {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: 'top=10&organizationCode=ORG-CN-EDU-YNNU',
|
||||
}).then(({ data: { data } }) =>
|
||||
data.map(({ createTime, noticeSubject, noticeContent, noticeCode, publishUnit }) => ({
|
||||
title: noticeSubject,
|
||||
description: noticeContent,
|
||||
pubDate: timezone(parseDate(createTime), +8),
|
||||
link: `${baseUrl}/notice-detail.html?c=${encode(noticeCode)}`,
|
||||
author: publishUnit,
|
||||
}))
|
||||
),
|
||||
got(`${baseUrl}/newsInformation/queryRecentNewsInformations`, {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: 'top=10&organizationCode=ORG-CN-EDU-YNNU',
|
||||
}).then(({ data: { data } }) =>
|
||||
data.map(({ createTime, title, newsContent, newsCode, publishUnit }) => ({
|
||||
title,
|
||||
description: newsContent,
|
||||
pubDate: timezone(parseDate(createTime), +8),
|
||||
link: `${baseUrl}/news-detail.html?c=${encode(newsCode)}`,
|
||||
author: publishUnit,
|
||||
}))
|
||||
),
|
||||
]).then((items) => items.flat()),
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user