mirror of
https://github.com/DIYgod/RSSHub.git
synced 2025-12-04 19:59:54 +08:00
feat(route): 山东大学(威海)新闻网 (#9537)
* feat(sduwh): add extractors.
* feat(route): add route for 山东大学(威海)新闻网
* docs: for route sduwh/news
* docs: for route sduwh/news
(cherry picked from commit 831830167a)
* feat(radar): for route 山东大学(威海)新闻网
* refactor: change `got.get` to `got`.
* refactor: prefer `parseDate()` to `new Date()`
Co-authored-by: Tony <TonyRL@users.noreply.github.com>
* fix: incomplete URL substring sanitization.
Make CodeQL happy.
* fix(radar): fix target field.
* fix: change route /sduwh to /sdu/wh
* fix: remove superfluous slash character in url.
* feat: look for exact date first.
* feat: extract exact date from news extractor.
* feat: extract exact date from view extractor.
* feat: extractor for www.sdrj.sdu.edu.cn
* refactor: semantic separation of sduwh with sdu
* feat(radar): more accurate name
* docs: update documentation
* refactor: migrate to v2
* refactor: fix deprecated url.resolve
* fix: update docs url
Co-authored-by: Tony <TonyRL@users.noreply.github.com>
* fix: sdu not working routes
* fix: accurate `ctx.state.data.url`
Co-authored-by: Tony <TonyRL@users.noreply.github.com>
* fix: better error handling for extractors.
* fix: timezone
Co-authored-by: Tony <TonyRL@users.noreply.github.com>
* fix: better error handling.
Co-authored-by: Tony <TonyRL@users.noreply.github.com>
This commit is contained in:
@@ -1961,7 +1961,7 @@ type 列表:
|
||||
|
||||
### 软件学院通知
|
||||
|
||||
<Route author="Ji4n1ng" example="/sdu/sc/0" path="/sdu/sc/:type?" :paramsDesc="['默认为 `0`']">
|
||||
<Route author="Ji4n1ng" example="/sdu/sc/0" path="/sdu/sc/:type?" :paramsDesc="['默认为 `0`']" radar="1" rssbud="1">
|
||||
|
||||
| 通知公告 | 学术动态 | 本科教育 | 研究生教育 |
|
||||
| ---- | ---- | ---- | ----- |
|
||||
@@ -1971,7 +1971,7 @@ type 列表:
|
||||
|
||||
### 材料科学与工程学院通知
|
||||
|
||||
<Route author="Ji4n1ng" example="/sdu/cmse/0" path="/sdu/cmse/:type?" :paramsDesc="['默认为 `0`']">
|
||||
<Route author="Ji4n1ng" example="/sdu/cmse/0" path="/sdu/cmse/:type?" :paramsDesc="['默认为 `0`']" radar="1" rssbud="1">
|
||||
|
||||
| 通知公告 | 学院新闻 | 本科生教育 | 研究生教育 | 学术动态 |
|
||||
| ---- | ---- | ----- | ----- | ---- |
|
||||
@@ -1981,7 +1981,7 @@ type 列表:
|
||||
|
||||
### 机械工程学院通知
|
||||
|
||||
<Route author="Ji4n1ng" example="/sdu/mech/0" path="/sdu/mech/:type?" :paramsDesc="['默认为 `0`']">
|
||||
<Route author="Ji4n1ng" example="/sdu/mech/0" path="/sdu/mech/:type?" :paramsDesc="['默认为 `0`']" radar="1" rssbud="1">
|
||||
|
||||
| 通知公告 | 院所新闻 | 教学信息 | 学术动态 | 学院简报 |
|
||||
| ---- | ---- | ---- | ---- | ---- |
|
||||
@@ -1991,7 +1991,7 @@ type 列表:
|
||||
|
||||
### 能源与动力工程学院通知
|
||||
|
||||
<Route author="Ji4n1ng" example="/sdu/epe/0" path="/sdu/epe/:type?" :paramsDesc="['默认为 `0`']">
|
||||
<Route author="Ji4n1ng" example="/sdu/epe/0" path="/sdu/epe/:type?" :paramsDesc="['默认为 `0`']" radar="1" rssbud="1">
|
||||
|
||||
| 学院动态 | 通知公告 | 学术论坛 |
|
||||
| ---- | ---- | ---- |
|
||||
@@ -2001,14 +2001,26 @@ type 列表:
|
||||
|
||||
### 计算机科学与技术学院通知
|
||||
|
||||
<Route author="suxb201" example="/sdu/cs/0" path="/sdu/cs/:type?" :paramsDesc="['默认为 `0`']">
|
||||
<Route author="suxb201" example="/sdu/cs/0" path="/sdu/cs/:type?" :paramsDesc="['默认为 `0`']" radar="1" rssbud="1">
|
||||
|
||||
| 学院公告 | 学术报告 | 新闻动态 |
|
||||
| 学院公告 | 学术报告 | 科技简讯 |
|
||||
| ---- | ---- | ---- |
|
||||
| 0 | 1 | 2 |
|
||||
|
||||
</Route>
|
||||
|
||||
## 山东大学(威海)
|
||||
|
||||
### 新闻网
|
||||
|
||||
<Route author="kxxt" example="/sdu/wh/news/xyyw" path="/sdu/wh/news/:column?" :paramsDesc="['专栏名称,默认为校园要闻(`xyyw`)']" radar="1" rssbud="1">
|
||||
|
||||
| 校园要闻 | 学生动态 | 综合新闻 | 山大视点 | 菁菁校园 | 校园简讯 | 玛珈之窗 | 热点专题 | 媒体视角 | 高教视野 | 理论学习 |
|
||||
| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
|
||||
| xyyw | xsdt | zhxw | sdsd | jjxy | xyjx | mjzc | rdzt | mtsj | gjsy | llxx |
|
||||
|
||||
</Route>
|
||||
|
||||
## 上海大学
|
||||
|
||||
### 上海大学官网信息
|
||||
|
||||
@@ -716,12 +716,12 @@ router.get('/jgsu/jwc', lazyloadRouteHandler('./routes/universities/jgsu/jwc'));
|
||||
// 中南大学
|
||||
router.get('/csu/job/:type?', lazyloadRouteHandler('./routes/universities/csu/job'));
|
||||
|
||||
// 山东大学
|
||||
router.get('/sdu/sc/:type?', lazyloadRouteHandler('./routes/universities/sdu/sc'));
|
||||
router.get('/sdu/cs/:type?', lazyloadRouteHandler('./routes/universities/sdu/cs'));
|
||||
router.get('/sdu/cmse/:type?', lazyloadRouteHandler('./routes/universities/sdu/cmse'));
|
||||
router.get('/sdu/mech/:type?', lazyloadRouteHandler('./routes/universities/sdu/mech'));
|
||||
router.get('/sdu/epe/:type?', lazyloadRouteHandler('./routes/universities/sdu/epe'));
|
||||
// 山东大学 migrated to v2
|
||||
// router.get('/sdu/sc/:type?', lazyloadRouteHandler('./routes/universities/sdu/sc'));
|
||||
// router.get('/sdu/cs/:type?', lazyloadRouteHandler('./routes/universities/sdu/cs'));
|
||||
// router.get('/sdu/cmse/:type?', lazyloadRouteHandler('./routes/universities/sdu/cmse'));
|
||||
// router.get('/sdu/mech/:type?', lazyloadRouteHandler('./routes/universities/sdu/mech'));
|
||||
// router.get('/sdu/epe/:type?', lazyloadRouteHandler('./routes/universities/sdu/epe'));
|
||||
|
||||
// 中国海洋大学
|
||||
router.get('/ouc/it/:type?', lazyloadRouteHandler('./routes/universities/ouc/it'));
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
|
||||
const host = 'http://www.cmse.sdu.edu.cn/';
|
||||
const typelist = ['通知公告', '学院新闻', '本科生教育', '研究生教育', '学术动态'];
|
||||
const urlList = ['zxzx/tzgg.htm', 'zxzx/xyxw.htm', 'zxzx/bksjy.htm', 'zxzx/yjsjy.htm', 'zxzx/xsdt.htm'];
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = parseInt(ctx.params.type) || 0;
|
||||
const link = url.resolve(host, urlList[type]);
|
||||
const response = await got.get(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('#list_right_list a')
|
||||
.slice(0, 10)
|
||||
.map((i, e) => $(e).attr('href'))
|
||||
.get();
|
||||
|
||||
const out = await Promise.all(
|
||||
list
|
||||
.filter((e) => e.startsWith('../info'))
|
||||
.map(async (itemUrl) => {
|
||||
itemUrl = url.resolve(host, itemUrl.slice('3'));
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
}
|
||||
|
||||
const response = await got.get(itemUrl);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const rawDate = $('#show_info').text().split(/\s{4}/);
|
||||
let date = rawDate[0].split(':')[1];
|
||||
date = date.slice(0, 4) + '-' + date.slice(5, 7) + '-' + date.slice(8, 10) + ' ' + date.slice(12);
|
||||
|
||||
const single = {
|
||||
title: $('#show_title').text().trim(),
|
||||
link: itemUrl,
|
||||
author: '山东大学材料科学与工程学院',
|
||||
description: $('#show_content').html(),
|
||||
pubDate: new Date(date),
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `山东大学材料科学与工程学院${typelist[type]}`,
|
||||
link,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,55 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
|
||||
const host = 'http://www.cs.sdu.edu.cn/';
|
||||
const typelist = ['学院公告', '学术报告', '新闻动态'];
|
||||
const urlList = ['index/xygg.htm', 'xwgg/xsbg.htm', 'xwgg/xyxw.htm'];
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = parseInt(ctx.params.type) || 0;
|
||||
const link = url.resolve(host, urlList[type]);
|
||||
|
||||
const response = await got.get(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const dateDict = {};
|
||||
const list = $('.sub_text .news-list')
|
||||
.slice(0, 10)
|
||||
.map((i, e) => {
|
||||
const divs = $(e).children();
|
||||
const tlink = 'http://www.cs.sdu.edu.cn/' + $('a', divs[1]).attr('href').substring(3);
|
||||
dateDict[tlink] = new Date($(divs[2]).text()).toUTCString();
|
||||
return tlink;
|
||||
})
|
||||
.get();
|
||||
|
||||
const out = await Promise.all(
|
||||
list.map(async (itemUrl) => {
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
}
|
||||
|
||||
const response = await got.get(itemUrl);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const single = {
|
||||
title: $('#newsTitle').text().trim(),
|
||||
author: '山东大学计算机科学与技术学院',
|
||||
description: $('.v_news_content').html(),
|
||||
pubDate: dateDict[itemUrl],
|
||||
link: itemUrl,
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `山东大学计算机科学与技术学院${typelist[type]}通知`,
|
||||
link,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,54 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
|
||||
const host = 'http://www.epe.sdu.edu.cn/';
|
||||
const typelist = ['学院动态', '通知公告', '学术论坛'];
|
||||
const urlList = ['zxzx/xydt.htm', 'zxzx/tzgg.htm', 'zxzx/xslt.htm'];
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = parseInt(ctx.params.type) || 0;
|
||||
const link = url.resolve(host, urlList[type]);
|
||||
const response = await got.get(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('#page_right_main li a')
|
||||
.slice(0, 10)
|
||||
.map((i, e) => $(e).attr('href'))
|
||||
.get();
|
||||
|
||||
const out = await Promise.all(
|
||||
list
|
||||
.filter((e) => e.startsWith('../info'))
|
||||
.map(async (itemUrl) => {
|
||||
itemUrl = url.resolve(host, itemUrl.slice('3'));
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
}
|
||||
|
||||
const response = await got.get(itemUrl);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const rawDate = $('#show_info').text().split(/\s{4}/);
|
||||
const date = rawDate[0].split(':')[1];
|
||||
|
||||
const single = {
|
||||
title: $('#show_title').text().trim(),
|
||||
link: itemUrl,
|
||||
author: '山东大学能源与动力工程学院',
|
||||
description: $('#show_content').html(),
|
||||
pubDate: new Date(date),
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `山东大学能源与动力工程学院${typelist[type]}`,
|
||||
link,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,58 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
|
||||
const typelist = ['通知公告', '院所新闻', '教学信息', '学术动态', '学院简报'];
|
||||
const urlList = ['xwdt/tzgg.htm', 'xwdt/ysxw.htm', 'xwdt/jxxx.htm', 'xwdt/xsdt.htm', 'xwdt/xyjb.htm'];
|
||||
const host = 'http://www.mech.sdu.edu.cn/';
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = parseInt(ctx.params.type) || 0;
|
||||
const link = url.resolve(host, urlList[type]);
|
||||
const response = await got.get(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('#page_list li a')
|
||||
.slice(0, 10)
|
||||
.map((i, e) => $(e).attr('href'))
|
||||
.get();
|
||||
|
||||
const out = await Promise.all(
|
||||
list
|
||||
.filter((e) => e.startsWith('../info') || e.startsWith('http://www.rd.sdu.edu.cn/'))
|
||||
.map(async (itemUrl) => {
|
||||
const isFromMech = itemUrl.startsWith('../info');
|
||||
if (isFromMech) {
|
||||
itemUrl = url.resolve(host, itemUrl.slice('3'));
|
||||
}
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
}
|
||||
|
||||
const response = await got.get(itemUrl);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const rawDate = $('#show_info').text().split(/\s{4}/);
|
||||
let date = rawDate[0].split(':')[1];
|
||||
date = date.slice(0, 4) + '-' + date.slice(5, 7) + '-' + date.slice(8, 10) + ' ' + date.slice(11);
|
||||
|
||||
const single = {
|
||||
title: $('#show_title').text().trim(),
|
||||
link: itemUrl,
|
||||
author: '山东大学机械工程学院',
|
||||
description: $('#show_content').html(),
|
||||
pubDate: new Date(date),
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `山东大学机械工程学院${typelist[type]}`,
|
||||
link,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,56 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const url = require('url');
|
||||
|
||||
const host = 'http://www.sc.sdu.edu.cn/';
|
||||
const typelist = ['通知公告', '学术动态', '本科教育', '研究生教育'];
|
||||
const urlList = ['tzgg.htm', 'kxyj/xsdt/2.htm', 'rcpy/bkjy.htm', 'rcpy/yjsjy.htm'];
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = parseInt(ctx.params.type) || 0;
|
||||
const link = url.resolve(host, urlList[type]);
|
||||
const response = await got.get(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const dateDict = {};
|
||||
const list = $('.lm_list li')
|
||||
.slice(0, 10)
|
||||
.map((i, e) => {
|
||||
let aLink = $(e).children('a').attr('href');
|
||||
// aLink = aLink.slice(3);
|
||||
aLink = url.resolve(host, aLink);
|
||||
const date = $(e).children('span').text().trim();
|
||||
dateDict[aLink] = date;
|
||||
return aLink;
|
||||
})
|
||||
.get();
|
||||
|
||||
const out = await Promise.all(
|
||||
list.map(async (itemUrl) => {
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
}
|
||||
|
||||
const response = await got.get(itemUrl);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const single = {
|
||||
title: $('h1.c-title').text().trim(),
|
||||
link: itemUrl,
|
||||
author: '山东大学软件学院',
|
||||
description: $('.v_news_content').html(),
|
||||
pubDate: new Date(dateDict[itemUrl]),
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `山东大学软件学院${typelist[type]}`,
|
||||
link,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -5,6 +5,7 @@
|
||||
* lib/route/tencent/wechat
|
||||
* lib/v2/wechat
|
||||
* lib/v2/gzh360
|
||||
* lib/v2/sdu/cs
|
||||
*
|
||||
* If your new route is not in the above folders, please add it to the list.
|
||||
*
|
||||
|
||||
59
lib/v2/sdu/cmse.js
Normal file
59
lib/v2/sdu/cmse.js
Normal file
@@ -0,0 +1,59 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
const host = 'http://www.cmse.sdu.edu.cn/';
|
||||
const typelist = ['通知公告', '学院新闻', '本科生教育', '研究生教育', '学术动态'];
|
||||
const urlList = ['zxzx/tzgg.htm', 'zxzx/xyxw.htm', 'zxzx/bksjy.htm', 'zxzx/yjsjy.htm', 'zxzx/xsdt.htm'];
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type ? parseInt(ctx.params.type) : 0;
|
||||
const link = new URL(urlList[type], host).href;
|
||||
const response = await got(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
let item = $('.article_list li')
|
||||
.map((_, e) => {
|
||||
e = $(e);
|
||||
const a = e.find('a');
|
||||
return {
|
||||
title: a.text().trim(),
|
||||
link: a.attr('href'),
|
||||
pubDate: parseDate(e.find('.date').text(), 'YYYY/MM/DD'),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
item = await Promise.all(
|
||||
item
|
||||
.filter((e) => e.link.startsWith('../info'))
|
||||
.map((item) => {
|
||||
item.link = new URL(item.link.slice('3'), host).href;
|
||||
return ctx.cache.tryGet(item.link, async () => {
|
||||
const response = await got(item.link);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
item.title = $('.contentTitle').text();
|
||||
item.author =
|
||||
$('.contentTitle2')
|
||||
.find('span')
|
||||
.eq(1)
|
||||
.text()
|
||||
.trim()
|
||||
.match(/作者:(.*)/)[1] || '山东大学材料科学与工程学院';
|
||||
$('.contentTitle, .contentTitle2').remove();
|
||||
item.description = $('.content_detail').html();
|
||||
|
||||
return item;
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `山东大学材料科学与工程学院${typelist[type]}`,
|
||||
description: $('title').text(),
|
||||
link,
|
||||
item,
|
||||
};
|
||||
};
|
||||
57
lib/v2/sdu/cs.js
Normal file
57
lib/v2/sdu/cs.js
Normal file
@@ -0,0 +1,57 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const { finishArticleItem } = require('@/utils/wechat-mp');
|
||||
|
||||
const host = 'https://www.cs.sdu.edu.cn/';
|
||||
const typelist = ['学院公告', '学术报告', '科技简讯'];
|
||||
const urlList = ['xygg.htm', 'xsbg.htm', 'kjjx.htm'];
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type ? parseInt(ctx.params.type) : 0;
|
||||
const link = new URL(urlList[type], host).href;
|
||||
|
||||
const response = await got(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
let item = $('.dqlb ul li')
|
||||
.map((_, e) => {
|
||||
e = $(e);
|
||||
const a = e.find('a');
|
||||
return {
|
||||
title: a.text().trim(),
|
||||
link: a.attr('href').startsWith('info/') ? host + a.attr('href') : a.attr('href'),
|
||||
pubDate: parseDate(e.find('.fr').text().trim(), 'YYYY-MM-DD'),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
item = await Promise.all(
|
||||
item.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
if (new URL(item.link).hostname === 'mp.weixin.qq.com') {
|
||||
return finishArticleItem(ctx, item);
|
||||
} else if (new URL(item.link).hostname !== 'www.cs.sdu.edu.cn') {
|
||||
return item;
|
||||
}
|
||||
const response = await got(item.link);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
item.title = $('.xqnr_tit h2').text().trim();
|
||||
item.author = $('.xqnr_tit span').eq(1).text().trim().replace('编辑:', '') || '山东大学计算机科学与技术学院';
|
||||
$('.xqnr_tit').remove();
|
||||
item.description = $('form[name=_newscontent_fromname]').html();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `山东大学计算机科学与技术学院${typelist[type]}通知`,
|
||||
description: $('title').text(),
|
||||
link,
|
||||
item,
|
||||
};
|
||||
};
|
||||
61
lib/v2/sdu/data.js
Normal file
61
lib/v2/sdu/data.js
Normal file
@@ -0,0 +1,61 @@
|
||||
module.exports = {
|
||||
wh: {
|
||||
news: {
|
||||
name: '山东大学(威海)新闻网',
|
||||
route: '/news',
|
||||
source: ['/'],
|
||||
titlePrefix: '(威海)新闻网|',
|
||||
docs: 'https://docs.rsshub.app/university.html#shan-dong-da-xue-wei-hai',
|
||||
getTarget(url) {
|
||||
return this.route + '/' + url.replace(/\.htm$/, '');
|
||||
},
|
||||
url: 'https://xinwen.wh.sdu.edu.cn/',
|
||||
columns: {
|
||||
xyyw: {
|
||||
name: '校园要闻',
|
||||
url: 'xyyw.htm',
|
||||
},
|
||||
xsdt: {
|
||||
name: '学生动态',
|
||||
url: 'xsdt.htm',
|
||||
},
|
||||
zhxw: {
|
||||
name: '综合新闻',
|
||||
url: 'zhxw.htm',
|
||||
},
|
||||
sdsd: {
|
||||
name: '山大视点',
|
||||
url: 'sdsd.htm',
|
||||
},
|
||||
jjxy: {
|
||||
name: '菁菁校园',
|
||||
url: 'jjxy.htm',
|
||||
},
|
||||
xyjx: {
|
||||
name: '校园简讯',
|
||||
url: 'xyjx.htm',
|
||||
},
|
||||
mjzc: {
|
||||
name: '玛珈之窗',
|
||||
url: 'mjzc.htm',
|
||||
},
|
||||
rdzt: {
|
||||
name: '热点专题',
|
||||
url: 'rdzt.htm',
|
||||
},
|
||||
mtsj: {
|
||||
name: '媒体视角',
|
||||
url: 'mtsj.htm',
|
||||
},
|
||||
gjsy: {
|
||||
name: '高教视野',
|
||||
url: 'gjsy.htm',
|
||||
},
|
||||
llxx: {
|
||||
name: '理论学习',
|
||||
url: 'llxx.htm',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
55
lib/v2/sdu/epe.js
Normal file
55
lib/v2/sdu/epe.js
Normal file
@@ -0,0 +1,55 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const timezone = require('@/utils/timezone');
|
||||
|
||||
const host = 'https://www.epe.sdu.edu.cn/';
|
||||
const typelist = ['学院动态', '通知公告', '学术论坛'];
|
||||
const urlList = ['zxzx/xydt.htm', 'zxzx/tzgg.htm', 'zxzx/xslt.htm'];
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type ? parseInt(ctx.params.type) : 0;
|
||||
const link = new URL(urlList[type], host).href;
|
||||
const response = await got(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
let item = $('#page_right_main li a')
|
||||
.map((_, e) => {
|
||||
e = $(e);
|
||||
return {
|
||||
title: e.attr('title'),
|
||||
link: e.attr('href'),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
item = await Promise.all(
|
||||
item
|
||||
.filter((e) => e.link.startsWith('../info'))
|
||||
.map((item) => {
|
||||
item.link = new URL(item.link.slice('3'), host).href;
|
||||
return ctx.cache.tryGet(item.link, async () => {
|
||||
const response = await got(item.link);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const info = $('#show_info').text().split(/\s{4}/);
|
||||
const date = info[0].split(':')[1];
|
||||
|
||||
item.title = $('#show_title').text().trim();
|
||||
item.author = info[1].replace('编辑:', '') || '山东大学能源与动力工程学院';
|
||||
item.description = $('#show_content').html();
|
||||
item.pubDate = timezone(parseDate(date), +8);
|
||||
|
||||
return item;
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `山东大学能源与动力工程学院${typelist[type]}`,
|
||||
description: $('title').text(),
|
||||
link,
|
||||
item,
|
||||
};
|
||||
};
|
||||
12
lib/v2/sdu/extractor/index.js
Normal file
12
lib/v2/sdu/extractor/index.js
Normal file
@@ -0,0 +1,12 @@
|
||||
module.exports = async (link, ctx) => {
|
||||
if (link.startsWith('https://xinwen.wh.sdu.edu.cn/')) {
|
||||
return await require('./wh/news')(link, ctx);
|
||||
}
|
||||
if (link.startsWith('https://www.view.sdu.edu.cn/')) {
|
||||
return await require('./view')(link, ctx);
|
||||
}
|
||||
if (link.startsWith('https://www.sdrj.sdu.edu.cn/')) {
|
||||
return await require('./sdrj')(link, ctx);
|
||||
}
|
||||
return {};
|
||||
};
|
||||
21
lib/v2/sdu/extractor/sdrj.js
Normal file
21
lib/v2/sdu/extractor/sdrj.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const timezone = require('@/utils/timezone');
|
||||
|
||||
module.exports = async (link, ctx) =>
|
||||
await ctx.cache.tryGet(link, async () => {
|
||||
let content, author, exactDate;
|
||||
try {
|
||||
const result = await got(link);
|
||||
const $ = cheerio.load(result.data);
|
||||
content = $('#vsb_content').html();
|
||||
author = $("form[name='_newscontent_fromname'] > h1").text();
|
||||
const exactDateLine = $("form[name='_newscontent_fromname'] > p.info").text().trim();
|
||||
const exactDateText = exactDateLine.match(/^发布时间:(?<date>\d+\/\d+\/\d+\s\d{2}:\d{2}:\d{2})/).groups.date;
|
||||
exactDate = timezone(parseDate(exactDateText, 'YYYY/MM/DD HH:mm:ss'), +8);
|
||||
return { description: content, author, exactDate };
|
||||
} catch (e) {
|
||||
return { description: content, author, exactDate };
|
||||
}
|
||||
});
|
||||
21
lib/v2/sdu/extractor/view.js
Normal file
21
lib/v2/sdu/extractor/view.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const timezone = require('@/utils/timezone');
|
||||
|
||||
module.exports = async (link, ctx) =>
|
||||
await ctx.cache.tryGet(link, async () => {
|
||||
let content, author, exactDate;
|
||||
try {
|
||||
const result = await got(link);
|
||||
const $ = cheerio.load(result.data);
|
||||
content = $('#vsb_content').html();
|
||||
author = $("form[name='_newscontent_fromname'] > div > p:last-of-type").text();
|
||||
const exactDateLine = $('.news_tit > p:last-child').text();
|
||||
const exactDateText = exactDateLine.match(/^发布日期:(?<date>\d+年\d+月\d+日\s\d{2}:\d{2})/).groups.date;
|
||||
exactDate = timezone(parseDate(exactDateText, 'YYYY年MM月DD日 HH:mm'), +8);
|
||||
return { description: content, author, exactDate };
|
||||
} catch (e) {
|
||||
return { description: content, author, exactDate };
|
||||
}
|
||||
});
|
||||
21
lib/v2/sdu/extractor/wh/news.js
Normal file
21
lib/v2/sdu/extractor/wh/news.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const timezone = require('@/utils/timezone');
|
||||
|
||||
module.exports = async (link, ctx) =>
|
||||
await ctx.cache.tryGet(link, async () => {
|
||||
let content, author, exactDate;
|
||||
try {
|
||||
const result = await got(link);
|
||||
const $ = cheerio.load(result.data);
|
||||
content = $('#main-content').html();
|
||||
author = $('#source').text();
|
||||
const exactDateLine = $('.news_tit > p:last-child').text();
|
||||
const exactDateText = exactDateLine.match(/^发布日期:(?<date>\d+年\d+月\d+日\s\d{2}:\d{2})/).groups.date;
|
||||
exactDate = timezone(parseDate(exactDateText, 'YYYY年MM月DD日 HH:mm'), +8);
|
||||
return { description: content, author, exactDate };
|
||||
} catch (e) {
|
||||
return { description: content, author, exactDate };
|
||||
}
|
||||
});
|
||||
8
lib/v2/sdu/maintainer.js
Normal file
8
lib/v2/sdu/maintainer.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
'/cmse/:type?': ['Ji4n1ng'],
|
||||
'/cs/:type?': ['Ji4n1ng'],
|
||||
'/epe/:type?': ['Ji4n1ng'],
|
||||
'/mech/:type?': ['Ji4n1ng'],
|
||||
'/sc/:type?': ['Ji4n1ng'],
|
||||
'/wh/news/:column?': ['kxxt'],
|
||||
};
|
||||
60
lib/v2/sdu/mech.js
Normal file
60
lib/v2/sdu/mech.js
Normal file
@@ -0,0 +1,60 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const timezone = require('@/utils/timezone');
|
||||
|
||||
const typelist = ['通知公告', '院所新闻', '教学信息', '学术动态', '学院简报'];
|
||||
const urlList = ['xwdt/tzgg.htm', 'xwdt/ysxw.htm', 'xwdt/jxxx.htm', 'xwdt/xsdt.htm', 'xwdt/xyjb.htm'];
|
||||
const host = 'https://www.mech.sdu.edu.cn/';
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type ? parseInt(ctx.params.type) : 0;
|
||||
const link = new URL(urlList[type], host).href;
|
||||
const response = await got(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
let item = $('#page_list li a')
|
||||
.slice(0, 1)
|
||||
.map((_, e) => {
|
||||
e = $(e);
|
||||
return {
|
||||
title: e.attr('title'),
|
||||
link: e.attr('href'),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
item = await Promise.all(
|
||||
item
|
||||
.filter((e) => e.link.startsWith('../info') || e.link.startsWith('https://www.rd.sdu.edu.cn/'))
|
||||
.map((item) => {
|
||||
const isFromMech = item.link.startsWith('../info');
|
||||
if (isFromMech) {
|
||||
item.link = new URL(item.link.slice('3'), host).href;
|
||||
}
|
||||
return ctx.cache.tryGet(item.link, async () => {
|
||||
const response = await got(item.link);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const info = $('#show_info').text().split(/\s{4}/);
|
||||
const date = info[0].split(':')[1];
|
||||
|
||||
item.title = $('#show_title').text().trim();
|
||||
item.author = info[1].replace('作者:', '') || '山东大学机械工程学院';
|
||||
$('#show_title, #show_info').remove();
|
||||
item.description = $('form[name=_newscontent_fromname] div').html();
|
||||
item.pubDate = timezone(parseDate(date), +8);
|
||||
|
||||
return item;
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `山东大学机械工程学院${typelist[type]}`,
|
||||
description: $('title').text(),
|
||||
link,
|
||||
item,
|
||||
};
|
||||
};
|
||||
153
lib/v2/sdu/radar.js
Normal file
153
lib/v2/sdu/radar.js
Normal file
@@ -0,0 +1,153 @@
|
||||
const { wh } = require('./data');
|
||||
|
||||
module.exports = {
|
||||
'sdu.edu.cn': {
|
||||
_name: '山东大学',
|
||||
'xinwen.wh': Object.entries(wh.news.columns).map(([, value]) => ({
|
||||
title: wh.news.titlePrefix + value.name,
|
||||
docs: wh.news.docs,
|
||||
source: wh.news.source,
|
||||
target: '/sdu/wh' + wh.news.getTarget(value.url),
|
||||
})),
|
||||
'www.cmse': [
|
||||
{
|
||||
title: '材料科学与工程学院通知',
|
||||
docs: 'https://docs.rsshub.app/university.html#shan-dong-da-xue',
|
||||
source: ['/*path', '/'],
|
||||
target: (params) => {
|
||||
let type;
|
||||
switch (params.path) {
|
||||
case 'zxzx/tzgg.htm':
|
||||
type = '0';
|
||||
break;
|
||||
case 'zxzx/xyxw.htm':
|
||||
type = '1';
|
||||
break;
|
||||
case 'zxzx/bksjy.htm':
|
||||
type = '2';
|
||||
break;
|
||||
case 'zxzx/yjsjy.htm':
|
||||
type = '3';
|
||||
break;
|
||||
case 'zxzx/xsdt.htm':
|
||||
type = '4';
|
||||
break;
|
||||
default:
|
||||
type = '0';
|
||||
break;
|
||||
}
|
||||
return `/sdu/cmse/${type}`;
|
||||
},
|
||||
},
|
||||
],
|
||||
'www.cs': [
|
||||
{
|
||||
title: '计算机科学与技术学院通知',
|
||||
docs: 'https://docs.rsshub.app/university.html#shan-dong-da-xue',
|
||||
source: ['/*path', '/'],
|
||||
target: (params) => {
|
||||
let type;
|
||||
switch (params.path) {
|
||||
case 'xygg.htm':
|
||||
type = '0';
|
||||
break;
|
||||
case 'xsbg.htm':
|
||||
type = '1';
|
||||
break;
|
||||
case 'kjjx.htm':
|
||||
type = '2';
|
||||
break;
|
||||
default:
|
||||
type = '0';
|
||||
break;
|
||||
}
|
||||
return `/sdu/cs/${type}`;
|
||||
},
|
||||
},
|
||||
],
|
||||
'www.epe': [
|
||||
{
|
||||
title: '能源与动力工程学院通知',
|
||||
docs: 'https://docs.rsshub.app/university.html#shan-dong-da-xue',
|
||||
source: ['/*path', '/'],
|
||||
target: (params) => {
|
||||
let type;
|
||||
switch (params.path) {
|
||||
case 'zxzx/xydt.htm':
|
||||
type = '0';
|
||||
break;
|
||||
case 'zxzx/tzgg.htm':
|
||||
type = '1';
|
||||
break;
|
||||
case 'zxzx/xslt.htm':
|
||||
type = '2';
|
||||
break;
|
||||
default:
|
||||
type = '0';
|
||||
break;
|
||||
}
|
||||
return `/sdu/epe/${type}`;
|
||||
},
|
||||
},
|
||||
],
|
||||
'www.mech': [
|
||||
{
|
||||
title: '机械工程学院通知',
|
||||
docs: 'https://docs.rsshub.app/university.html#shan-dong-da-xue',
|
||||
source: ['/*path', '/'],
|
||||
target: (params) => {
|
||||
let type;
|
||||
switch (params.path) {
|
||||
case 'xwdt/tzgg.htm':
|
||||
type = '0';
|
||||
break;
|
||||
case 'xwdt/ysxw.htm':
|
||||
type = '1';
|
||||
break;
|
||||
case 'xwdt/jxxx.htm':
|
||||
type = '2';
|
||||
break;
|
||||
case 'xwdt/xsdt.htm':
|
||||
type = '3';
|
||||
break;
|
||||
case 'xwdt/xyjb.htm':
|
||||
type = '4';
|
||||
break;
|
||||
default:
|
||||
type = '0';
|
||||
break;
|
||||
}
|
||||
return `/sdu/mech/${type}`;
|
||||
},
|
||||
},
|
||||
],
|
||||
'www.sc': [
|
||||
{
|
||||
title: '软件学院通知',
|
||||
docs: 'https://docs.rsshub.app/university.html#shan-dong-da-xue',
|
||||
source: ['/*path', '/'],
|
||||
target: (params) => {
|
||||
let type;
|
||||
switch (params.path) {
|
||||
case 'tzgg.htm':
|
||||
type = '0';
|
||||
break;
|
||||
case 'kxyj/xsyg.htm':
|
||||
type = '1';
|
||||
break;
|
||||
case 'rcpy/bkjy.htm':
|
||||
type = '2';
|
||||
break;
|
||||
case 'rcpy/yjsjy.htm':
|
||||
type = '3';
|
||||
break;
|
||||
default:
|
||||
type = '0';
|
||||
break;
|
||||
}
|
||||
return `/sdu/sc/${type}`;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
8
lib/v2/sdu/router.js
Normal file
8
lib/v2/sdu/router.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = function (router) {
|
||||
router.get('/cmse/:type?', require('./cmse'));
|
||||
router.get('/cs/:type?', require('./cs'));
|
||||
router.get('/epe/:type?', require('./epe'));
|
||||
router.get('/mech/:type?', require('./mech'));
|
||||
router.get('/sc/:type?', require('./sc'));
|
||||
router.get('/wh/news/:column?', require('./wh/news'));
|
||||
};
|
||||
61
lib/v2/sdu/sc.js
Normal file
61
lib/v2/sdu/sc.js
Normal file
@@ -0,0 +1,61 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
const host = 'https://www.sc.sdu.edu.cn/';
|
||||
const typelist = ['通知公告', '学术动态', '本科教育', '研究生教育'];
|
||||
const urlList = ['tzgg.htm', 'kxyj/xsyg.htm', 'rcpy/bkjy.htm', 'rcpy/yjsjy.htm'];
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type ? parseInt(ctx.params.type) : 0;
|
||||
const link = new URL(urlList[type], host).href;
|
||||
const response = await got(link);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
let item = $('.newlist01 li')
|
||||
.map((_, e) => {
|
||||
e = $(e);
|
||||
const a = e.find('a');
|
||||
let link = a.attr('href');
|
||||
link = new URL(link, host).href;
|
||||
return {
|
||||
title: a.text().trim(),
|
||||
link,
|
||||
pubDate: parseDate(e.find('.date').text().trim()),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
item = await Promise.all(
|
||||
item.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
try {
|
||||
const response = await got(item.link);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
item.title = $('h3').text();
|
||||
item.author =
|
||||
$('.pr')
|
||||
.text()
|
||||
.trim()
|
||||
.match(/作者:(.*)/)[1] || '山东大学软件学院';
|
||||
$('h3, .pr').remove();
|
||||
item.description = $('.content').html();
|
||||
|
||||
return item;
|
||||
} catch (e) {
|
||||
// intranet oa.sdu.edu.cn
|
||||
return item;
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `山东大学软件学院${typelist[type]}`,
|
||||
description: $('title').text(),
|
||||
link,
|
||||
item,
|
||||
};
|
||||
};
|
||||
38
lib/v2/sdu/wh/news.js
Normal file
38
lib/v2/sdu/wh/news.js
Normal file
@@ -0,0 +1,38 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const data = require('../data').wh.news;
|
||||
const extractor = require('../extractor');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const column = ctx.params.column ?? 'xyyw';
|
||||
const baseUrl = data.url;
|
||||
const response = await got(baseUrl + data.columns[column].url);
|
||||
const $ = cheerio.load(response.data);
|
||||
const items = $('.n_newslist li');
|
||||
const out = await Promise.all(
|
||||
items.map(async (index, item) => {
|
||||
item = $(item);
|
||||
const anchor = item.find('a');
|
||||
const title = anchor.attr('title');
|
||||
const href = anchor.attr('href');
|
||||
const link = href.startsWith('http') ? href : baseUrl + href;
|
||||
const { description, author, exactDate } = await ctx.cache.tryGet(link, async () => await extractor(link, ctx));
|
||||
const span = item.find('span');
|
||||
const pubDate = exactDate ?? parseDate(span.text(), 'YYYY/MM/DD');
|
||||
return {
|
||||
title,
|
||||
link,
|
||||
description,
|
||||
pubDate,
|
||||
author,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${data.name} ${data.columns[column].name}`,
|
||||
link: baseUrl + data.columns[column].url,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user