随着前后端技术的越来越成熟,使用成熟的前端框架来实现前后端分离的项目越来越多,这就导致了如果直接使用 requests 库获取到的页面内容,可能与最终在浏览器呈现的不一致,而且没有任何数据内容。这是因为前后端分离的项目页面上的数据是通过 JavaScript 从服务器获取数据后,然后重新处理后所展示出的内容(前台渲染),而数据是通过 Ajax 方式获取的,整个过程通常都是异步完成的,因此在用户体验上非常好。
基于上述原因,想要爬取这种页面的数据,就需要学会分析网页如何通过接口向后台发送 Ajax 请求,并使用 requests 来模拟浏览器发送 Ajax 请求来获取数据。
什么是 Ajax 请求
Ajax 是一种异步的 JavaScript 请求,其中 x 表示的 XML,但现在 JSON 的使用要多于 XML。利用 Ajax 可以实现在页面不刷新的情况下与服务器进行通讯更新数据,这就避免了因为要更新页面而刷新网址的操作,体验效果更好。
Ajax 的原理
Ajax 的原理非常简单,大致包含三个步骤:
- 发送网络请求
在早先时候,window 下的 XMLHttpRequest 对象是发送 Ajax 请求的原始实现,通过获取 XMLHttpRequest 示例,并监听 onreadystatechange 事件来完成整个异步流程,而且需要考虑浏览器的兼容性,在使用过程中非常麻烦。不过后来的 JQuery 框架提供了非常简便的调用方法,还不需要考虑兼容性,这使得 Ajax 使用易用且越来越广泛。现在非常流行的 Vue 项目,则使用 axios 框架来完成 Ajax 请求。
- 服务器响应数据成功后,解析响应数据
数据解析的过程相对简单,虽然通过 Ajax 可以返回任意形式的数据,这在开发阶段一般前后端会做约定,现今较为流行的是返回 JSON 格式的标准数据,JavaScript 可以非常容易的处理这些响应的数据。
- 通过 JavaScript 更新页面内容
不管是使用原生 JavaScript DOM api 还是使用像 JQuery 这样的库,都是将接口返回的数据重新渲染到页面上,才完成了最终的目的。
如何获取 Ajax 请求
由于 Ajax 请求是在不刷新页面的情况下且异步完成的数据请求。因此我们必须借助浏览器开发工具(有多重打开方式: 快捷键 F12, 页面鼠标右键-检查等等)来获取请求链接的相关内容。这对于我们有 web 开发的经验的同学是非常熟悉的技能,在绝大多数时候需要借助此工具来调试接口。
如上述中的图片中,Ajax 发起的请求在浏览器中显示的类型是 xhr,点击后就可看到请求的各种内容,Ajax 请求响应回的数据既有 HTML 页面内容,也有 JSON 数据,在做接口响应分析时一定要关注。
同时也可以在请求头中看到X-Requested-With: XMLHttpRequest 的描述信息(这不是必有的选项)。
Ajax 响应数据处理
前边我们说过,在 Ajax 的响应数据中,返回的数据不总是 JSON 格式的,因此在做接口响应处理之前,需要对响应内容做基础的判断,防止解析方式错误导致获取到的数据不正确。不过当前流行的前后端分离项目中,以 JSON 作为响应结果的占绝大多数,因此以下以 JSON 结果为例做说明。
以 httbin 中的 json 获取为例,通过点击浏览器网络工具中标头可以获得请求相关的信息,包含请求地址 URL,请求方式 GET 等相关内容。
import requests
import pprint
res = requests.get(
'https://www.httpbin.org/json')
pprint.pprint(res.json())
# {
# "slideshow": {
# "author": "Yours Truly",
# "date": "date of publication",
# "slides": [
# {
# "title": "Wake up to WonderWidgets!",
# "type": "all"
# },
# {
# "items": [
# "Why <em>WonderWidgets</em> are great",
# "Who <em>buys</em> WonderWidgets"
# ],
# "title": "Overview",
# "type": "all"
# }
# ],
# "title": "Sample Slide Show"
# }
# }
如上边的代码示例,我们通过使用 request 访问地址,在响应结果中调用 json 方法即可获取到返回的 JSON 数据,并且自动转换为了dic类型,至此就可以轻松的获取 Ajax 响应中的数据。
在爬取Ajax 数据的时候,最重要的就是分析请求接口,包括每次请求的规律,比如每次请求参数是如何变化的,以及各种参数是如何获取和生成的,还有各种防止爬虫的策略,需要设置请求头的数据等等。