前面我们讲了《大规模异步新闻爬虫的实现思路》,在文章最后提到了把它升级为分布式的思路。今天,我们就来详细实现一下,把它真正升级为分布式的大规模异步爬虫。
一、架构
我们设计的这个分布式是典型的CS架构,也就是分为服务器端和客户端。服务器端我们称为“爬虫Server”,客户端称为“爬虫Client”。
爬虫Server,负责管理所有URL(即,爬虫客户端的下载任务)的状态,通过我们前面介绍的UrlPool(网址池)进行管理。还不知道UrlPool的同学可以搜索我们前面的文章,或者到《猿人学网站》上去看“Python爬虫教程”找到UrlPool的讲解。Server提供接口给Clients,以便它们获取URL和提交URL。
爬虫Client,负责URL的下载、网页的解析以及存储等各种。Client通过接口向Server请求需要被下载的URL,下载完成后向Server报告URL是否下载成功,同时把从网页中提取到的URLs提交给Server,Server把它们放入URLPool。
Server和Client的分工明确,由它们组成的分布式爬虫的架构就是这样子的:
我们把这个分布式爬虫叫做“bee”(小蜜蜂),寓意一群蜜蜂去采蜜。分别创建Server和Client的文件:
bee_server.py
bee_client.py
二、爬虫Server端实现
爬虫Server端需要建立一个服务,它可以是TCP的,也可以是HTTP的。这里,我们选择Python的异步web框架:Sanic 来写这个服务。这个服务很简单,代码如下:
上面是web服务的实现代码,通过
@app.listener(‘after_server_stop’)
在Server退出前,缓存URLPool里面的url。
整个web服务就实现了一个接口:/task, 通过GET方法让client获取URLs,通过POST让client提交URLs。
后面再加上执行程序:
三、爬虫Client的实现
我们把Client写成一个类,这个类一部分接口是与Server交互用的,也就是从Server那里获取要下载的URL,以及向Server提交新得到的URLs。另外一部分接口是与互联网交互的,即下载URLs。
通过异步IO,我们可以把Client的并发提高上去,达到更高的抓取速度。
先来看看这个类的初始化:
其中,self._workers 记录当前正在下载的协程(即,并发数);
sellf.workers_max 是限制最大并发数,根据自己的CPU性能和网络带宽调整其大小,从而达到最大效率利用硬件资源。
download()方法是对aiohttp的封装,方便异步下载。
下面是与Server服务进行交互的两个方法:
下面是下载任务相关的方法。其中save_html()根据自己需要可以把下载的网页保存到数据库;filter_good()清洗提取到的URLs,把不需要下载的URLs扔掉。process()是个协程定义,它的工作就是下载、提取、保存、提交,这个协程会在抓取循环中被不断的创建,达到并发的目的。
最后,我们定义两个循环,一个用于定时向Server请求要下载的URLs,另一个用于调度下载任务处理协程。通过self._workers这个计数器限制协程数量。start()方法就是整个类的执行入口。
最后的最后,我们需要执行Client:
四、运行和部署
运行过程很简单,先运行Server程序:bee_server.py
再运行Client程序: bee_client.py
部署的话,可以单机也可以多机。
如果你的服务器很强,多核的,单机可能就满足你的下载量的需求了。首先运行一个Server,剩下client的运行数量根据核数来定。单核大约占50%的CPU,自己多跑跑看。
如果你的下载量很大,比如实时抓取几千家新闻网站,那么可以多台、多核进行部署。这时候,记得改一下Server监听的host为0.0.0.0,以便其它机器能访问它。
这就是一个分布式的爬虫,道理很简单,实现也不复杂。由于UrlPool的支持,你的Server可以随时停掉重启,然后继续无重复下载。在这套代码上面,修改部分接口,就可以实现你自己的抓取目的。
老规矩,猿人学Python公众号后台回复“bee”获取相关代码。
———————————–
广而告之,最近我在教爬虫
一对一教学Python爬虫;
学会如何设计抓取海量数据的爬虫;
学会如何分析/反反爬策略;
学完自己能真实动手开发那种;
在猿人学Python公众号菜单栏-联系我,找到我的微信。
爬虫文章拓展阅读:

我的公众号:猿人学 Python 上会分享更多心得体会,敬请关注。
***版权申明:若没有特殊说明,文章皆是猿人学 yuanrenxue.con 原创,没有猿人学授权,请勿以任何形式转载。***
您好,server程序运行在自己电脑上,client程序在自己买的云服务器上,这样理解对吗?