diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index 27b8019af..ce438a156 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -20,7 +20,7 @@ on: permissions: contents: read - + concurrency: group: ${{ github.head_ref }} cancel-in-progress: true diff --git a/docs/government.md b/docs/government.md index 8ca07b535..641056a53 100644 --- a/docs/government.md +++ b/docs/government.md @@ -718,6 +718,12 @@ pageClass: routes +## 南京鼓楼医院 + +### 员工版教育培训 + + + ## 南京市人民政府 ### 信息公开 diff --git a/docs/university.md b/docs/university.md index 9d6245e89..883076f0d 100644 --- a/docs/university.md +++ b/docs/university.md @@ -2246,6 +2246,12 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS +## 南京中医药大学 + +### 研究生院博士招生 + + + ## 南开大学 ### 南开大学教务处 diff --git a/lib/v2/njglyy/maintainer.js b/lib/v2/njglyy/maintainer.js new file mode 100644 index 000000000..57b94cca5 --- /dev/null +++ b/lib/v2/njglyy/maintainer.js @@ -0,0 +1,3 @@ +module.exports = { + '/ygbjypx': ['real-jiakai'], +}; diff --git a/lib/v2/njglyy/radar.js b/lib/v2/njglyy/radar.js new file mode 100644 index 000000000..4342187f1 --- /dev/null +++ b/lib/v2/njglyy/radar.js @@ -0,0 +1,13 @@ +module.exports = { + 'njglyy.com': { + _name: '南京鼓楼医院', + '.': [ + { + title: '员工版教育培训', + docs: 'https://docs.rsshub.app/university.html#nan-jing-gu-lou-yi-yuan-yuan-gong-ban-jiao-yu-pei-xun', + source: ['/ygb/jypx/jypx.aspx', '/'], + target: '/njglyy/ygbjypx', + }, + ], + }, +}; diff --git a/lib/v2/njglyy/router.js b/lib/v2/njglyy/router.js new file mode 100644 index 000000000..25adeebce --- /dev/null +++ b/lib/v2/njglyy/router.js @@ -0,0 +1,3 @@ +module.exports = (router) => { + router.get('/ygbjypx', require('./ygbjypx')); +}; diff --git a/lib/v2/njglyy/utils/index.js b/lib/v2/njglyy/utils/index.js new file mode 100644 index 000000000..b598f8f71 --- /dev/null +++ b/lib/v2/njglyy/utils/index.js @@ -0,0 +1,50 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); +const timezone = require('@/utils/timezone'); + +async function getNoticeList(ctx, url, host, listSelector, itemSelector, titleSelector, contentSelector) { + const response = await got(url); + const $ = cheerio.load(response.data); + + const list = $(listSelector) + .toArray() + .map((item) => { + item = $(item); + return { + title: item.find(titleSelector).text(), + link: host + item.find(itemSelector).attr('href'), + }; + }); + + const out = await Promise.all( + list.map((item) => + ctx.cache.tryGet(item.link, async () => { + const response = await got(item.link); + if (response.redirectUrls.length) { + item.link = response.redirectUrls[0]; + item.description = '该通知无法直接预览,请点击原文链接↑查看'; + } else { + const $ = cheerio.load(response.data); + item.title = $(contentSelector.title).text(); + item.description = $(contentSelector.content) + .html() + .replace(/src="\//g, `src="${new URL('.', host).href}`) + .replace(/href="\//g, `href="${new URL('.', host).href}`) + .trim(); + const preDate = $(contentSelector.date) + .text() + .match(/(\d{4}-\d{2}-\d{2})/)[1]; + item.pubDate = timezone(parseDate(preDate, 'YYYY-MM-DD'), +8); + } + return item; + }) + ) + ); + + return out; +} + +module.exports = { + getNoticeList, +}; diff --git a/lib/v2/njglyy/ygbjypx.js b/lib/v2/njglyy/ygbjypx.js new file mode 100644 index 000000000..7980635ff --- /dev/null +++ b/lib/v2/njglyy/ygbjypx.js @@ -0,0 +1,18 @@ +const { getNoticeList } = require('./utils'); + +const url = 'https://njglyy.com/ygb/jypx/jypx.aspx'; +const host = 'https://njglyy.com/ygb/jypx/'; + +module.exports = async (ctx) => { + const out = await getNoticeList(ctx, url, host, '.mtbd-list > dl', 'a', 'dt', { + title: '.detail', + content: '.detail2', + date: 'span:contains("发布时间")', + }); + + ctx.state.data = { + title: '南京鼓楼医院 -- 员工版教育培训', + link: url, + item: out, + }; +}; diff --git a/lib/v2/njucm/grabs.js b/lib/v2/njucm/grabs.js new file mode 100644 index 000000000..e454a07b7 --- /dev/null +++ b/lib/v2/njucm/grabs.js @@ -0,0 +1,18 @@ +const { getNoticeList } = require('./utils'); + +const url = 'https://gra.njucm.edu.cn/2899/list.htm'; +const host = 'https://gra.njucm.edu.cn'; + +module.exports = async (ctx) => { + const out = await getNoticeList(ctx, url, host, '#wp_news_w3 > table > tbody > tr', 'a', { + title: '.Article_Title', + content: '.Article_Content', + date: '.Article_PublishDate', + }); + + ctx.state.data = { + title: '南京中医药大学 -- 博士招生', + link: url, + item: out, + }; +}; diff --git a/lib/v2/njucm/maintainer.js b/lib/v2/njucm/maintainer.js new file mode 100644 index 000000000..9ab083e5d --- /dev/null +++ b/lib/v2/njucm/maintainer.js @@ -0,0 +1,3 @@ +module.exports = { + '/grabszs': ['real-jiakai'], +}; diff --git a/lib/v2/njucm/radar.js b/lib/v2/njucm/radar.js new file mode 100644 index 000000000..bd0dd4659 --- /dev/null +++ b/lib/v2/njucm/radar.js @@ -0,0 +1,13 @@ +module.exports = { + 'njucm.edu.cn': { + _name: '南京中医药大学', + lib: [ + { + title: '研究生院博士招生', + docs: 'https://docs.rsshub.app/university.html#nan-jing-zhong-yi-yao-da-xue-yan-jiu-sheng-yuan-bo-shi-zhao-sheng', + source: ['/2899/list.htm', '/'], + target: '/njucm/grabszs', + }, + ], + }, +}; diff --git a/lib/v2/njucm/router.js b/lib/v2/njucm/router.js new file mode 100644 index 000000000..4caf175bb --- /dev/null +++ b/lib/v2/njucm/router.js @@ -0,0 +1,3 @@ +module.exports = (router) => { + router.get('/grabszs', require('./grabs')); +}; diff --git a/lib/v2/njucm/utils/index.js b/lib/v2/njucm/utils/index.js new file mode 100644 index 000000000..8f131f665 --- /dev/null +++ b/lib/v2/njucm/utils/index.js @@ -0,0 +1,47 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); +const timezone = require('@/utils/timezone'); + +async function getNoticeList(ctx, url, host, listSelector, titleSelector, contentSelector) { + const response = await got(url); + const $ = cheerio.load(response.data); + + const list = $(listSelector) + .toArray() + .map((item) => { + item = $(item); + return { + title: item.find(titleSelector).attr('title'), + link: host + item.find(titleSelector).attr('href'), + }; + }); + + const out = await Promise.all( + list.map((item) => + ctx.cache.tryGet(item.link, async () => { + const response = await got(item.link); + if (response.redirectUrls.length) { + item.link = response.redirectUrls[0]; + item.description = '该通知无法直接预览,请点击原文链接↑查看'; + } else { + const $ = cheerio.load(response.data); + item.title = $(contentSelector.title).text(); + item.description = $(contentSelector.content) + .html() + .replace(/src="\//g, `src="${new URL('.', host).href}`) + .replace(/href="\//g, `href="${new URL('.', host).href}`) + .trim(); + item.pubDate = timezone(parseDate($(contentSelector.date).text()), +8); + } + return item; + }) + ) + ); + + return out; +} + +module.exports = { + getNoticeList, +};