在《Week 11:学会扒网页》我们已经介绍过,通过捷径获取网页的方式有两种,一种是通过扒网页,一种是通过 API。

上一周的内容主要介绍了「扒网页」这种方法。它的主要思路就是把一个网页还原为 HTML,随后从纯文本中匹配出我们需要的部分(比如图片链接),再把这部分内容提取出来(比如下载链接里的图片)。

扒网页的方法适应的范围很广,所以我们说它「可耻但有效」,但它也有三个明显的局限性:

  1. 必须设计复杂的匹配:我们要精确地获取网页中的信息,就要精确匹配到想要的内容,这需要对正则表达式有一定的要求不说,还需要设计大量的步骤以及试错。
  2. 必须下载整个网页:因为必须精确匹配网页内的内容,所以我们必须无差别地下载整个网页的内容。哪怕我们只想要网页里的一句话,我们也不得不把网页里的所有图片都下载下来。
  3. 无法灵活应对变化:这也是扒网页这个方法最不稳定的原因。不同的公司会根据自身的发展需求,对网页的界面的组织方式和显示方式进行调整、改版、升级等等,而我们针对某一个时间点设计的扒网页流程很容易因为这些变动而失效。

出于对这三个局限性的厌恶,我们会希望有一种更稳定、更有针对性的方法,它能够让我们:

  1. 不必设计复杂的匹配,而是像查字典一样就能获取需要的内容。
  2. 不必下载整个网页,而是仅下载自己要用的那部分内容。
  3. 不必面对变化,不管网页设计怎么变,都不影响我们获取内容的那个方式。

有这么好的方法吗?有,这种方法就是借由 API 来获取网页里的内容。

基础的 API 知识

我们先来说一下为什么通过 API 这种方法能够这么稳定和有针对性。

简单来说,这是因为开发者也想稳定和有针对性地、更有效并节省资源地完成工作。

扒网页的方法,麻烦的根源在于,它把作为形式的壳(样式排版等),和作为内容的核,都被放到了同一个载体(HTML 文件)之下。所以获取其中的内容,有时候需要一层层地剥掉内容外面的壳。所以既然我们只是要作为核的内容,那么只要为了专门摄取内容而设计一个方法就可以了,而这个方法,就是通过 API(Application Programming Interface,应用程序接口)。

在《Workflow 教程(七):征服 Workflow 中的最高峰》和《Workflow 教程(八):利用新的请求方法打造 Web 小程序》的开头部分,我分别对 API 的形式和原理进行了一定的介绍,在这就不重新写一遍了1 。但是现在重新理解捷径和 API,我发现其实小白不知道 API 的原理之类的,也不影响在捷径里使用它。实际上,我们正是通过使用而不是定义来真正理解一个东西的,特别是一个需要被实际应用的东西,定义和实操总是有差距,而熟练了实操再回去看定义往往理解得更真着。

那么我们就来看看想在捷径里使用 API 需要知道的这点儿东西。

JSON 看起来什么样?

首先,其实我们都不是很有必要知道 API 到底是什么,因为 API 可以说是一个在背后的机制,是程序员们需要考虑的,我们需要知道的是怎么用好 API 给我们提供的东西。就像去饭店,你不是特别需要知道后厨的事,你只要知道你要吃的菜应该用什么工具吃,怎么吃就行了。

那么我们和 API 接触,这个面儿上的东西,就是 JSON(JavaScript Object Notation,JavaScript 对象表示法)。先别头大,这东西你依然不需要对它知根知底。还是那句话,知道它长啥样,怎么用,就足够。

我们使用捷径时,一般用得到的 JSON 长什么样呢?一般长这样:

在捷径中直接获取的 JSON 看起来非常乱

这是这条 Tweet2  的 JSON 结果,你肯定在骂街了,心想「这xx什么破xx玩意,是不是给人看的。」

这么想的不是你一个,程序员们也都是这么想的,这种东西人肯定是不愿意看的,所以他们设计了 JSONFormatter 这样的工具,把它换了一种显示的方式:

JSONFormatter 格式化后的 JSON

