feat(route): add 北京大学学生就业指导服务中心 (#7904)

* feat(route): add 北京大学学生就业指导服务中心

* fix(route): get content from sript tag

request content in script tag to get full text

* fix(doc): fix parameter description

* fix(route): fix header and selector

* add test request and wait

* docs: fix warning

* refactor: migrate to v2

* fix: eecs

refactor: legacy url.resolve

refactor: use parseDate from utils

* docs: fix recruit path

Co-authored-by: TonyRL <TonyRL@users.noreply.github.com>
This commit is contained in:
DylanXie123 2022-04-24 23:14:17 +08:00 committed by GitHub
parent c9bb12fc34
commit 10acacfa46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 347 additions and 126 deletions

View File

@ -114,7 +114,7 @@ pageClass: routes
### 信科公告通知
<Route author="Ir1d" example="/pku/eecs/0" path="/pku/eecs/:type" :paramsDesc="['分区 type可在网页 URL 中找到']">
<Route author="Ir1d" example="/pku/eecs/0" path="/pku/eecs/:type" :paramsDesc="['分区 type可在网页 URL 中找到']" radar="1" rssbud="1">
| 全部 | 学院通知 | 人事通知 | 教务通知 | 学工通知 | 科研通知 | 财务通知 | 工会通知 | 院友通知 |
| -- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
@ -124,15 +124,15 @@ pageClass: routes
### 每周一推 - 中国政治学研究中心
<Route author="vhxubo" example="/pku/rccp/mzyt" path="/pku/rccp/mzyt" />
<Route author="vhxubo" example="/pku/rccp/mzyt" path="/pku/rccp/mzyt" radar="1" rssbud="1"/>
### 生命科学学院近期讲座
<Route author="TPOB" example="/pku/cls/lecture" path="/pku/cls/lecture" />
<Route author="TPOB" example="/pku/cls/lecture" path="/pku/cls/lecture" radar="1" rssbud="1"/>
### 北大未名 BBS 全站十大
<Route author="wooddance" example="/pku/bbs/hot" path="/pku/bbs/hot">
<Route author="wooddance" example="/pku/bbs/hot" path="/pku/bbs/hot" radar="1" rssbud="1">
::: warning 注意
@ -142,9 +142,19 @@ pageClass: routes
</Route>
### 学生就业指导服务中心
<Route author="DylanXie123" example="/pku/scc/recruit/zpxx" path="/pku/scc/recruit/:type?" :paramsDesc="['分区,见下表,默认请求 `tzgg`']" radar="1" rssbud="1">
| xwrd | tzgg | zpxx | gfjgxx | sxxx | cyxx |
| ---- | ---- | ---- | ------ | ---- | ---- |
| 新闻热点 | 通知公告 | 招聘信息 | 国防军工信息 | 实习信息 | 创业信息 |
</Route>
### 人事处
<Route author="nczitzk" example="/pku/hr" path="/pku/hr/:category?" :paramsDesc="['分类,见下方说明,默认为首页最新公告']">
<Route author="nczitzk" example="/pku/hr" path="/pku/hr/:category?" :paramsDesc="['分类,见下方说明,默认为首页最新公告']" radar="1" rssbud="1">
::: tip 提示
@ -156,6 +166,10 @@ pageClass: routes
</Route>
### 研究生招生网
<Route author="shengmaosu" example="/pku/admission/sszs" path="/pku/admission/sszs" radar="1" rssbud="1"/>
## 北京航空航天大学
### 北京航空航天大学

View File

@ -563,11 +563,12 @@ router.get('/lit/tw/:name?', lazyloadRouteHandler('./routes/universities/lit/tw'
router.get('/thu/career', lazyloadRouteHandler('./routes/universities/thu/career'));
router.get('/thu/:type', lazyloadRouteHandler('./routes/universities/thu/index'));
// 北京大学
router.get('/pku/eecs/:type?', lazyloadRouteHandler('./routes/universities/pku/eecs'));
router.get('/pku/rccp/mzyt', lazyloadRouteHandler('./routes/universities/pku/rccp/mzyt'));
router.get('/pku/cls/lecture', lazyloadRouteHandler('./routes/universities/pku/cls/lecture'));
router.get('/pku/bbs/hot', lazyloadRouteHandler('./routes/universities/pku/bbs/hot'));
// 北京大学 migrated to v2
// router.get('/pku/eecs/:type?', lazyloadRouteHandler('./routes/universities/pku/eecs'));
// router.get('/pku/rccp/mzyt', lazyloadRouteHandler('./routes/universities/pku/rccp/mzyt'));
// router.get('/pku/cls/lecture', lazyloadRouteHandler('./routes/universities/pku/cls/lecture'));
// router.get('/pku/bbs/hot', lazyloadRouteHandler('./routes/universities/pku/bbs/hot'));
// router.get('/pku/scc/recruit/:type?', lazyloadRouteHandler('./routes/universities/pku/scc/recruit'));
// 上海海事大学
router.get('/shmtu/www/:type', lazyloadRouteHandler('./routes/universities/shmtu/www'));
@ -2640,8 +2641,8 @@ router.get('/scutyjs', lazyloadRouteHandler('./routes/universities/scut/scutyjs'
// 华南农业大学研究生院通知公告
router.get('/scauyjs', lazyloadRouteHandler('./routes/universities/scauyjs/scauyjs'));
// 北京大学研究生招生网通知公告
router.get('/pkuyjs', lazyloadRouteHandler('./routes/universities/pku/pkuyjs'));
// 北京大学研究生招生网通知公告 migrated to v2
// router.get('/pkuyjs', lazyloadRouteHandler('./routes/universities/pku/pkuyjs'));
// 北京理工大学研究生通知公告
router.get('/bityjs', lazyloadRouteHandler('./routes/universities/bit/bityjs'));

View File

@ -1,41 +0,0 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
module.exports = async (ctx) => {
const host = 'http://eecs.pku.edu.cn/';
let type = ctx.params && ctx.params.type;
if (type === undefined) {
type = '0';
}
const response = await got({
method: 'get',
url: host + 'Survey/Notice/?Mtitle=' + type,
headers: {
Referer: host,
},
});
const $ = cheerio.load(response.data);
const text = $('.hvr-shutter-out-vertical').slice(0, 10);
ctx.state.data = {
title: '北大信科通知',
link: host + 'Survey/Notice/?Mtitle=' + type,
description: '北大信科 公告通知',
item:
text &&
text
.map((index, item) => {
item = $(item);
return {
title: item.find('p').text(),
link: host + 'Survey/Notice/' + item.attr('href'),
description: item.find('p').text(),
pubDate: item.find('em').text(),
};
})
.get(),
};
};

View File

@ -1,23 +0,0 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
module.exports = async (ctx) => {
const link = 'https://admission.pku.edu.cn/zsxx/sszs/index.htm';
const response = await got.get(link);
const $ = cheerio.load(response.data);
const list = $('.zsxx_cont_list li').slice(0, 10);
ctx.state.data = {
title: '北京大学研究生院',
link,
description: '北京大学研究生院通知公告',
item:
list &&
list
.map((index, item) => {
item = $(item);
return { title: item.find('li a').text(), description: item.find('li a').text(), link: item.find('li a').attr('href') };
})
.get(),
};
};

View File

@ -1,33 +0,0 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const baseUrl = 'http://www.rccp.pku.edu.cn/mzyt/';
module.exports = async (ctx) => {
const response = await got({
method: 'get',
url: baseUrl,
});
const $ = cheerio.load(response.data);
ctx.state.data = {
title: `每周一推 - 北京大学中国政治学研究中心`,
link: baseUrl,
description: `北京大学中国政治学研究中心,北大中国政治学研究中心,北大政治学研究中心,中国政治学研究中心,政治学研究中心,政治学,北大政治学,北京大学,俞可平
北京大学中国政治学研究中心官方网站www.rccp.pku.edu.cn
北京大学中国政治学研究中心微信公众平台北大政治学微信号PKURCCP`,
item: $('li.list')
.map((index, item) => ({
title: $(item).find('a').text().trim(),
description: '',
pubDate: $(item)
.find('span')
.first()
.text()
.match(/\d{4}-\d{2}-\d{2}/g)[0],
link: baseUrl + $(item).find('a').attr('href'),
}))
.get(),
};
};

View File

@ -1,14 +1,8 @@
const config = require('@/config').value;
const cheerio = require('cheerio');
const got = require('@/utils/got');
const resolveUrl = require('url').resolve;
function parseDate(text) {
const match = /[0-9 :-]+/.exec(text);
if (match) {
return new Date(match[0]).toUTCString();
}
}
const { parseDate } = require('@/utils/parse-date');
const timezone = require('@/utils/timezone');
module.exports = async (ctx) => {
const cookie = config.pkubbs.cookie;
@ -21,7 +15,7 @@ module.exports = async (ctx) => {
const listItems = $('#list-content .list-item')
.map(function () {
return {
url: resolveUrl(r.url, $(this).find('> a.link').attr('href')),
url: new URL($(this).find('> a.link').attr('href'), r.url).href,
title: $(this).find('.title').text(),
};
})
@ -35,12 +29,13 @@ module.exports = async (ctx) => {
try {
const r = await got(url, { headers });
const $ = cheerio.load(r.body);
const date = $('.post-card:first-child .sl-triangle-container .down-list span').text() || $('.post-card:first-child .sl-triangle-container .title span').text();
return {
title,
description: $('.post-card:first-child .content').html(),
link: url,
guid: url,
pubDate: parseDate($('.post-card:first-child .sl-triangle-container .title span').text()),
pubDate: timezone(parseDate(date, '发表于YYYY-MM-DD HH:mm:ss'), +8),
};
} catch (error) {
return {

View File

@ -1,14 +1,12 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
const homeUrl = 'http://www.bio.pku.edu.cn/homes/Index/news_jz/7/7.html';
const baseUrl = 'http://www.bio.pku.edu.cn';
const homeUrl = 'http://bio.pku.edu.cn/homes/Index/news_jz/7/7.html';
const baseUrl = 'http://bio.pku.edu.cn';
module.exports = async (ctx) => {
const response = await got({
method: 'get',
url: homeUrl,
});
const response = await got(homeUrl);
const $ = cheerio.load(response.data);
ctx.state.data = {
@ -19,7 +17,7 @@ module.exports = async (ctx) => {
.map((index, item) => ({
title: $(item).find('p').text().trim(),
description: '日期: ' + $(item).find('span'), // ${item.find('.chair_txt div').find('span').second().text()}
pubDate: parseDate($(item).find('.date').text()),
link: baseUrl + $('a.clearfix').attr('href'),
}))
.get(),

64
lib/v2/pku/eecs.js Normal file
View File

@ -0,0 +1,64 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
const { eecsMap } = require('./utils');
module.exports = async (ctx) => {
const host = 'https://eecs.pku.edu.cn';
let type = ctx.params && parseInt(ctx.params.type);
if (type === undefined) {
type = 0;
}
const response = await got(host + '/xygk1/ggtz/' + eecsMap.get(type));
const $ = cheerio.load(response.data);
let items = $('.hvr-shutter-out-vertical')
.toArray()
.map((item) => {
item = $(item);
return {
title: item.attr('title'),
link: new URL(item.attr('href'), host).href,
pubDate: parseDate(item.find('em').text()),
};
});
items = await Promise.all(
items.map((item) =>
ctx.cache.tryGet(item.link, async () => {
const detail = await got(item.link);
const content = cheerio.load(detail.data);
content('input').remove();
content('h1').remove();
content('.con_xq').remove();
content('form[name=_newscontent_fromname] img').each((_, i) => {
i = $(i);
if (i.attr('src').startsWith('/')) {
i.attr('src', new URL(i.attr('src'), host).href);
}
});
content('form[name=_newscontent_fromname] ul li a').each((_, a) => {
a = $(a);
if (a.attr('href').startsWith('/')) {
a.attr('href', new URL(a.attr('href'), host).href);
}
});
item.description = content('form[name=_newscontent_fromname]').html();
return item;
})
)
);
ctx.state.data = {
title: $('title').text(),
link: host + '/xygk1/ggtz/' + eecsMap.get(type),
description: '北大信科 公告通知',
item: items,
};
};

View File

@ -1,3 +1,9 @@
module.exports = {
'/admission/sszs': ['pkuyjs'],
'/bbs/hot': ['wooddance'],
'/cls/lecture': ['TPOB'],
'/eecs/:type?': ['Ir1d'],
'/hr/:category?': ['nczitzk'],
'/rccp/mzyt': ['vhxubo'],
'/scc/recruit/:type?': ['DylanXie123'],
};

29
lib/v2/pku/pkuyjs.js Normal file
View File

@ -0,0 +1,29 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const link = 'https://admission.pku.edu.cn/zsxx/sszs/index.htm';
const response = await got(link);
const $ = cheerio.load(response.data);
const list = $('.zsxx_cont_list li');
ctx.state.data = {
title: `${$('.twostage_title_C').text()} - ${$('title').text()}`,
link,
description: '北京大学研究生院通知公告',
item:
list &&
list
.map((index, item) => {
item = $(item);
return {
title: item.find('li a').text(),
description: item.find('li a').text(),
link: item.find('li a').attr('href'),
pubDate: parseDate(item.find('.zsxxCont_list_time').text()),
};
})
.get(),
};
};

View File

@ -1,6 +1,73 @@
module.exports = {
'pku.edu.cn': {
_name: '北京大学',
admission: [
{
title: '硕士招生',
docs: 'https://docs.rsshub.app/university.html#bei-jing-da-xue',
source: ['/zsxx/sszs/index.htm', '/'],
target: '/pku/admission/sszs',
},
],
bbs: [
{
title: '北大未名 BBS 全站十大',
docs: 'https://docs.rsshub.app/university.html#bei-jing-da-xue',
source: ['/v2/hot-topic.php', '/'],
target: '/pku/bbs/hot',
},
],
bio: [
{
title: '生命科学学院近期讲座',
docs: 'https://docs.rsshub.app/university.html#bei-jing-da-xue',
source: ['/homes/Index/news_jz/7/7.html', '/'],
target: '/pku/cls/lecture',
},
],
eecs: [
{
title: '信科公告通知',
docs: 'https://docs.rsshub.app/university.html#bei-jing-da-xue',
source: ['/xygk1/ggtz/:type', '/xygk1/ggtz.htm', '/'],
target: (params) => {
let type = params.type;
switch (type) {
case 'qb.htm':
type = 0;
break;
case 'xytz.htm':
type = 1;
break;
case 'rstz.htm':
type = 2;
break;
case 'jwtz.htm':
type = 6;
break;
case 'xgtz.htm':
type = 8;
break;
case 'kytz.htm':
type = 7;
break;
case 'cwtz.htm':
type = 5;
break;
case 'ghtz.htm':
type = 3;
break;
case 'yytz.htm':
type = 4;
break;
default:
type = 0;
break;
}
return `/pku/eecs/${type}`;
},
},
],
hr: [
{
title: '人事处',
@ -9,5 +76,47 @@ module.exports = {
target: '/pku/hr/:category?',
},
],
'www.rccp': [
{
title: '每周一推 - 中国政治学研究中心',
docs: 'https://docs.rsshub.app/university.html#bei-jing-da-xue-ren-shi-chu',
source: ['/'],
target: '/pku/rccp/mzyt',
},
],
scc: [
{
title: '学生就业指导服务中心',
docs: 'https://docs.rsshub.app/university.html#bei-jing-da-xue-ren-shi-chu',
source: ['/*path'],
target: (params) => {
let type;
switch (params.path) {
case 'home!newsHome.action?category=12':
type = 'xwrd';
break;
case 'home!newsHome.action?category=13':
type = 'tzgg';
break;
case 'home!recruit.action?category=1&jobType=110001':
type = 'zpxx';
break;
case 'home!recruitList.action?category=1&jobType=110002':
type = 'gfjgxx';
break;
case 'home!recruitList.action?category=2':
type = 'sxxx';
break;
case 'home!newsHome.action?category=11':
type = 'cyxx';
break;
default:
type = 'zpxx';
break;
}
return `/pku/scc/recruit/${type}`;
},
},
],
},
};

23
lib/v2/pku/rccp/mzyt.js Normal file
View File

@ -0,0 +1,23 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
const baseUrl = 'https://www.rccp.pku.edu.cn/mzyt/';
module.exports = async (ctx) => {
const response = await got(baseUrl);
const $ = cheerio.load(response.data);
ctx.state.data = {
title: '每周一推 - 北京大学中国政治学研究中心',
link: baseUrl,
description: $('meta[name="description"]').attr('content'),
item: $('li.list')
.map((index, item) => ({
title: $(item).find('a').text().trim(),
description: '',
pubDate: parseDate($(item).find('span').first().text(), '[YYYY-MM-DD]'),
link: baseUrl + $(item).find('a').attr('href'),
}))
.get(),
};
};

View File

@ -1,3 +1,9 @@
module.exports = function (router) {
router.get('/admission/sszs', require('./pkuyjs'));
router.get('/bbs/hot', require('./bbs/hot'));
router.get('/cls/lecture', require('./cls/lecture'));
router.get('/eecs/:type?', require('./eecs'));
router.get('/hr/:category?', require('./hr'));
router.get('/rccp/mzyt', require('./rccp/mzyt'));
router.get('/scc/recruit/:type?', require('./scc/recruit'));
};

58
lib/v2/pku/scc/recruit.js Normal file
View File

@ -0,0 +1,58 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
const arr = {
xwrd: 'home!newsHome.action?category=12',
tzgg: 'home!newsHome.action?category=13',
zpxx: 'home!recruit.action?category=1&jobType=110001',
gfjgxx: 'home!recruitList.action?category=1&jobType=110002',
sxxx: 'home!recruitList.action?category=2',
cyxx: 'home!newsHome.action?category=11',
};
const baseUrl = 'https://scc.pku.edu.cn/';
module.exports = async (ctx) => {
const type = ctx.params.type ?? 'zpxx';
const rootUrl = baseUrl + arr[type];
const list_response = await got(rootUrl);
const $ = cheerio.load(list_response.data);
const feed_title = $('h2.category').text();
const list = $('div#articleList-body div.item.clearfix')
.map((_, item) => {
item = $(item);
const a = item.find('a');
const date = parseDate(item.find('div.item-date').text());
return {
title: a.text(),
link: new URL(a.attr('href'), baseUrl),
pubDate: date,
};
})
.get();
const sorted = list.sort((a, b) => b.pubDate.getTime() - a.pubDate.getTime()).slice(0, 10);
ctx.state.data = {
title: `北京大学学生就业指导服务中心 - ${feed_title}`,
link: rootUrl,
item: await Promise.all(
sorted.map((item) =>
ctx.cache.tryGet(item.link, async () => {
const detail_page = await got(item.link);
const detail = cheerio.load(detail_page.data);
const script = detail('script', 'div#content-div').html();
if (script !== null) {
const content_route = script.match(/\$\("#content-div"\).load\("(\S+)"\)/)[1];
const content = await got(new URL(content_route, baseUrl).href);
item.description = content.data;
}
return item;
})
)
),
};
};

15
lib/v2/pku/utils.js Normal file
View File

@ -0,0 +1,15 @@
const eecsMap = new Map([
[0, 'qb.htm'],
[1, 'xytz.htm'],
[2, 'rstz.htm'],
[6, 'jwtz.htm'],
[8, 'xgtz.htm'],
[7, 'kytz.htm'],
[5, 'cwtz.htm'],
[3, 'ghtz.htm'],
[4, 'yytz.htm'],
]);
module.exports = {
eecsMap,
};