阅读文本大概需要5分钟。
随着今日头条内部代码的不断升级改版,现在网上一些爬取今日头条街拍美图的代码显然不能适用,我利用周末的时间研究了一下如何用Ajax爬取今日头条街拍美图,今天就和大家分享一下这个项目。
背 景
有时候当我们用requests抓取页面时,得到的结果可能和在浏览器中看到的不一样:在浏览器中可以看到正常显示的页面数据,但是使用requests得到的结果并没有。
这是因为requests获取的都是原始的HTML文档,而浏览器中的页面则是经过JavaScript处理数据后生成的结果,这些数据的来源有多种,可能是通过Ajax加载的,可能是包含在HTML文档中的,也可能是经过JavaScript和特定算法计算后生成的。
因此,如果遇到这样的页面,我们再用requests等库是无法获取得到有效数据的,这时需要分析网页后台接口发送的Ajax请求,如果可以用requests来模拟Ajax请求,那么就可以成功抓取了。
1.什么是Ajax
Ajax,全称为Asynchronous JavaScriptand XML,即异步的JavaScript和XML。它不是一门编程语言,而是利用JavaScript在保证页面不被刷新、页面链接不改变的情况下与服务器交换数据并更新部分网页的技术。
下面就让我们用一个实例来学习一下Ajax在数据爬取中的应用吧。
2.分析Ajax爬取今日头条街拍美图
(1)目标
这次要抓取的目标是今日头条的街拍美图,抓取完成后,将每组图片分文件夹下载到本地并保存下来。
(2)准备工作
在本项目开始之前,请确保已经安装好requests库,如果没有安装,可以用pip命令安装。
(3)抓取分析
打开今日头条的首页http://www.toutiao.com/,页面右上角有一个搜索入口,在这里输入“街拍”进行搜索,如下图所示;
打开开发者工具(F12),查看所有的网络请求。因为Ajax其实有其特殊的请求类型,它叫做xhr。在下图中,我们可以发现一个请求,其Type为xhr,这就是一个Ajax请求,用鼠标点击这个请求,就可以查看这个请求的详细信息。
然后点击右侧的Preview中的data字段展开,发现这里有许多条数据,点击第一条展开,可以发现一个title字段,它的值正好就是页面中第一条数据的标题。再检查一下其他数据,也是一一对应的,如下图所示。
data字段中的每条数据还有一个image_detail字段,它是列表形式,这其中就包含了组图的所有图片列表,我们只需要将列表中的url字段提取出来并下载下来就好了。每一组图都建立一个文件夹,文件夹的名称就为组图的标题。
(4)分析请求
切换到Headers选项卡,观察一下它的请求URL和Headers信息,如图所示。
可以看到,这是一个GET请求,请求URL的参数有offest、format、keyword、autoload、count和cur_tab。我们需要找出这些参数的规律,因为这样才可以方便地用程序构造出来。
这里观察一下后续链接的参数,发现变化的参数只有offset,其他参数都没有变化,而且第二次请求的offset值为20,第三次为40,第四次为60,所以可以发现规律,这个offset值就是偏移量,进而可以推断出count参数就是一次性获取的数据条数。因此,我们可以用offset参数来控制数据分页。
(5)代码实现
首先,定义方法get_page()来加载单个Ajax请求的结果。其中唯一变化的参数就是offset,所以我们将它当作参数传递,代码如下:
然后,在定义一个解析方法:提取每条数据的image_detail字段中的每一张图片链接,将图片链接和图片所属的标题一并返回,此时可以构造一个生成器,代码如下:
接着,定义一个方法保存图片。该方法中,要根据item的title来创建文件夹,然后请求这个图片的链接,获取图片的二进制数据,以二进制的形式写入文件。代码如下:
最后,只需要构造一个offset数组,遍历offset,提取图片链接,并将其下载即可,代码如下:
(6)结果展示
整个程序运行之后,可以发现街拍美图都分文件夹保存了下来,如图所示。
3.总 结
通过这个项目,我们可以了解Ajax分析的流程、Ajax分页的模拟以及图片的下载过程。按照web发展趋势来看,网页的原始HTML文档不会包含任何数据,数据都是通过Ajax统一加载而后再呈现出来的,所以我们需要熟练掌握Ajax数据爬取。后台回复「街拍」便可以获得项目的源码。