这么一看,你是不是………………还是想骂街说看不懂。没关系我理解,但是你还是受累看一下,你就能发现里面有一些东西是可以看明白的,比如:

  1. 单词:看清楚里面的单词儿了,查查也都能知道是啥意思。
  2. 字典形式:每一行好像都是 "英文单词":文本链接啥的 这样的形式,像是字典一样。
  3. 组织方式:每几行都有一组花括号({})把里面这几行给包着。
  4. 缩进:花括号上面要还有一行的话,它要往前缩进一下。

看到一个 JSON 的结果,只要能看得出这 4 点,你就能把它利用好。

我们怎么用 JSON

当我们看到一个 JSON,能够下意识地看得出前面说的那几点之后,就可以按照这样的方式去利用它:

第一步,找自己想要的东西对应的单词。

比如说前面那个截图里的 JSON,是个推特视频的 JSON,那它里面肯定得有视频(Video)吧,你一看,哎发现确实有个 video\/mp43 。它下面还有个 url,你肯定和我一样会猜这个 URL 是不是就是视频的链接,Safari 粘贴并跳转一看,果然是视频!

土方法玩开心了,我们就要按规矩办事了。

第二步,通过「名称」获取「值」。

通过名称获取值,就是 JSON 的规矩。像上面截图中的例子,"bitrate":632000,冒号左边是名称,右边是值。

拿到 JSON 以后,你告诉软件(比如捷径)说,你要的是 bitrate,那捷径就会返回给你 632000。如果像截图这样,有两个 "bitrate":,那捷径就会给你返回两个值。

第三步,按层级获取。

从 JSON 获取内容要按照它的层级,层级本质上是一个名称里有多个值或者多组值,比如下面这样:

JSON 的层级

