来!编写你的第一个网络爬虫
为了抓取网站,我们首先需要下载包含有感兴趣数据的网页,该过程一般称为爬取(crawling)。爬取一个网站有很多种方法,而选用哪种方法更加合适,则取决于目标网站的结构。本章中,我们首先会探讨如何安全地下载网页,然后会介绍如下3种爬取网站的常见方法:
爬取网站地图;
使用数据库ID遍历每个网页;
跟踪网页链接。
到目前为止,我们交替使用了抓取和爬取这两个术语,接下来让我们先来定义这两种方法的相似点和不同点。
1.5.1 抓取与爬取的对比
根据你所关注的信息以及站点内容和结构的不同,你可能需要进行网络抓取或是网站爬取。那么它们有什么区别呢?
网络抓取通常针对特定网站,并在这些站点上获取指定信息。网络抓取用于访问这些特定的页面,如果站点发生变化或者站点中的信息位置发生变化的话,则需要进行修改。例如,你可能想要通过网络抓取查看你喜欢的当地餐厅的每日特色菜,为了实现该目的,你需要抓取其网站中日常更新该信息的部分。
与之不同的是,网络爬取通常是以通用的方式构建的,其目标是一系列顶级域名的网站或是整个网络。爬取可以用来收集更具体的信息,不过更常见的情况是爬取网络,从许多不同的站点或页面中获取小而通用的信息,然后跟踪链接到其他页面中。
除了爬取和抓取外,我们还会在第8章中介绍网络爬虫。爬虫可以用来爬取指定的一系列网站,或是在多个站点甚至整个互联网中进行更广泛的爬取。
一般来说,我们会使用特定的术语反映我们的用例。在你开发网络爬虫时,可能会注意到它们在你想要使用的技术、库和包中的区别。在这些情况下,你对不同术语的理解,可以帮助你基于所使用的术语选择适当的包或技术(例如,是否只用于抓取?是否也适用于爬虫?)。
1.5.2 下载网页
在本书中,我们将假设你在文件中编写代码,而不是使用提示符的方式(如上述代码所示)。当你发现代码以Python提示符 >>> 或IPython提示符 In [1]:
开始时,你需要将其输入到正在使用的主文件中,或是保存文件后,在Python解释器中导入这些函数和类。
1.重试下载
如果你在任何时候不想再继续爬取,可以按下Ctrl + C或cmd + C退出Python解释器或执行的程序。
1.5.4 ID遍历爬虫
本节中,我们将利用网站结构的弱点,更加轻松地访问所有内容。下面是一些示例国家(或地区)的URL。
http://example.python-scraping.com/view/Afghanistan-1
http://example.python-scraping.com/view/Australia-2
http://example.python-scraping.com/view/Brazil-3
可以看出,这些URL只在URL路径的最后一部分有所区别,包括国家(或地区)名(作为页面别名)和ID。在URL中包含页面别名是非常普遍的做法,可以对搜索引擎优化起到帮助作用。一般情况下,Web服务器会忽略这个字符串,只使用ID来匹配数据库中的相关记录。下面我们将其移除,查看
图1.1
从图1.1中可以看出,网页依然可以加载成功,也就是说该方法是有用的。现在,我们就可以忽略页面别名,只利用数据库ID来下载所有国家(或地区)的页面了。下面是使用了该技巧的代码片段。
在这段代码中,我们对ID进行遍历,直到出现下载错误时停止,我们假设此时抓取已到达最后一个国家(或地区)的页面。不过,这种实现方式存在一个缺陷,那就是某些记录可能已被删除,数据库ID之间并不是连续的。此时,只要访问到某个间隔点,爬虫就会立即退出。下面是这段代码的改进版本,在该版本中连续发生多次下载错误后才会退出程序。
1.5.5 链接爬虫
到目前为止,我们已经利用示例网站的结构特点实现了两个简单爬虫,用于下载所有已发布的国家(或地区)页面。只要这两种技术可用,就应当使用它们进行爬取,因为这两种方法将需要下载的网页数量降至最低。不过,对于另一些网站,我们需要让爬虫表现得更像普通用户,跟踪链接,访问感兴趣的内容。
通过跟踪每个链接的方式,我们可以很容易地下载整个网站的页面。但是,这种方法可能会下载很多并不需要的网页。例如,我们想要从一个在线论坛中抓取用户账号详情页,那么此时我们只需要下载账号页,而不需要下载讨论贴的页面。本章使用的链接爬虫将使用正则表达式来确定应当下载哪些页面。下面是这段代码的初始版本。
我们查看站点可以得知索引页链接遵循如下格式:
http://example.python-scraping.com/index/1
http://example.python-scraping.com/index/2
国家(或地区)页遵循如下格式:
http://example.python-scraping.com/view/Afghanistan-1
http://example.python-scraping.com/view/Aland-Islands-2
正则表达式是从字符串中抽取信息的非常好的工具,因此我推荐每名程序员都应当“学会如何阅读和编写一些正则表达式”。即便如此,它们往往会非常脆弱,容易失效。我们将在本书后续部分介绍更先进的抽取链接和识别页面的方式。
当你运行这段代码时,会看到虽然下载了匹配的网页,但是同样的地点总是会被不断下载到。产生该行为的原因是这些地点相互之间存在链接。比如,澳大利亚链接到了南极洲,而南极洲又链接回了澳大利亚,此时爬虫就会继续将这些URL放入队列,永远不会到达队列尾部。要想避免重复爬取相同的链接,我们需要记录哪些链接已经
当运行该脚本时,它会爬取所有地点,并且能够如期停止。最终,我们得到了一个可用的链接爬虫!
高级功能
现在,让我们为链接爬虫添加一些功能,使其在爬取其他网站时更加有用。
1.解析robots.txt
2.支持代理
3.下载限速
如果我们爬取网站的速度过快,就会面临被封禁或是造成服务器过载的风险。为了降低这些风险,我们可以在两次下载之间添加一组延时,从而对爬虫限速。下面是实现了该功能的类的代码。
4.避免爬虫陷阱
目前,我们的爬虫会跟踪所有之前没有访问过的链接。但是,一些网站会动态生成页面内容,这样就会出现无限多的网页。比如,网站有一个在线日历功能,提供了可以访问下个月和下一年的链接,那么下个月的页面中同样会包含访问再下个月的链接,这样就会一直持续请求到部件设定的最大时间(可能会是很久之后的时间)。该站点可能还会在简单的分页导航中提供相同的功能,本质上是分页请求不断访问空的搜索结果页,直至达到最大页数。这种情况被称为爬虫陷阱。
想要避免陷入爬虫陷阱,一个简单的方法是记录到达当前网页经过了多少个链接,也就是深度。当到达最大深度时,爬虫就不再向队列中添加该网页中的链接了。要实现最大深度的功能,我们需要修改seen变量。该变量原先只记录访问过的网页链接,现在修改为一个字典,增加了已发现链接的深度记录。
5.最终版本
和预期一样,爬虫在下载完国家(或地区)列表的第一页之后就停止了。
1.5.6 使用requests库
本书在大部分情况下,都将使用requests库,因为它足够简单并且易于使用,而且它事实上也是大多数网络爬虫项目的标准。
作者:[德]凯瑟琳 雅姆尔(Katharine Jarmul)、[澳]理查德 劳森(Richard Lawson)
译者:李斌
畅销的Python 3网络爬虫
数据抓取采集分析
开发实战图书全新升级版,针对Python 3编写
上一版年度销量近40000册, 提供示例完整源码和实例网站搭建源码
本书是使用Python 3.6的新特性来爬取网络数据的入门指南。本书讲解了从静态网站提取数据的方法,以及如何使用数据库和文件缓存技术来节省时间并管理服务器负载,然后介绍了如何使用浏览器、爬虫和并发爬虫开发一个更为复杂的爬虫。
借助于PyQt和Selenium,你可以决定何时以及如何从依赖JavaScript的网站上爬取数据,以及更好地理解在受CAPTCHA保护的复杂网站上提交表单的方法。本书还讲解了使用Python包(比如mechanize)进行自动化处理的方法、使用Scrapy库创建基于类的爬虫的方法,以及如何在真实的网站上实施所学的爬虫技巧。
本书最后还涵盖了使用爬虫对网站进行测试、远程爬取技术、图像处理以及其他相关的主题。
本书主要内容如下:
使用简单的Python程序从页面中提取数据;
构建并发爬虫,对页面进行并行处理;
通过跟踪链接来爬取一个网站;
从HTML中提取特性;
缓存下载的HTML,以供复用;
比较并发模型,确定比较快的爬虫;
解析依赖于JavaScript的网站;
与表单和会话进行交互。
本文转载自异步社区。
原文链接:https://www.epubit.com/articleDetails?id=Nd8a0d7ac-8d62-409b-b213-4626b741572e
- 点赞
- 收藏
- 关注作者
评论(0)