diff --git a/docs/government.md b/docs/government.md index 7fa2afacbb7803..e39c49b8ae16fd 100644 --- a/docs/government.md +++ b/docs/government.md @@ -1474,6 +1474,10 @@ pageClass: routes +### 司局通知 + + + ## 中华人民共和国农业农村部 ### 新闻 diff --git a/docs/other.md b/docs/other.md index b6727667c16702..b2211dfa026813 100644 --- a/docs/other.md +++ b/docs/other.md @@ -717,6 +717,22 @@ type 为 all 时,category 参数不支持 cost 和 free +## 汽油价格网 + +### 今日油价查询 + + + +::: tip 提示 + +路径处填写对应页面 URL 中 `http://www.qiyoujiage.com/` 和 `.shtml` 之间的字段。下面是一个例子。 + +若订阅 [福建漳州龙海今日油价](http://www.qiyoujiage.com/fujian/zhangzhou/longhai.shtml) 则将对应页面 URL 中 `http://www.qiyoujiage.com/` 和 `.shtml` 之间的字段 `fujian/zhangzhou/longhai` 作为路径填入。此时路由为 [`/qiyoujiage/fujian/zhangzhou/longhai`](https://rsshub.app/qiyoujiage/fujian/zhangzhou/longhai) + +::: + + + ## 且听风吟福利 ### 分类 @@ -925,12 +941,6 @@ type 为 all 时,category 参数不支持 cost 和 free -## 油价 - -### 今日油价 - - - ## 有据 ### 最新文章列表 diff --git a/docs/university.md b/docs/university.md index 0e0bdc754f7c57..ab1019801ff301 100644 --- a/docs/university.md +++ b/docs/university.md @@ -278,6 +278,16 @@ pageClass: routes +### 信息学院通知 + + + +| 学院新闻 | 科研动态 | 本科生培养 | 研究生培养 | +| ---- | ---- | ----- | ----- | +| xyxw | kydt | pydt | pydt2 | + + + ### 教务处通知公告 @@ -310,13 +320,27 @@ pageClass: routes -### 信息学院通知 +### 图书馆通知 - + -| 学院新闻 | 科研动态 | 本科生培养 | 研究生培养 | -| ---- | ---- | ----- | ----- | -| xyxw | kydt | pydt | pydt2 | +| 资源动态 | 新闻动态 | 系列讲座 | +| ---- | ---- | ----- | +| zydt | xwdt | xljz1 | + + + +### 党委学生工作部辅导员发展中心 + + + +::: tip 提示 + +路径处填写对应页面 URL 中 `https://fdy.bnu.edu.cn/` 和 `/index.htm` 之间的字段。下面是一个例子。 + +若订阅 [通知公告 > 队伍建设](https://fdy.bnu.edu.cn/tzgg/dwjs/index.htm) 则将对应页面 URL 中 `https://fdy.bnu.edu.cn/` 和 `/index.htm` 之间的字段 `tzgg/dwjs` 作为路径填入。此时路由为 [`/bnu/fdy/tzgg/dwjs`](https://rsshub.app/bnu/fdy/tzgg/dwjs) + +::: @@ -3021,6 +3045,10 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS ## 西南交通大学 +### 就业招聘信息 + + + ### 交通运输与物流学院 #### 研究生通知 diff --git a/lib/router.js b/lib/router.js index e87e376a13fbb9..7ed0478e4bf16c 100644 --- a/lib/router.js +++ b/lib/router.js @@ -928,9 +928,6 @@ router.get('/chouti/:subject?', lazyloadRouteHandler('./routes/chouti')); // Westore router.get('/westore/new', lazyloadRouteHandler('./routes/westore/new')); -// 油价 -router.get('/oilprice/:area', lazyloadRouteHandler('./routes/oilprice')); - // nHentai router.get('/nhentai/search/:keyword/:mode?', lazyloadRouteHandler('./routes/nhentai/search')); router.get('/nhentai/:key/:keyword/:mode?', lazyloadRouteHandler('./routes/nhentai/other')); diff --git a/lib/routes/oilprice/index.js b/lib/routes/oilprice/index.js deleted file mode 100644 index 1c7dd586abbf93..00000000000000 --- a/lib/routes/oilprice/index.js +++ /dev/null @@ -1,66 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); -const iconv = require('iconv-lite'); - -module.exports = async (ctx) => { - const { area } = ctx.params; - const link = 'http://oil.usd-cny.com/'; - const response = await got({ - method: 'get', - url: link, - responseType: 'buffer', - }); - const $ = cheerio.load(iconv.decode(response.data, 'gb2312')); - const $list = $('.content').eq(0).find('table tbody tr'); - const resultItem = []; - let areaName = ''; - const updateTime = $('.time').text().split(':')[1]; - const labelList = $list - .eq(1) - .find('td') - .slice(1) - .map((index, item) => $(item).text()) - .get(); - - for (let i = 2; i < $list.length; i++) { - if ($list.eq(i).find('td a').attr('href').includes(`oil.usd-cny.com/${area}.htm`)) { - const $item = $list.eq(i); - areaName = $item.find('td a').text(); - const { description, content } = labelList.reduce( - (descObj, label, index) => { - const price = $item - .find('td') - .eq(index + 1) - .text(); - - descObj.description += ` - ${label}: ${price}
- `; - descObj.content += `${label}-${price}; `; - - return descObj; - }, - { - description: '', - content: '', - } - ); - - resultItem.push({ - title: `${updateTime}-${areaName}油价: ${content}`, - description, - link, - guid: updateTime, - pubDate: new Date(updateTime).toUTCString(), - }); - break; - } - } - - ctx.state.data = { - title: `今日油价查询-${areaName}`, - description: '今日汽油价格查询 最新柴油油价实时行情', - link, - item: resultItem, - }; -}; diff --git a/lib/v2/bnu/fdy.js b/lib/v2/bnu/fdy.js new file mode 100644 index 00000000000000..b4319f5377c16d --- /dev/null +++ b/lib/v2/bnu/fdy.js @@ -0,0 +1,41 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); + +module.exports = async (ctx) => { + const baseUrl = 'http://fdy.bnu.edu.cn'; + const { path = 'tzgg' } = ctx.params; + const link = `${baseUrl}/${path}/index.htm`; + + const { data: response } = await got(link); + const $ = cheerio.load(response); + + const list = $('.listconrl li') + .toArray() + .map((item) => { + item = $(item); + const a = item.find('a'); + return { + title: a.attr('title'), + link: new URL(a.attr('href'), link).href, + pubDate: parseDate(item.find('.news-dates').text()), + }; + }); + + const items = await Promise.all( + list.map((item) => + ctx.cache.tryGet(item.link, async () => { + const { data: response } = await got(item.link); + const $ = cheerio.load(response); + item.description = $('.listconrc-newszw').html(); + return item; + }) + ) + ); + + ctx.state.data = { + title: $('head title').text(), + link, + item: items, + }; +}; diff --git a/lib/v2/bnu/lib.js b/lib/v2/bnu/lib.js new file mode 100644 index 00000000000000..0ef008ba92f8c1 --- /dev/null +++ b/lib/v2/bnu/lib.js @@ -0,0 +1,40 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); + +module.exports = async (ctx) => { + const baseUrl = 'http://www.lib.bnu.edu.cn'; + const { category = 'zydt' } = ctx.params; + const link = `${baseUrl}/${category}/index.htm`; + + const { data: response } = await got(link); + const $ = cheerio.load(response); + + const list = $('.view-content .item-list li') + .toArray() + .map((item) => { + item = $(item); + return { + title: item.find('a').text(), + link: `${baseUrl}/${category}/${item.find('a').attr('href')}`, + pubDate: parseDate(item.find('span > span').eq(1).text(), 'YYYY-MM-DD'), + }; + }); + + const items = await Promise.all( + list.map((item) => + ctx.cache.tryGet(item.link, async () => { + const { data: response } = await got(item.link); + const $ = cheerio.load(response); + item.description = $('#block-system-main .content .content').html(); + return item; + }) + ) + ); + + ctx.state.data = { + title: $('head title').text(), + link, + item: items, + }; +}; diff --git a/lib/v2/bnu/maintainer.js b/lib/v2/bnu/maintainer.js index b8aaba34f6d1dd..f452e47d5e596f 100644 --- a/lib/v2/bnu/maintainer.js +++ b/lib/v2/bnu/maintainer.js @@ -1,3 +1,6 @@ module.exports = { '/bs/:category?': ['nczitzk'], + '/dwxgb/:category/:type': ['Fatpandac'], + '/fdy/:path*': ['TonyRL'], + '/lib/:category?': ['TonyRL'], }; diff --git a/lib/v2/bnu/radar.js b/lib/v2/bnu/radar.js index 471cb5c959cbc6..ddb8a67c10b982 100644 --- a/lib/v2/bnu/radar.js +++ b/lib/v2/bnu/radar.js @@ -1,19 +1,37 @@ module.exports = { 'bnu.edu.cn': { _name: '北京师范大学', - '.': [ + bs: [ { title: '经济与工商管理学院', docs: 'https://docs.rsshub.app/university.html#bei-jing-shi-fan-da-xue', - source: ['/'], - target: '/bs/:category?', + source: ['/:category/index.html'], + target: '/bnu/bs/:category', }, + ], + dwxgb: [ { - title: '经济与工商管理学院', + title: '党委学生工作部', docs: 'https://docs.rsshub.app/university.html#bei-jing-shi-fan-da-xue', - source: ['/'], + source: ['/:category/:type/index.html'], target: '/bnu/dwxgb/:category/:type', }, ], + fdy: [ + { + title: '党委学生工作部辅导员发展中心', + docs: 'https://docs.rsshub.app/university.html#bei-jing-shi-fan-da-xue', + source: ['/'], + target: (_, url) => `/bnu/fdy${new URL(url).pathname.replace(/\/index\.htm(l)?$/, '')}`, + }, + ], + 'www.lib': [ + { + title: '图书馆通知', + docs: 'https://docs.rsshub.app/university.html#bei-jing-shi-fan-da-xue', + source: ['/:category/index.htm'], + target: '/bnu/lib/:category', + }, + ], }, }; diff --git a/lib/v2/bnu/router.js b/lib/v2/bnu/router.js index e605fe286daa52..58e357684afde1 100644 --- a/lib/v2/bnu/router.js +++ b/lib/v2/bnu/router.js @@ -1,4 +1,6 @@ module.exports = function (router) { router.get('/bs/:category?', require('./bs')); router.get('/dwxgb/:category/:type', require('./dwxgb')); + router.get('/fdy/:path*', require('./fdy')); + router.get('/lib/:category?', require('./lib')); }; diff --git a/lib/v2/gov/maintainer.js b/lib/v2/gov/maintainer.js index 502d0bbf2e4aac..db91bcd2bd0020 100644 --- a/lib/v2/gov/maintainer.js +++ b/lib/v2/gov/maintainer.js @@ -23,6 +23,7 @@ module.exports = { '/miit/wjgs': ['Yoge-Code'], '/miit/zcjd': ['Yoge-Code'], '/moe/:type': ['Crawler995'], + '/moe/s78/:column': ['TonyRL'], '/mofcom/article/:suffix+': ['LogicJake'], '/moj/aac/news/:type?': ['TonyRL'], '/nifdc/:path+': ['nczitzk'], diff --git a/lib/v2/gov/moe/moe.js b/lib/v2/gov/moe/moe.js index 8c38644137299b..feb773f41d9e9a 100644 --- a/lib/v2/gov/moe/moe.js +++ b/lib/v2/gov/moe/moe.js @@ -17,10 +17,10 @@ module.exports = async (ctx) => { let id = ''; let name = ''; - for (let i = 0; i < typesIdMap.length; i++) { - if (typesIdMap[i].type === type) { - id = typesIdMap[i].id; - name = typesIdMap[i].name; + for (const item of typesIdMap) { + if (item.type === type) { + id = item.id; + name = item.name; } } diff --git a/lib/v2/gov/moe/s78.js b/lib/v2/gov/moe/s78.js new file mode 100644 index 00000000000000..661849591ef4cf --- /dev/null +++ b/lib/v2/gov/moe/s78.js @@ -0,0 +1,44 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); +const timezone = require('@/utils/timezone'); + +module.exports = async (ctx) => { + const baseUrl = 'https://www.moe.gov.cn'; + const { column } = ctx.params; + const link = `${baseUrl}/s78/${column}/tongzhi/`; + + const { data: response } = await got(link); + const $ = cheerio.load(response); + + const list = $('#list li') + .toArray() + .map((item) => { + item = $(item); + return { + title: item.find('a').attr('title'), + link: new URL(item.find('a').attr('href'), link).href, + pubDate: timezone(parseDate(item.find('span').text(), 'YYYY-MM-DD'), +8), + }; + }); + + const items = await Promise.all( + list.map((item) => + ctx.cache.tryGet(item.link, async () => { + const { data: response } = await got(item.link); + const $ = cheerio.load(response); + + $('#moe-detail-page-set, #moeCode, .moe-detail-shuxing, h1').remove(); + item.description = $('.moe-detail-box').html(); + + return item; + }) + ) + ); + + ctx.state.data = { + title: `${$('meta[name="ColumnType"]').attr('content')} - ${$('head title').text()}`, + link, + item: items, + }; +}; diff --git a/lib/v2/gov/radar.js b/lib/v2/gov/radar.js index c56545129c96e4..d6928a592c18fc 100644 --- a/lib/v2/gov/radar.js +++ b/lib/v2/gov/radar.js @@ -681,6 +681,12 @@ module.exports = { source: ['/'], target: '/gov/moe/newest_file', }, + { + title: '司局通知', + docs: 'https://docs.rsshub.app/government.html#zhong-hua-ren-min-gong-he-guo-jiao-yu-bu', + source: ['/s78/:column/tongzhi', '/s78/:column'], + target: '/gov/moe/s78/:column', + }, ], }, 'mofcom.gov.cn': { diff --git a/lib/v2/gov/router.js b/lib/v2/gov/router.js index 6c44873bd51343..d6e360fc113f7c 100644 --- a/lib/v2/gov/router.js +++ b/lib/v2/gov/router.js @@ -15,6 +15,7 @@ module.exports = function (router) { router.get('/miit/wjgs', require('./miit/wjgs')); router.get('/miit/zcjd', require('./miit/zcjd')); router.get('/moe/:type', require('./moe/moe')); + router.get('/moe/s78/:column', require('./moe/s78')); router.get('/mofcom/article/:suffix+', require('./mofcom/article')); router.get('/moj/aac/news/:type?', require('./moj/aac/news')); router.get(/nifdc\/([\w/-]+)?/, require('./nifdc')); diff --git a/lib/v2/qiyoujiage/maintainer.js b/lib/v2/qiyoujiage/maintainer.js new file mode 100644 index 00000000000000..e14a130df9b189 --- /dev/null +++ b/lib/v2/qiyoujiage/maintainer.js @@ -0,0 +1,3 @@ +module.exports = { + '/:path+': ['TonyRL'], +}; diff --git a/lib/v2/qiyoujiage/price.js b/lib/v2/qiyoujiage/price.js new file mode 100644 index 00000000000000..b2926700f0dbb4 --- /dev/null +++ b/lib/v2/qiyoujiage/price.js @@ -0,0 +1,28 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const md5 = require('@/utils/md5'); + +module.exports = async (ctx) => { + const { path } = ctx.params; + const link = `http://www.qiyoujiage.com/${path}.shtml`; + + const { data: response } = await got(link); + const $ = cheerio.load(response); + + const priceText = $('#youjia').text(); + const item = [ + { + title: priceText, + description: $('#youjia').html(), + link, + guid: `${link}#${md5(priceText)}`, + }, + ]; + + ctx.state.data = { + title: $('title').text(), + description: $('meta[name="Description"]').attr('content'), + link, + item, + }; +}; diff --git a/lib/v2/qiyoujiage/radar.js b/lib/v2/qiyoujiage/radar.js new file mode 100644 index 00000000000000..c29822e00d763f --- /dev/null +++ b/lib/v2/qiyoujiage/radar.js @@ -0,0 +1,13 @@ +module.exports = { + 'qiyoujiage.com': { + _name: '汽油价格网', + '.': [ + { + title: '今日油价查询', + docs: 'https://docs.rsshub.app/other.html#qi-you-jia-ge-wang', + source: ['/*'], + target: (_, url) => `/qiyoujiage${new URL(url).pathname.replace('.shtml', '')}`, + }, + ], + }, +}; diff --git a/lib/v2/qiyoujiage/router.js b/lib/v2/qiyoujiage/router.js new file mode 100644 index 00000000000000..365a01c2f3c017 --- /dev/null +++ b/lib/v2/qiyoujiage/router.js @@ -0,0 +1,3 @@ +module.exports = (router) => { + router.get('/:path+', require('./price')); +}; diff --git a/lib/v2/swjtu/jtys/yjs.js b/lib/v2/swjtu/jtys/yjs.js index e16134c618fe4e..2727225ec616b0 100644 --- a/lib/v2/swjtu/jtys/yjs.js +++ b/lib/v2/swjtu/jtys/yjs.js @@ -5,6 +5,31 @@ const { parseDate } = require('@/utils/parse-date'); const rootURL = 'https://ctt.swjtu.edu.cn'; const url_addr = `${rootURL}/yethan/WebIndexAction?setAction=newsList&bigTypeId=0E4BF4D36E232918`; +const getItem = (item, cache) => { + const news_info = item.find('div[class="news-title newsInfo"]'); + const news_month = item.find('.month').text(); + const news_day = item.find('.day').text(); + + const info_id = news_info.attr('newsid'); + const info_title = news_info.text(); + const link = `${rootURL}/yethan/WebIndexAction?setAction=newsInfo&newsId=${info_id}`; + return cache.tryGet(link, async () => { + const resp = await got({ + method: 'get', + url: link, + }); + const $$ = cheerio.load(resp.data); + const info_text = $$('.news-left').html(); + + return { + title: info_title, + pubDate: parseDate(`${news_month}.${news_day}`), + link, + description: info_text, + }; + }); +}; + module.exports = async (ctx) => { const resp = await got({ method: 'get', @@ -14,22 +39,17 @@ module.exports = async (ctx) => { const $ = cheerio.load(resp.data); const list = $("[class='news-list flex']"); + const items = await Promise.all( + list.toArray().map((i) => { + const item = $(i); + return getItem(item, ctx.cache); + }) + ); + ctx.state.data = { title: '西南交大交运学院-研究生通知', link: url_addr, - item: - list && - list.toArray().map((i) => { - const item = $(i); - const news_info = item.find('div[class="news-title newsInfo"]'); - const news_month = item.find('.month'); - const news_day = item.find('.day'); - return { - title: `标题:${news_info.text()}`, - pubDate: parseDate(`${news_month.text()}.${news_day.text()}`), - link: `${rootURL}/yethan/WebIndexAction?setAction=newsInfo&newsId=${news_info.attr('newsid')}`, - }; - }), + item: items, allowEmpty: true, }; }; diff --git a/lib/v2/swjtu/jyzpxx.js b/lib/v2/swjtu/jyzpxx.js new file mode 100644 index 00000000000000..ffb800c8b91ccc --- /dev/null +++ b/lib/v2/swjtu/jyzpxx.js @@ -0,0 +1,27 @@ +const utils = require('./utils'); +const got = require('@/utils/got'); + +const rootURL = 'https://jiuye.swjtu.edu.cn/career'; + +module.exports = async (ctx) => { + const resp = await got({ + method: 'post', + url: `${rootURL}/zpxx/search/zpxx/1/30`, + }); + + const list = resp.data.data.list; + + const items = await Promise.all( + list.map((item) => { + const key = `${rootURL}/zpxx/data/zpxx/${item.zpxxid}`; + return utils.descpPage(key, ctx.cache); + }) + ); + + ctx.state.data = { + title: '西南交大-就业招聘信息', + link: `${rootURL}/zpxx/zpxx`, + item: items, + allowEmpty: true, + }; +}; diff --git a/lib/v2/swjtu/maintainer.js b/lib/v2/swjtu/maintainer.js index 7ebf1e43026686..47c795c3e3181f 100644 --- a/lib/v2/swjtu/maintainer.js +++ b/lib/v2/swjtu/maintainer.js @@ -1,3 +1,4 @@ module.exports = { '/jtys/yjs': ['qizidog'], + '/jyzpxx': ['qizidog'], }; diff --git a/lib/v2/swjtu/radar.js b/lib/v2/swjtu/radar.js index c9c280ca315ec1..6717d179f97133 100644 --- a/lib/v2/swjtu/radar.js +++ b/lib/v2/swjtu/radar.js @@ -9,5 +9,13 @@ module.exports = { target: (_, url) => (new URL(url).searchParams.get('setAction') === 'newsList' && new URL(url).searchParams.get('bigTypeId') === '0E4BF4D36E232918' ? '/swjtu/jtys/yjs' : null), }, ], + jiuye: [ + { + title: '就业招聘信息', + docs: 'https://docs.rsshub.app/university.html#xi-nan-jiao-tong-da-xue', + source: ['/career', '/'], + target: '/swjtu/jyzpxx', + }, + ], }, }; diff --git a/lib/v2/swjtu/router.js b/lib/v2/swjtu/router.js index fa5fd6b1a28ae0..632f5957b851e0 100644 --- a/lib/v2/swjtu/router.js +++ b/lib/v2/swjtu/router.js @@ -1,3 +1,4 @@ module.exports = function (router) { router.get('/jtys/yjs', require('./jtys/yjs')); + router.get('/jyzpxx', require('./jyzpxx')); }; diff --git a/lib/v2/swjtu/templates/job_desc.art b/lib/v2/swjtu/templates/job_desc.art new file mode 100644 index 00000000000000..0c4a793ff94908 --- /dev/null +++ b/lib/v2/swjtu/templates/job_desc.art @@ -0,0 +1,19 @@ +
+
+

