diff --git a/docs/README.md b/docs/README.md index 20a21e9a53..c6a3ed61e0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1278,15 +1278,15 @@ GitHub 官方也提供了一些 RSS: ### 直播开播 -见 <#哔哩哔哩直播> +见 [#哔哩哔哩直播](#哔哩哔哩直播) ### 直播搜索 -见 <#哔哩哔哩直播> +见 [#哔哩哔哩直播](#哔哩哔哩直播) ### 直播分区 -见 <#哔哩哔哩直播> +见 [#哔哩哔哩直播](#哔哩哔哩直播) ### 主站话题列表 @@ -1506,6 +1506,14 @@ GitHub 官方也提供了一些 RSS: - id, 用户 id, 可在即刻 web 端用户页 URL 中找到 +### 即刻小报 + +举例: + +路由: `/jike/daily` + +参数: 无 + ## 微信 ::: tip 提示 @@ -2587,7 +2595,7 @@ GitHub 官方也提供了一些 RSS: ### App Store/Mac App Store -见 <#app-store-mac-app-store> +见 [#app-store-mac-app-store](#app-store-mac-app-store) ## Minecraft CurseForge diff --git a/docs/en/README.md b/docs/en/README.md index c74d8d912c..932f4d8dc5 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -15,16 +15,9 @@ RSSHub is a lightweight and extensible RSS feed aggregator, it's able to generat ### Special Sponsors -

- - - -

-

- - - -

