用 Deno 编写一个简单的 REST API
754
2022-05-30
有人的地方就有江湖,有江湖的地方就有争论。前些天,继《[译]为什么如今 Deno 正全面取代 Node.js》之后,又有了《【译】Deno 已经死了吗?》,也许这便是江湖。说回标题”Deno 在手,天下我有“,其实 Deno 换成Charj、NodeJS、Java 等其他名词都一样,毕竟只是标题罢了,可能真正不一样的是使用她的愉悦感。对我而言,能给我带来 Copy 的快感,便是极好的!
源起
本周,被@justjavac 巨佬的各个热搜榜项目吸睛了,抱着对技术的三分钟热情以及对优秀代码的学习心切,我又开始了新的代码拷贝旅程。二话不说,先git clone一顿操作猛如虎,定睛一看,好像这几个项目的实现都差不多,也请教了巨佬本尊确定实现是一样的,但为毛要开 4 个 repo 呢?也许这就是单一职责原则吧。然后,我寻思着能不能整合一下再加点别的热搜榜就能变成trending in one,是不是很棒的想法,哈哈哈哈。接下来,我还会对今日头条下手--”得热搜者得天下,热搜榜拿来吧!“,三下除二拿到了头条热搜榜(尽管需要输入图片验证码)。最后就是资源整合,不过发现 README.md 爆了,看来单例还是有单例的好。
即刻获取今日热搜榜 ➡️ trending-in-one
剖析
其实抛开语言和平台,要想实现热搜汇总榜,无非就是三步走:① 获取数据 ② 处理数据 ③ 输出数据。接下来从 Deno 的视角来详细解说这三步是如何走的:
获取数据
当我们遇到一个需求,可能要从它的本质出发,比如要实现热搜汇总,首先我们就需要各大平台的热搜数据,如今日头条热搜榜、知乎热门视频、知乎热门话题、知识热门搜索、微博热门搜索等等,怎么获取呢?常规的手段就是框按 F12 看看 Network,实在不行试试抓包工具.好在“前人栽树后人乘凉”,于是乎我们便有了各平台的接口,获取数据岂不是信手沾来。
头条热榜:https://is-lq.snssdk.com/api/suggest_words/?business_id=10016
微博热搜:https://s.weibo.com/top/summary
知乎热门话题:https://www.zhihu.com/api/v3/feed/topstory/hot-lists/total?limit=100
知乎热门视频:https://www.zhihu.com/api/v3/feed/topstory/hot-lists/zvideo?limit=100
知乎热搜: https://www.zhihu.com/api/v4/search/top_search
当然以上接口并非永久有效,目前来看也只能是能用多久用多久了,如果您不满足于此,亦可以试试Twitter、Medium 等等(PS:好人一生平安)。不过,上边的接口中,微博热搜特立独行,她返回的是 HTML 需要用到正则匹配即可拿到热搜标题和链接,正则可把我难住了:/(.+)<\/a>/g,似懂非懂。各位少侠可否移步评论区多多指教?
以今日头条为例,获取数据似乎显示特别简单,但扪心自问 await、fetch、TypeScript 我又了解多少呢?
"https://is-lq.snssdk.com/api/suggest_words/?business_id=10016",
console.error(response.statusText);
const result: ToutiaoTopSearch = await response.json();
const words = result.data[0].words;
最终我们的数据可能是这样的--参见2020-12-01 头条热搜
export function createTuotiaoList(words: ToutiaoWord[]): string {
words.map((x) => `1. [${x.word}](${x.url})`)
export async function createReadme4Toutiao(
const readme = await Deno.readTextFile("./README.md");
另外再对比新旧数据的时候,用到了常用的数组迭代方法及**Object.entries()** ,感觉 MDN 还得多刷,完全不熟练,尤其是串起来的时候:
export function mergeWords4Toutiao(
for (const w of words.concat(another)) {
return Object.entries(obj).map(([url, word]) => ({
其实在处理数据的时候,我们基本完成了数据输出的准备工作,鉴于本项目中只输出为.md 文件和.json 文件,直接调用之前的处理数据方法即可,简单粗暴:
export async function toutiaoSearch() {
await Deno.writeTextFile(fullPath, JSON.stringify(wordsAll));
const readme = await createReadme4Toutiao(wordsAll);
await Deno.writeTextFile("./README.md", readme);
const archiveText = createArchive4Toutiao(wordsAll, yyyyMMdd);
const archivePath = join("archives/toutiao-search", `${yyyyMMdd}.md`);
await Deno.writeTextFile(archivePath, archiveText);