diff --git a/docs/multimedia.md b/docs/multimedia.md index 58d699c72d..9a8b2833b4 100644 --- a/docs/multimedia.md +++ b/docs/multimedia.md @@ -4,6 +4,12 @@ pageClass: routes # 音视频 +## 60-Second Science - Scientific American + +### Transcript + + + ## 99% Invisible ### Transcript diff --git a/docs/new-media.md b/docs/new-media.md index a9321d41a9..e43896dce2 100644 --- a/docs/new-media.md +++ b/docs/new-media.md @@ -27,6 +27,20 @@ pageClass: routes +## AEON + + + +支持以文体分类: +| Ideas | Essays | Videos | +| ----- | ------ | ------ | +| ideas | essays | videos | + +同样支持以话题分类: +| Culture | Philosophy | Psychology | Society | Science | +| ------- | ---------- | ---------- | ------- | ------- | +| culture | philosophy | psychology | society | science | + ## BOF ### 首页 diff --git a/lib/router.js b/lib/router.js index 9a97aa0e01..95f5d526f4 100644 --- a/lib/router.js +++ b/lib/router.js @@ -782,6 +782,9 @@ router.get('/laosiji/hot', require('./routes/laosiji/hot')); router.get('/laosiji/feed', require('./routes/laosiji/feed')); router.get('/laosiji/hotshow/:id', require('./routes/laosiji/hotshow')); +// Scientific American 60-Second Science +router.get('/60s-science/transcript', require('./routes/60s-science/transcript')); + // 99% Invisible router.get('/99percentinvisible/transcript', require('./routes/99percentinvisible/transcript')); @@ -1422,6 +1425,9 @@ router.get('/ningmeng/song', require('./routes/ningmeng/song')); // 紫竹张 router.get('/zzz', require('./routes/zzz/index')); +// AEON +router.get('/aeon/:cid', require('./routes/aeon/category')); + // AlgoCasts router.get('/algocasts', require('./routes/algocasts/all')); diff --git a/lib/routes/60s-science/transcript.js b/lib/routes/60s-science/transcript.js new file mode 100644 index 0000000000..13e2d90a99 --- /dev/null +++ b/lib/routes/60s-science/transcript.js @@ -0,0 +1,48 @@ +const cheerio = require('cheerio'); +const got = require('@/utils/got'); + +module.exports = async (ctx) => { + const url = `https://www.scientificamerican.com/podcast/60-second-science/`; + + const res = await got.get(url); + const $ = cheerio.load(res.data); + const list = $('.underlined_text.t_small').get(); + + const out = await Promise.all( + list.map(async (item) => { + const $ = cheerio.load(item); + const title = $(item).attr('aria-label'); + const address = $(item).attr('href'); + const cache = await ctx.cache.get(address); + if (cache) { + return Promise.resolve(JSON.parse(cache)); + } + const res = await got.get(address); + const capture = cheerio.load(res.data); + + const tStr = '.article-header__divider > ul > li > span:nth-child(2)'; + const time = capture(tStr).text(); + const aStr = '.article-header__divider > ul > li > span:nth-child(1) > span'; + const author = capture(aStr).text(); + + capture('.transcript__close').remove(); + const intro = capture('.article-media__object').html() + '

'; + const contents = intro + capture('.transcript__inner').html(); + const single = { + title, + description: contents, + link: address, + guid: address, + author: author, + pubDate: new Date(time).toUTCString(), + }; + ctx.cache.set(address, JSON.stringify(single)); + return Promise.resolve(single); + }) + ); + ctx.state.data = { + title: 'Transcripts of SA 60-Second Science', + link: url, + item: out, + }; +}; diff --git a/lib/routes/aeon/category.js b/lib/routes/aeon/category.js new file mode 100644 index 0000000000..7afb8c32c5 --- /dev/null +++ b/lib/routes/aeon/category.js @@ -0,0 +1,86 @@ +const cheerio = require('cheerio'); +const got = require('@/utils/got'); + +module.exports = async (ctx) => { + const url = `https://aeon.co/${ctx.params.cid}`; + + const res = await got.get(url); + const $ = cheerio.load(res.data); + const list = $('.article-card').get(); + + const out = await Promise.all( + list.map(async (item) => { + const $ = cheerio.load(item); + const title = $('.article-card__title').text(); + const partial = $('.article-card__title').attr('href'); + const address = `https://aeon.co${partial}`; + const author = $('.article-card__authors__inner').text(); + + const cache = await ctx.cache.get(address); + if (cache) { + return Promise.resolve(JSON.parse(cache)); + } + + const res = await got.get(address); + const capture = cheerio.load(res.data); + const time = capture('.article__date.published').text(); + + capture('div.newsletter-signup').remove(); + capture('div.pullquote').remove(); + capture('div.article__related').remove(); + capture('div.article__shares').remove(); + + let bio; + const authorInfo = '.article__body__author-details > p:nth-child(2)'; + if (capture(authorInfo).html() !== null) { + bio = + `





` + + author.trim() + + ' ' + + capture(authorInfo) + .html() + .trim() + + `


`; + capture('.article__inline-sidebar').remove(); + } else { + bio = ''; + } + + let banner; + if (capture('.article-card__image-wrap').html() !== null) { + const imgSty = capture('figure.responsive-image').attr('style'); + const imgLink = imgSty.match(/url\(["']?([^"']*)["']?\)/)[1]; + banner = ``; + } + if (capture('.article__image__wrapper').html() !== null) { + banner = ''; + capture('img').each((index, item) => { + item = $(item); + item.removeAttr('alt'); + }); + capture('.display-article').remove; + } + if (capture('.video__embed').html() !== null) { + banner = capture('div.video__embed').html(); + capture('.article__header__subtitle').remove(); + } + + const contents = banner + capture('.article__body__content').html() + bio; + const single = { + title, + author: author, + pubDate: new Date(time).toUTCString(), + description: contents, + link: address, + guid: address, + }; + ctx.cache.set(address, JSON.stringify(single)); + return Promise.resolve(single); + }) + ); + ctx.state.data = { + title: $('title').text(), + link: url, + item: out, + }; +};