最初下载小说的爬虫只有二十几行代码,虽然二十几行代码就可以完成这项工作,但是如果把爬虫的各个功能封装成不同的类,这样便于以后复用也便于阅读。
拓展之后,把刚开始下载小说的代码拓展成一个基础爬虫,但是这还不够,便就有了这篇关于分布式爬虫的文章,同样也是下载小说,不过这次分离地更明确。
这篇文章实现的是主从模式的分布式爬虫
主从模式的分布式爬虫主要分为两部分:
- 控制节点
- 爬虫节点
控制节点用来分发任务以及数据存储,爬虫节点用来接收任务并返回结果集合。
工作模式如图所示:
控制节点
对于传进来的一个初始URL,先把它加入URL管理器
url_manager = UrlManager()
url_manager.add_new_url(root_url)
再从URL管理器中取出一个URL把它加入到URL队列:
new_url = url_manager.get_new_url()
url_q.put(new_url)
从返回的结果队列取出想要的URL存入URL管理器
content = result_q.get(True)
if content['new_urls'] == 'end':
print('小说已下载完毕,可以停止了')
store_q.put('end') conn_q.put(content['new_urls'])
从返回的结果队列取出想要的数据再存入文件
text = store_q.get()
chaptername = text['chaptername']
html_context = text['html_context']
if chaptername == 'end' and html_context == 'end':
print('小说已下载完毕,可以停止了')
return
output.store(chaptername, html_context, file_object)
这基本上就是控制节点所要做的事情了,不要想那么复杂。
几个问题
- URL队列怎么获取的数据?
- URL队列起了一个什么样的角色?
URL队列从URL管理器获取URL,URL管理器其实就是一个列表,每次Pop一个URL出来给URL队列。(完全可以通过URL管理器来进行爬取工作)
URL队列其实就充当了一个中转的角色,因为URL管理器是一个列表,我们没法把它暴露在网络上,只能通过URL队列来实现。
为什么通过URL队列来实现?
很简单,因为队列能暴露在网络上,因此从其它地方我们可以获取这个URL队列。
爬虫节点
首先要弄明白爬虫节点要干什么
- 从URL队列获取URL
- 通过URL获取HTML文档
- 解析HTML文档获取新的URL以及想要的文本
- 把URL以及文本传进结果队列
这就是爬虫节点所做的工作
如何获取URL队列
控制节点已经帮我们创造了URL队列,并把它暴露在了网络上,我们只需要根据响应的地址以及端口接入就可以获取URL队列了。URL队列只有一个,对于控制节点和爬虫节点来说它们共用一个URL队列,很明显结果队列也只有一个,控制节点和爬虫节点共用一个结果队列。
BaseManager.register('get_task_queue')
BaseManager.register('get_result_queue')
server_addr = '127.0.0.1'
self.m = BaseManager(address=(server_addr, 8010), authkey=b'xuezhong')
self.m.connect()
self.task = self.m.get_task_queue()
self.result = self.m.get_result_queue()
然后就是很正常的通过拿到URL来获取HTML文档
url = self.task.get()
html_text = self.download.download(url)
最后就是分析HTML文档,构造结果集,并传入结果队列:
new_urls, chaptername, html_context = self.parser.parser_context(url, html_text)
self.result.put({'new_urls': new_urls, 'text': {'chaptername': chaptername, 'html_context': html_context}})
这样一个主从模式的分布式爬虫就完成了,其实就是通过队列可以在网络上暴露的功能,把爬虫分离的更彻底一点。
基础爬虫的特点
- HTML下载器,HTML解析器,数据下载器,URL管理器,各司其职,分工明确
主从模式的分布式爬虫特点
- 控制节点就是用来分发任务和处理数据
- 爬虫节点就是用来接受任务返回数据
从这来看,主从模式的分布式爬虫分离地更彻底一点。
如何运行?
先运行控制节点,等到有URL加入到URL队列时,启动爬虫节点即可
运行爬虫节点
对应地控制节点输出为
核心
URL队列和结果队列其实只有一个,因为在主从模式中我们只用到了一个控制节点+一个爬虫节点,千万不要想多,我刚开始就是因为想太多,而搞不清其原理。
参考文献:
[1]范传辉. Python爬虫开发与项目实战. 实战项目:简单分布式爬虫, 2017
[2]分布式进程