招聘主题:{{ intro.zpzt }}

+

单位名称:{{ intro.dwmc }}

+

单位性质:{{ intro.xzyjmc }}

+

行业名称:{{ intro.hyyjmc }}({{ intro.hyejmc }})

+

公司规模:{{ intro.rsgmmc }}

+

工作地点:{{ intro.szxmc }} {{ intro.xxdz }}

+

招聘截止日期:{{ intro.zpjzrq }}

+

简历投递邮箱:{{ intro.jltdyx }}

+

单位网站:{{ intro.dwwz }}

+
+ + {{@ job_list }} + +
+ {{@ intro.zpxxEditor }} +
+
\ No newline at end of file diff --git a/lib/v2/swjtu/templates/job_detail.art b/lib/v2/swjtu/templates/job_detail.art new file mode 100644 index 00000000000000..de3e2a13419bb3 --- /dev/null +++ b/lib/v2/swjtu/templates/job_detail.art @@ -0,0 +1,21 @@ +
+

招聘职位:

+ + + + + + + + + {{each jobs}} + + + + + + + + {{/each}} +
职位名称职位月薪工作地点专业需求应聘条件
{{$value.zwmc}}{{$value.yxmc}}/月{{$value.gzdz}}{{$value.zyyqmc}}{{$value.zwms}}
+
\ No newline at end of file diff --git a/lib/v2/swjtu/utils.js b/lib/v2/swjtu/utils.js new file mode 100644 index 00000000000000..7667cd7502ffab --- /dev/null +++ b/lib/v2/swjtu/utils.js @@ -0,0 +1,33 @@ +const got = require('@/utils/got'); +const { art } = require('@/utils/render'); +const { parseDate } = require('@/utils/parse-date'); +const path = require('path'); + +const renderDetail = (jobs) => art(path.join(__dirname, 'templates/job_detail.art'), { jobs }); +const renderDesc = (intro) => + art(path.join(__dirname, 'templates/job_desc.art'), { + intro, + job_list: renderDetail(intro.zwxxList), + }); + +const descpPage = (link, cache) => + cache.tryGet(link, async () => { + const data = await got({ + method: 'post', + url: link, + }); + const intro = data.data.data; + + return { + title: `${intro.dwmc}(${intro.xzyjmc})`, + pubDate: parseDate(String(intro.fbrq)), + description: renderDesc(intro), + link: String(link.replace('data', 'view')), + }; + }); + +module.exports = { + descpPage, + renderDetail, + renderDesc, +};