[翻译]Web Scraping 201: finding the API

前言:之前,在帮同学获取百度城市百科内容时,每个城市页面下的内容是通过 js 动态生成的(Ajax?),不能直接通过爬取页面解析得到。最终通过浏览器查看网络请求,找到了请求地址和具体参数含义。整理收藏夹的时候,发现有这么一篇文章,鉴于Blog 已经长草,决定翻译一下留做以后备查吧。

有很多网站的 API 确实可以通过这样的方式获得,但是另一些网站(如 twitter、weibo),它们的 API 是有很多的限制,并且需要进行申请的。相比之下,如果能查到 API 的开发文档,则应当以开发文档为主。当然,本文通过审查工具来分析页面的加载流程,进而找到一些需要的内容还是很有必要的。

源地址:http://www.gregreda.com/2015/02/15/web-scraping-finding-the-api/

前一篇文章中,我解释了如何爬取一个页面,不过那里的情况是:页面由服务端生成。然而,随着 Javascript 框架例如AngularJS 配合 RESTful APIs 的流行,更多的页面开始由服务端转向客户端。

这篇文章中,将简要的阐明这两者的不同,然后展示如何找到其背后的 API,允许你自己获得想要的数据。

服务端生成 vs 客户端生成

假如,我们有一项运动的统计数据,并且打算基于此构建一个 web 应用,例如basketball-reference

如果我们使用一个服务端架构例如 Django,当用户访问页面的时候将会发生如下的事情:

  1. 用户浏览器发送请求到应用的服务器
  2. 我们的服务器处理请求,验证 URL 的正确性等
  3. 如果 URL 不存在,返回错误,并重定向到404页面
  4. 如果页面存在,运行服务端程序来获取数据库中的数据
  5. Django 代码将获得的数据插入到应用的模板中,生成最终的 HTML 页面
  6. 最终,服务器返货 HTML 页面给用户的浏览器

为了阐明最后的一步,go to John Wall’s game log and view the page source. Ctrl+f 或者 Cmd+f 搜索 “2014-10-29”。这是表格的第一行。我们可以知道页面是由服务端生成的,因为数据在页面源代码中可以看到。

然而,如果一个web 应用有客户端框架如 Angular 构建,处理的过程会有一些不同。这种情况下,服务器仍然发送静态的文本(HTML、CSS、Javascript),但是 HTML 只是一个模板,它并没有任何数据。Javascript 脚本来从 API 获取数据,然后在客户端创建页面。

我们可以看John Wall’s shot log 的页面,里面没有任何数据!(注:北邮人论坛就是这样。。。)你在页面的源代码里也照不到任何的表格信息。

如果你想,糟了,我没法爬这个数据了。你很幸运,相比直接爬取页面,通过 API 通常更容易来获取数据——你只需要直到如何找到 API 即可。这就是这篇文章接下来要做的事。

寻找 API

一个客户端的应用,浏览器将会做很多的工作。因为浏览器是来解释 HTML 的,我们可以使用它内置的开发者工具(Chrome 中为右键->审查元素,Firefox 可以使用 Firebug)来看看数据是从哪里来的。我们选择 Network 标签。

To open Chrome’s Developer Tools, go to View -> Developer -> Developer Tools. In Firefox, it’s Tools -> Web Developer -> Toggle Tools. We’ll be using the Network tab, so click on that one. It should be empty.

打开你想要爬取的页面,本文的例子为 John Wall’s shot logs,如果你已经打开,刷新一次就好。你的 Network 标签页应该会像下面这样

network tab example

接下来,点击 XHR 过滤器。XHR 是 XMLHttpRequest 的缩写,这种一种用来获取 XML 或者 JSON 数据的请求。在这里可以看到一些请求,其中会有返回你想要数据的 API 请求

XHR requests example

这里,你需要认真的分析,那个请求才是你想要找到的。这次的例子,以 “playerdashptshotlog” 开头的请求似乎很可能。点击它,在 Preview 标签页查看,如下图

API response preview

哈哈,这就是我们要找的 API 了,我们可以仔细看看这个响应的内容。

API results preview

你能看到一系列的内容:

  1. 资源的名字——playerdashptshotlog.
  2. 参数(你可能需要点开 resource 部分)。这里包含传递给 API 的请求参数,你可以认为是 SQL 语句中的 WHERE 部分。这个请求的参数是Season=2014-15PlayerID=202322。改变参数会获得不同的数据。
  3. 返回的结果集
  4. 在结果中,可以找到列名和行集。

现在,回到 Headers 标签页,复制请求的 URL,在新的浏览器中打开,我们将会看到返回的数据,它们是 JSON 格式的

API response

下面是 Python 的代码来实现请求

不同的 API 会返回不同的类型的数据,一些可能返回 XML,另一些可能是 JSON。一些可能会在数组中存储数组,另一些则可能在数组中存储 map 或者 dict。

发表评论

电子邮件地址不会被公开。 必填项已用*标注