"variants": 后面是左中括号([),后面没有直接跟值,而是换行、向后缩进一下、大括号、再换行、再缩进一下,才出现了一个新的名称,后面跟了一个正常的值。当一个名称里有多组值的时候就会出现这种情况,中括号包住的是这个名称的整个值,其中花括号包住的是每一组值。而截图里也只是嵌套了一层,真实使用的情况往往会嵌套很多层。

一般来说,我们想获取的,就是图里链接这样的最底层的值,这时候我们的方法应该是按层级获取。一层一层来,首先获取 variant,才能再去获取它下面的 url 后的值。也就是说用捷径的时候,要先跟捷径说,我要获取 variant 的值,然后捷径会把后面中括号里的都给你,这时候你再说,我要 url 里的值,然后捷径在把 url 后面的链接给你。

以上就是用 JSON 的思路,但我们还没有进入到捷径中如何用 JSON 的细节,再看这一点之前,我们还要先知道一个问题,怎么获取 JSON。

从哪获取 JSON

相信看到这你们已经领会到,JSON 就是我们通过 API 这种机制,获取到的那个和网页形式(壳)分开的网页内容(核)。有了这个核,你说要视频链接它就直接给你视频链接,你说要 Tweet 原文它就给你 Tweet 原文。再也不用扒网页。

那关键问题来了,扒网页的时候我们有个特别方便的点,是我们扒的就是我们看的那个网页,链接是现成的。那么 JSON 这个东西,它既然是网上的它肯定也要有个链接,那它的链接是啥?

这个问题很关键。获取不了 JSON 那前面说的都百搭,而链接就是获取 JSON 的关键,那么这个链接从哪获得?答案是 API 文档。

每个支持 API 的服务,如果它公开了自己的 API 的话,就会在它的开发者页面公开自己的 API 文档,比如 Twitter 的 API 文档。这种 API 比较容易获得,我们只要搜索 服务名 API,一般都能查到它的文档,比如搜「Instagram API」。不过也有有不少整合这种公共 API 的站点,比如 PUBLIC APIs UI 就是其中一个:

PUBLIC APIs UI

当然,如果一个服务没有公开它的 API 文档,也可能会有人去通过一些技术手段,破解出它的 API,比如网易云音乐的 API

获取不同 JSON 的不同链接

只是知道从 API 获取 JSON 的链接显然是不够的,这就相当于说去图书馆找书一样,大方向正确但不够具体。

实际上,针对同一个服务,不同目的的 JSON 的链接很有可能完全不同。拿豆瓣来说吧:

  • 豆瓣音乐的 JSON 链接的开头是:https://api.douban.com/v2/music/
  • 豆瓣图书的 JSON 链接的开头是:https://api.douban.com/v2/book/
  • 豆瓣电影的 JSON 链接的开头是:https://api.douban.com/v2/movie/

然后,再取电影这一项来说:

  • 搜索的 JSON 链接是:https://api.douban.com/v2/movie/search?q=关键词,能搜人搜电影等
  • 查看电影详细信息的 JSON 链接是(以《教父》为例):https://api.douban.com/v2/movie/subject/1291841
  • 查看电影人详细信息等 JSON 链接是(以姜文为例):https://api.douban.com/v2/movie/celebrity/1021999

用不同的链接,获取不同的 JSON,用不同的 JSON,获取不同的内容。

不同的 JSON 的链接,主要根据查阅 API 文档来获得。但也可以通过搜索、推理等方法获得。查 API 文档的好处是了解得扎实系统,搜索推理这些方法——如果搞得定的话——好处是比较具体和直接比较快。

在捷径中应用 JSON 的思路和方法

至此,我们应该基本知道怎么用、去哪查 JSON 这个东西了。现在我们要来看看,在捷径里用 JSON,该采取的是个什么思路?

在前面我们讲 JSON 的时候,用的是倒着的方法,先看见它,再理解它,再知道它去哪查,再知道它怎么查。

那么在使用它的时候,这个思路要掉个儿。我们得:

  1. 查阅文档,找到获取所需的 JSON 的链接
  2. 根据链接获取 JSON
  3. 找到 JSON 里找自己想要的那个值对应的名称
  4. 最后按照层级,获取那个名称中的值

在捷径中,它们对应着不同的操作。

当我们已经知道 JSON 的链接,我们需要把它放在「URL」这个操作中:

操作「URL」

接下来,想要获取链接中的 JSON,我们需要使用「获取 URL 内容」这个操作:

操作「获取 URL 内容」

当我们获得了 JSON,我们需要把它放到 JSONFormatter 这样的工具中进行转化。这一步捷径没办法代劳,我们只能先把 JSON 的内容复制,再在 Safari 中打开 JSONFormatter,粘贴进去转化格式。转化完之后,去观察层级,找到自己想要的值以及其对应的名称,还有这个名称所在的层级,找到它每一个上级的名称。

最后,在捷径中,获取名称的值的操作,是「获取词典值」:

操作「获取词典值」

小结

最后再回顾一下这一节的内容,虽然我们没有具体解决任何一个问题,但是这一节的内容非常重要,所以我在标题上加了「必读」。

首先这一节的最初解释了我们有必要借助 API 这种手段来获取网页内容,它和扒网页的方法相比优势在哪。

接下来是这一节的重点,这一节的重点其实是我们处理 JSON 文件时候应该有的思维方式。

我们在捷径使用 API 的方式获取网页内容时,从始至终都应该奔着一个东西去,那就是一个可用的 JSON 文件。所以我们要知道它长什么样,而且我们整个过程就是为了看见这么个东西。

随后就是当我们看见它之后,我们怎么理解它。这里的关键是理解两个东西:一是名称:值 这个关系,二是名称的层级。我们要的是值,但要根据名称来获取值。我们要获取的名称值一般都在最底层,那么我们就要通过它之上的那些名称,一步一步到达最底层这个名称,再获取它的值。

最后我们要问,我们怎么获取这个 JSON?对于公开了 API 的服务来说,查看 API 文档是最正统的方法,当然我们也可以通过搜索、推测等方式去更有针对性地得到一些我们需要的 JSON 链接。对于技术比较到位的程序员来说,他们可以通过一些技术手段获取未公开的 API,甚至把一个没有 API 的网页给改造成带有 API 的形式。

在捷径中,我们有填写链接的操作,根据链接请求 JSON 的操作,以及获取到 JSON 之后,从 JSON 中根据名称获取值的操作。所以捷径是非常适合通过 API 这种方法来获取网页内容的。

在这一周接下来的内容里,我们会根据实例,进一步熟悉巩固这个思维方式和流程。

  • 1省的被说混字数(笑)。
  • 2Tweet 是 Twitter 里的推文。
  • 3这里面的 \/ 是斜线(Slash)和反斜线(Backslash)。其中,斜线的作用是为了分割「video」和「mp4」这两个单词,而反斜线在一些语言中,是为了表示其后的字符应被特殊处理。而反斜线后面如果是符号,一般代表这个符号就是它本身。所以这里的 video\/mp4 其实就是 video/mp4,这样看起来是不是就顺多了。