+| | | | +| :-----------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------: | + ### Sponsors diff --git a/docs/en/joinus/README.md b/docs/en/joinus/README.md index 39e7a8899a..c04138a30c 100644 --- a/docs/en/joinus/README.md +++ b/docs/en/joinus/README.md @@ -96,7 +96,7 @@ ctx.state.data = { itunes_item_image: '', // The item image enclosure_url: '', // The item's audio link enclosure_length: '', // The audio length, the unit is seconds. - enclosure_type: '', // 'audio/mpeg' or 'audio/m4a' or others + enclosure_type: '', // 'audio/mpeg' or 'audio/x-m4a' or others itunes_duration: '', // Covert the 'enclosure_length' to hh:mm:ss (1:33:52) }, ], diff --git a/docs/joinus/README.md b/docs/joinus/README.md index 1ee13ba0ec..156839294a 100644 --- a/docs/joinus/README.md +++ b/docs/joinus/README.md @@ -96,7 +96,7 @@ ctx.state.data = { itunes_item_image: '', // 图像 enclosure_url: '', // 音频链接 enclosure_length: '', // 时间戳 (播放长度) , 一般是秒数 - enclosure_type: '', // [.mp3就填'audio/mpeg'] [.m4a就填'audio/m4a'], 或其他类型. + enclosure_type: '', // [.mp3就填'audio/mpeg'] [.m4a就填'audio/x-m4a'], 或其他类型. itunes_duration: '', // 由enclosure_length转换为 时:分:秒 }, ], diff --git a/router.js b/router.js index ff196f4019..cab1da7138 100755 --- a/router.js +++ b/router.js @@ -233,6 +233,7 @@ if (config.youtube && config.youtube.key) { router.get('/jike/topic/:id', require('./routes/jike/topic')); router.get('/jike/topic/square/:id', require('./routes/jike/topicSquare')); router.get('/jike/user/:id', require('./routes/jike/user')); +router.get('/jike/daily', require('./routes/jike/daily')); // 极客时间 router.get('/geektime/column/:cid', require('./routes/geektime/column')); diff --git a/routes/bilibili/partion-ranking.js b/routes/bilibili/partion-ranking.js index 37f5edf80a..0173f8bbbb 100644 --- a/routes/bilibili/partion-ranking.js +++ b/routes/bilibili/partion-ranking.js @@ -40,7 +40,7 @@ module.exports = async (ctx) => { item = { title: `${item.title} - ${item.author}`, - description: `${item.description}
Tags:${item.tag}`, + description: `${item.description}
Tags:${item.tag}`, pubDate: new Date(item.pubdate).toUTCString(), link: item.arcurl, }; diff --git a/routes/jike/daily.js b/routes/jike/daily.js new file mode 100644 index 0000000000..fbe6eea98b --- /dev/null +++ b/routes/jike/daily.js @@ -0,0 +1,19 @@ +const axios = require('../../utils/axios'); + +module.exports = async (ctx) => { + const { + data: { data }, + } = await axios.get('https://app.jike.ruguoapp.com/1.0/dailies/list'); + + ctx.state.data = { + title: '即刻小报', + link: 'https://jike.app/', + description: '不定期呈现的即刻内容精选', + item: data.map((item) => ({ + title: item.title, + description: ``, + pubDate: new Date(item.date).toUTCString(), + link: `https://m.okjike.com/dailies/${item.id}`, + })), + }; +}; diff --git a/routes/universities/njupt/jwc.js b/routes/universities/njupt/jwc.js index a1468f9a91..90a6f8fa57 100644 --- a/routes/universities/njupt/jwc.js +++ b/routes/universities/njupt/jwc.js @@ -21,39 +21,59 @@ module.exports = async (ctx) => { }); const $ = cheerio.load(response.data); - const list = $('.content') + const urlList = $('.content') .find('a') .slice(0, 10) .map((i, e) => $(e).attr('href')) .get(); + const titleList = $('.content') + .find('a') + .slice(0, 10) + .map((i, e) => $(e).attr('title')) + .get(); + + const dateList = $('.content tr') + .find('div') + .slice(0, 10) + .map((i, e) => $(e).text()) + .get(); + const out = await Promise.all( - list.map(async (itemUrl) => { + urlList.map(async (itemUrl, index) => { itemUrl = url.resolve(host, itemUrl); - const cache = await ctx.cache.get(itemUrl); - if (cache) { - return Promise.resolve(JSON.parse(cache)); + if (itemUrl.indexOf('.htm') !== -1) { + const cache = await ctx.cache.get(itemUrl); + if (cache) { + return Promise.resolve(JSON.parse(cache)); + } + const response = await axios.get(itemUrl); + const $ = cheerio.load(response.data); + const single = { + title: $('.Article_Title').text(), + link: itemUrl, + description: $('.wp_articlecontent') + .html() + .replace(/src="\//g, `src="${url.resolve(host, '.')}`) + .replace(/href="\//g, `href="${url.resolve(host, '.')}`) + .trim(), + pubDate: new Date( + $('.Article_PublishDate') + .text() + .replace('发布时间:', '') + ), + }; + ctx.cache.set(itemUrl, JSON.stringify(single), 24 * 60 * 60); + return Promise.resolve(single); + } else { + const single = { + title: titleList[index], + link: itemUrl, + description: '该通知为文件,请点击原文链接↑下载', + pubDate: dateList, + }; + return Promise.resolve(single); } - - const response = await axios.get(itemUrl); - const $ = cheerio.load(response.data); - - const single = { - title: $('.Article_Title').text(), - link: itemUrl, - description: $('.wp_articlecontent') - .html() - .replace(/src="\//g, `src="${url.resolve(host, '.')}`) - .replace(/href="\//g, `href="${url.resolve(host, '.')}`) - .trim(), - pubDate: new Date( - $('.Article_PublishDate') - .text() - .replace('发布时间:', '') - ), - }; - ctx.cache.set(itemUrl, JSON.stringify(single), 24 * 60 * 60); - return Promise.resolve(single); }) ); let info = '通知公告'; diff --git a/routes/universities/pku/eecs.js b/routes/universities/pku/eecs.js index fbc14383de..24b24baff0 100644 --- a/routes/universities/pku/eecs.js +++ b/routes/universities/pku/eecs.js @@ -21,7 +21,7 @@ module.exports = async (ctx) => { const text = $('.hvr-shutter-out-vertical'); ctx.state.data = { - title: '', + title: '北大信科通知', link: host + 'Survey/Notice/?Mtitle=' + type, description: '北大信科 公告通知', item: @@ -31,7 +31,7 @@ module.exports = async (ctx) => { item = $(item); return { title: item.find('p').text(), - link: host + item.attr('href'), + link: host + 'Survey/Notice/' + item.attr('href'), description: item.find('p').text(), pubDate: item.find('em').text(), }; diff --git a/routes/ximalaya/album.js b/routes/ximalaya/album.js index 29adc01c57..3e4fde7077 100644 --- a/routes/ximalaya/album.js +++ b/routes/ximalaya/album.js @@ -1,67 +1,77 @@ const axios = require('../../utils/axios'); const baseUrl = 'http://www.ximalaya.com'; -const axios_ins = axios.create({ - responseType: 'json', -}); +const axios_ins = axios.create({}); module.exports = async (ctx) => { const id = ctx.params.id; // 专辑id - const AlbumInfoApi = `http://www.ximalaya.com/revision/album?albumId=${id}`; // 专辑数据的API + const TrackInfoApi = 'http://mobile.ximalaya.com/v1/track/baseInfo?device=android&trackId='; + const AlbumInfoApi = `https://www.ximalaya.com/revision/album?albumId=${id}`; // 专辑数据的API const AlbumInfoResponse = await axios_ins.get(AlbumInfoApi); - const albuminfo = AlbumInfoResponse.data.data.mainInfo; // 专辑数据 const authorinfo = AlbumInfoResponse.data.data.anchorInfo; // 作者数据 - const trackinfo = AlbumInfoResponse.data.data.tracksInfo; // tracks数据 + const author = authorinfo.anchorName; + const author_intro = authorinfo.personalIntroduction; - const classify = albuminfo.crumbs.categoryPinyin; // 专辑分类的拼音 - const album_category = albuminfo.crumbs.categoryTitle; // 专辑分类 + const albuminfo = AlbumInfoResponse.data.data.mainInfo; // 专辑数据 + const album_title = albuminfo.albumTitle; // 专辑标题 + const album_cover = albuminfo.cover.split('&')[0]; + const classify = albuminfo.crumbs.categoryPinyin; // 专辑分类 + const album_category = albuminfo.crumbs.categoryTitle; // 专辑分类名字 + const album_intro = albuminfo.richIntro; // 专辑介绍 + const album_desc = author_intro + '
' + album_intro; const albumUrl = '/' + classify + '/' + id + '/'; // 某分类的链接 const ispaid = albuminfo.isPaid; // 是否需要付费 - const album_title = albuminfo.albumTitle; // 专辑标题 - const album_url = baseUrl + albumUrl; // 专辑链接 - const album_desc = authorinfo.anchorName + ' ' + authorinfo.personalIntroduction + '
' + albuminfo.detailRichIntro; - const album_cover_url = albuminfo.cover.split('&')[0]; - const album_author = authorinfo.anchorName; - const tracks_count = trackinfo.trackTotalCount; - const PlayInfoApi = `http://mobile.ximalaya.com/mobile/v1/album/track?albumId=${id}&pageSize=${tracks_count}`; // 声音播放数据 - const PlayInfoResponse = await axios_ins.get(PlayInfoApi); - - const playList = PlayInfoResponse.data.data.list; + const tracksinfo = AlbumInfoResponse.data.data.tracksInfo; // 专辑数据 + const playList = tracksinfo.tracks; const resultItems = await Promise.all( playList.map(async (item) => { const title = item.title; - let desc = title + '
查看收听提示:
' + baseUrl + albumUrl + item.trackId; - if (ispaid) { - desc = title + '
[付费内容无法收听] 原文链接:
' + baseUrl + albumUrl + item.trackId; - } - const enclosure_length = item.duration; // 时间长度:单位(秒) - // itunes_duration格式:32:46 - const itunes_duration = Math.floor(enclosure_length / 3600) + ':' + Math.floor((enclosure_length % 3600) / 60) + ':' + (((enclosure_length % 3600) % 60) / 100).toFixed(2).slice(-2); + const trackId = item.trackId; + const trackUrl = item.url; + const link = baseUrl + trackUrl; + + let resultItem = {}; + const value = await ctx.cache.get(link); + if (value) { + resultItem = JSON.parse(value); + } else { + const track = await axios_ins.get(TrackInfoApi + trackId); + const track_item = track.data; + const enclosure_length = track_item.duration; // 时间长度:单位(秒) + const itunes_duration = Math.floor(enclosure_length / 3600) + ':' + Math.floor((enclosure_length % 3600) / 60) + ':' + (((enclosure_length % 3600) % 60) / 100).toFixed(2).slice(-2); + let desc = track_item.intro; + if (ispaid) { + desc = '
[付费内容无法收听]
' + track_item.intro; + } + + resultItem = { + title: title, + link: link, + description: desc, + pubDate: new Date(track_item.createdAt).toUTCString(), + itunes_item_image: track_item.coverLarge.split('&')[0], + enclosure_url: track_item.downloadUrl, + enclosure_length: enclosure_length, + enclosure_type: 'audio/aac', + itunes_duration: itunes_duration, + }; + + ctx.cache.set(link, JSON.stringify(resultItem), 24 * 60 * 60); + } - const resultItem = { - title: title, - link: baseUrl + albumUrl + item.trackId, - description: desc, - pubDate: new Date(item.createdAt).toUTCString(), - itunes_item_image: item.coverLarge, - enclosure_url: item.playPathAacv224, - enclosure_length: enclosure_length, - enclosure_type: 'audio/m4a', - itunes_duration: itunes_duration, - }; return Promise.resolve(resultItem); }) ); ctx.state.data = { title: `${album_title}`, - link: `${album_url}`, + link: `${baseUrl + albumUrl}`, description: album_desc, - image: album_cover_url, - itunes_author: album_author, + image: album_cover, + itunes_author: author, itunes_category: album_category, item: resultItems, }; diff --git a/routes/zaobao/realtime.js b/routes/zaobao/realtime.js index fc2c1c1517..b7ca8ca0a1 100644 --- a/routes/zaobao/realtime.js +++ b/routes/zaobao/realtime.js @@ -12,21 +12,25 @@ module.exports = async (ctx) => { const type = ctx.params.type || 'china'; let info = '中港台'; - let word = 'div#CN.list-sect-sub'; + let word = '/realtime/china'; + let div = 'div#CN.list-sect-sub'; if (type === '2') { info = 'singapore'; - word = 'div#SG.list-sect-sub'; + word = '/realtime/singapore'; + div = 'div#SG.list-sect-sub'; } else if (type === 'world') { info = '国际'; - word = 'div#Global.list-sect-sub'; + word = '/realtime/world'; + div = 'div#Global.list-sect-sub'; } else if (type === 'zfinance') { info = '财经'; - word = 'div#Finance.list-sect-sub'; + word = '/zfinance/realtime'; + div = 'div#Finance.list-sect-sub'; } const response = await axios_ins.get(host); const $ = cheerio.load(response.data); - const data = $('li', word).find('div'); + const data = $('li', div).find('div'); // .attr('about') const resultItems = await Promise.all( data.toArray().map(async (item) => { @@ -59,7 +63,7 @@ module.exports = async (ctx) => { .replace(/(.{2})/, '$1:'); let description = ''; $1('p', '.article-content-container').each(function() { - description = description + $(this).html() + '
'; + description = description + '

' + $(this).html() + '

'; }); resultItem = { @@ -78,7 +82,7 @@ module.exports = async (ctx) => { ctx.state.data = { title: `《联合早报》${info} 即时`, - link: host, + link: baseUrl + word, description: '《联合早报》被公认是一份素质高、负责任、报道客观、言论公正、可信度高的报纸,对中国的发展采取积极的态度,在华人世界中享有崇高的信誉。', item: resultItems, }; diff --git a/routes/zaobao/znews.js b/routes/zaobao/znews.js index fb6ac48a59..95046deb25 100644 --- a/routes/zaobao/znews.js +++ b/routes/zaobao/znews.js @@ -55,7 +55,7 @@ module.exports = async (ctx) => { const date = res.replace('发布/', '').toString(); let description = ''; $1('p', '.article-content-container').each(function() { - description = description + $(this).html() + '
'; + description = description + '

' + $(this).html() + '

'; }); resultItem = {