From 0466f27a43e43ad4c7f07b77a24067850febeb2f Mon Sep 17 00:00:00 2001 From: Singee Date: Fri, 24 May 2019 18:59:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20add=20algocasts.io=20=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20(#2210)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add algocasts.io 视频更新 * fix: 修复 AlgoCasts 缓存问题 * fix: AlgoCasts 默认输出全文 * feat: 补上 AlgoCasts 不抓取列表代码中忘记的返回 * fix: 删去 AlgoCasts 中多余的缓存代码 --- docs/programming.md | 8 +++ lib/router.js | 3 ++ lib/routes/algocasts/all.js | 98 +++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 lib/routes/algocasts/all.js diff --git a/docs/programming.md b/docs/programming.md index f6744470ca..8f79869164 100644 --- a/docs/programming.md +++ b/docs/programming.md @@ -4,6 +4,14 @@ pageClass: routes # 编程 +## AlgoCasts + +### 视频更新 + + + +> AlgoCasts 需要付费订阅, RSS 仅做更新提醒, 不含付费内容. + ## Dockone ### 周报 diff --git a/lib/router.js b/lib/router.js index 9365717103..5e4017e01d 100644 --- a/lib/router.js +++ b/lib/router.js @@ -1345,6 +1345,9 @@ router.get('/steamgifts/discussions/:category?', require('./routes/steamgifts/di // Steamgifts router.get('/zzz', require('./routes/zzz/index')); +// AlgoCasts +router.get('/algocasts', require('./routes/algocasts/all')); + // aqicn router.get('/aqicn/:city', require('./routes/aqicn/index')); diff --git a/lib/routes/algocasts/all.js b/lib/routes/algocasts/all.js new file mode 100644 index 0000000000..cb3fd192d0 --- /dev/null +++ b/lib/routes/algocasts/all.js @@ -0,0 +1,98 @@ +const axios = require('@/utils/axios'); +const cheerio = require('cheerio'); + +const getCacheParsed = async (ctx, key) => { + const value = await ctx.cache.get(key); + if (value) { + return JSON.parse(value); + } +}; + +const generateResponse = async (ctx, items) => ({ + // 源标题 + title: 'AlgoCasts', + // 源链接 + link: `https://www.algocasts.com`, + // 源说明 + description: `AlgoCasts 旨在用心做好每一个算法讲解视频。每个视频包含两个部分:题目的剖析讲解以及编码,力求在讲解清楚到位的基础上,尽可能地保持视频精简短小,让大家可以在碎片时间里进行学习,并收获这些算法题背后的思想与乐趣。`, + item: await Promise.all( + items.map(async (item) => ({ + // 文章标题 + title: `${item.title} | AlgoCasts 视频更新`, + // 文章正文 + description: item.description || '', + // 文章链接 + link: item.link, + })) + ), +}); + +const makeFull = async (ctx, infos) => { + const limit = 10; // 仅获取最近十条信息(避免无意义请求) + infos = infos.slice(0, limit); + + return await Promise.all( + infos.map(async (item) => { + const cacheKey = `episode-${item.episode}`; + + // 尝试从缓存查找相关数据 + let info = await getCacheParsed(ctx, cacheKey); + // console.log(info); + if (info) { + // 找到 -> 直接返回 + return info; + } else { + // 未找到 -> 返回 + info = item; + } + // 抓取详细信息 + const response = await axios({ + method: 'get', + url: info.link, + }); + const $ = cheerio.load(response.data); + + const badges = []; + $('.badge').each((index, badge) => { + badges.push($(badge).text()); + }); + + info.description = `

${info.title}

${badges.join(' | ')}
${$('#my-content p').html()}
`; + ctx.cache.set(cacheKey, info); + + // console.log(info); + + return info; + }) + ); +}; + +module.exports = async (ctx) => { + const response = await axios({ + method: 'get', + url: 'http://algocasts.io/episodes', + }); + + const $ = cheerio.load(response.data); + const infos = []; + + $('tr') + .slice(1) + .each((i, e) => { + const id = parseInt( + $(e) + .find('th') + .text() + ); + const titleLabel = $(e).find('td a'); + const title = `${id}. ${titleLabel.text()}`; + const episode = titleLabel + .attr('href') + .trim() + .split('/')[2]; + const link = `http://algocasts.io/episodes/${episode}`; + + infos.push({ id, title, episode, link }); + }); + ctx.state.data = await generateResponse(ctx, await makeFull(ctx, infos)); +};