1.3 网页上的数据
互联网是最大的数据库,大大小小各种网站的网页上每天发布着海量信息,这些信息都可以作为数据。但是,如果这些数据存在网页上,通常不能直接用于数据科学项目,必须通过某种技术手段将它们保存到指定数据库或文件中。实现这种操作的技术就是“网络爬虫”。当然,如果某网站为用户提供了读取有关信息的接口,那就不需要网络爬虫,直接通过接口读取有关内容即可。但是,接口提供的信息若不能满足需要,则必须使用网络爬虫技术从网页上获取必需的数据。
基础知识
网络爬虫(Web crawler),也叫网络蜘蛛(Spider),是一种用来自动浏览网页的网络机器人,它可以将自己所访问的页面保存下来。
请读者注意,并不是所有网站都能够使用网络爬虫得到其页面内容。使用爬虫技术,务必遵守法律法规和有关道德要求。
在Python语言生态中,有很多实现网络爬虫的工具。这里演示一种比较简单、常用的第三方模块requests(官方网站:https://2.python-requests.org/en/master/),其安装方法如下:
提示:要正确、合理地使用网络爬虫技术。
下面以获取页面https://2.python-requests.org/en/master/community/support/的有关数据为例演示requests的基本应用。
图1-3-1是上述网址的页面,最终目标是要获取方框中的文档内容。
图1-3-1 用网络爬虫技术获取的内容
执行In[1]的代码,获得了所访问URL页面的全部内容,①为请求该URL,可以用In[2]中演示的方式判断该请求是否成功。
返回值为200,说明请求成功。In[1]的②得到了返回的页面中的所有信息。如果读者在浏览器中打开了①中的URL,可以查看该页面的源码(例如Firefox浏览器,按F12键即可查看,其他浏览器也有类似操作)。
②所返回的内容和图1-3-2中的网页源码内容一致。那么,如何才能得到图1-3-1方框中的文本呢?此处需要另外一个工具:
图1-3-2 网页源码
200是服务器header返回状态码。常见的还有:400(请求无效)、403(禁止访问)、404(无法找到文件)、500(内部服务器错误)等。
Beautiful Soup是一个可以从HTML或XML文件中提取数据的Python库(官方网站:https://www.crummy.com/software/BeautifulSoup/bs4/doc/)。
在使用这个工具之前,先要分析如图1-3-2所示的网页源码,找到所要的文本在源码中的位置和相关的网页标记符。以图1-3-1中的第一段Stack Overflow为例,其部分相关源码样式如图1-3-3所示。
图1-3-3 部分相关源码样式
通常网站的网页由HTML编写,HTML(超文本标记语言,HyperText Markup Language)是一种标记语言。
从如图1-3-3所示的源码可以看出,该段内容在<div id="stack-overflow" class="section">标签之内,并且以<h2>标签标示了大标题(Stack Overflow),以<p>标签标示了其下的文本说明。
以后三段内容与此类似。
根据上述规律,可以编写如下代码,以获取相应文本内容。
循环得到每个<div>中的id值。
输出内容中的“乱码”系爬虫所得内容的一部分。
In[1]的②所得到的是一个包含了所有源码的字符串,In[3]的③则是通过BeautifulSoup模块将其转化为纯粹的HTML代码,如In[4]所示——其实是bs4.BeautifulSoup类型对象。
从对源码的分析可知,所要的内容在<div>标签内,其id值分别是"stack-overflow"、"send-a-tweet"、"file-an-issue"、"e-mail"和"irc"。
函数extract_text中的⑤使用find方法依据id值查询到相应<div>标签中的文本,此文本也由HTML源码组成。再从中分别读取到标题和内容,⑥获取<h2>标签内的文本,⑦获取<p>标签内的文本。
然后用循环语句,依次向函数传入<div>标签的id值,获取相应文本内容(如⑧所示)。
为了显示更清晰,⑨使用了标准库中的pprint模块的函数。
利用In[3]代码得到的文本内容,可以保存到文件或者数据库中。
项目案例
1.项目描述
爬取“豆瓣电影”中即将上映电影的信息,网址是https://movie.douban.com/coming,具体要求如下:
●获得网页中所列出的“即将上映电影”信息。
●网页中的“片名”都是超链接对象,显示了每部电影的详细信息,要求以该超链接为入口,通过每部电影的详细信息,得知其导演、主演。
●将上述两部分数据合并为一个Pandas的DataFrame对象,并保存成本地的CSV文件。
出于网站的原因,读者阅读此内容时,要先确认该网址是否有效。网站修改URL是正常且经常发生的行为。
2.实现过程
(1)分析网页源码。
在浏览器中打开页面并显示源码,如图1-3-4所示(注意,随着时间的推移,读者访问该页面的时候,所显示的电影信息会有所差异)。单击图中①指向的选择工具,用它在页面上单击任何一个元素,就会在下半部分的源码中标记出与该元素对应的源码。反之,如果单击下面的源码,也可以在上面的网页中标记出相应的元素,如图中②所示。
图1-3-4所使用的浏览器是Firefox。
图1-3-4 <table>标签与网页内容
如此,就知道了页面中的列表内容在<table>标签内,并且每一行是一个<tr>标签,每个单元格中的内容则对应着一个<td>标签。<td>标签与网页内容如图1-3-5所示。
图1-3-5 <td>标签与网页内容
在HTML中使用<table>标签来定义表格。每个表格均有若干行(由<tr>标签定义),每行被分割为若干单元格(由<td>标签定义)。字母td指表格数据(table data),即数据单元格的内容。
用同样的方式,分析出每部电影详细信息的HTML源码结构,如图1-3-6所示。
图1-3-6 电影详细信息的HTML源码结构
(2)获取列表内容。
注意区分find_all和find。两者都返回符合条件的所有标签,find_all返回的值是列表;find直接返回结果。
从执行结果来看,应该还比较令人满意,初步达到了项目的要求,将网页上的电影信息都保存到了列表里面。
上面的代码还没有得到每部电影名称的超链接。从图1-3-5的源码中可以看出,电影名称的超链接用<a>标签标示。如果分析不同电影的超链接,会发现它们的区别在于最后的那个数字,如图1-3-7所示。
图1-3-7 不同电影的超链接的差别
可以认为,图1-3-7中不同的值是每部电影的网页在该网站的唯一标示——称为id值,因此只要得到了它,就能写出每部电影详细信息页面的URL。
依照上述思路,优化In[5]的代码。
In[6]的⑩和⑪是新增代码,⑩的功能就是得到图1-3-7中所标示的id值。
以上所得到的data是列表,可以将其转换为Pandas中的DataFrame对象,并将内容保存到CSV文件中。
(3)获取影片详情。
此处省略了显示的部分内容,请读者观察调试结果。
在前面的基础上,理解In[8]相对容易一些。⑬的参数与以往有所不同,这是因为在电影详情的页面中,对不同项目并没有设置不同的id或者class值,如图1-3-8所示。从此源码中可以看出,如果要得到导演的名称(即<span>标签中的文本)是比较麻烦的,因为多个<span>标签中的class值都相同。但是,观察发现,在相应的<span>标签中还有“rel="v:directedBy"”以区别于其他项目,于是在⑬中使用了它。⑭的解决方法类似。
图1-3-8 电影详情的页面中的源码分析
网络爬虫技术的关键在于认真分析网页源码特点。
请注意,因为网站页面可能会被开发者随时修改,当读者调试上述代码的时候,一定要对照网站源码,并根据当下的源码结构进行适当调整。
(4)保存数据。
根据项目要求,最后要合并In[7]和In[8]得到的数据,并保存到本地的CSV文件中。
⑮将前述两个DataFrame对象合并,因为两数据中都有名为“ID”的列,于是以它为合并依据(即on='ID'的含义)。
对网站而言,修改网页结构是常见的操作,因此爬虫技术鲜有一劳永逸,需要根据网站的技术调整而进行相应变化。
动手练习
(对于以下两个练习,可以二选一。)
1.利用爬虫技术,从电子商务网站上获取某类商品的用户评论信息。
2.利用爬虫技术,从电子商务网站上获取部分商品的名称、价格、已销售数量等信息。
扩展探究
1.Scrapy是一款开源的网络爬虫框架,官方网站:https://scrapy.org/。建议读者学习和应用此工具。
2.除了通用的网络爬虫工具,还有一些专门针对某网站的工具,例如https://github.com/SpiderClub/weibospider是一款针对微博网站的专用工具。