Pyspider架构01

 
一、目录结构
1.scheduler、fetch、processor三大组件
pyspider适应网页迅速改变,变动性强的网页爬虫,scheduler是用于判断哪些网页需要更新,以及各自的优先级问题的组件。
fetcher用于拉取数据,其中涉及到phantomjs的拉取,使用代理来实现,后面详细描述。
processor用于页面解析数据提取工作,这里提供如pyquery等选择器api。
可以看到,爬虫的核心组件是拉去网页的fetcher和处理网页的processor,任何爬虫框架需要先处理好这两个核心问题,然后是对于变动性强,需要重爬取的网页设计scheduler。
2.数据持久层database、result
3.交互层 webui
4.信息传导层 massage_queue
5.其他 libs
 
二、fetcher
phantomjs_fetcher是在phantomjs上运行的脚本,负责监视固定端口请求,这样就可以接受来自fetcher的phantomjs_fetcher请求。
可以看到两种不同程序、不同语言之间的交互使用这种监视端口和请求的模型,能够最大程度降低耦合。
 
1.tornado_fetcher
http请求发送和接受一般是交由外部库完成的,这里选择了tornado框架中的httpclient,这个client是异步的。
其他的类似的client还有request、gevent、还有python内置的urllib等等。
这里面两个My开头的client都是继承自tornado内部的CurlAsycnHTTPClient。
CurlAsycnHTTPClient继承自AsyncHTTPClient。
从下面tornado官方文档中对该类的描述可知,这个client是异步+回调的方式来使用,内部使用libcurl来实现。
 
Fetcher类
fetcher类大量使用了tornado提供的接口进行任务管理,注意fetcher不是httpclient这种请求器,而是作为一个全局组件,一般都使用任务-队列的模型进行管理
在fetcher类中提供了run和quit方法就是这种全局组件的任务调度方法。
run方法
在inqueue中不断取task,进行self.fetch。
fetcher类中还存在单次调用的,完成一次性任务的放入,如fetch、asyncfetch、httpfetch等等,为什么有了task和httpclient(有了参数和请求器直接请求不就好了)还要有这么多方法做什么呢?
增加的这些代码起到以下的作用:
a.在fetch方法中,增加判断是否使用异步fetch
b.在asyncfetch中,判断是否使用phantomjs,并在请求完毕之后调用callback,调用on_fetch等等
c.在httpfetch中,增加重定向判断、cookies处理,result的封装,错误处理等等
也就是说fetcher包含了 请求前的类型判断、代理、重定向、result封装、错误处理、回调函数 这些请求器不包含的处理。
 
重点
这两处请求代码都是放入tornado相关组件中进行管理的,那么重点来了,tornado起到什么管理作用?
 
按照官方解释,ioloop是底层  IO事件循环(IO多路复用) 的包装,底层可以使用epoll、kqueue甚至poll、select等等
那么什么事 IO事件循环呢?
简而言之,IO事件,比如说常见的读写socket这种事件,可以使用一个线程进行一个socket,在很多socket(并发量非常大的)时候,会使得线程爆炸,同时由于socket其实不是始终处于需要读写(CPU控制),很多时候在进行等待,使得CPU不断切换线程,效率降低。那么另外一种模型就是,最好有机制告诉CPU那个socket需要读写(CPU控制)了,然后定向读写,这样理论上只要有一个线程就可以了。
所以loop的核心api是告诉loop ,需要监听  哪个socket 的 哪个事件 如何处理。
这里官方文档展示了io_loop的核心api add_handler(socket,callback,event);
 
回到pyspider,在什么地方使用到了io_loop的特性呢?
a.httpfetch中:
TODO gen模块怎么和ioloop进行联动呢?
并不是gen模块进行联动,以下代码的关键之处不在于gen,而在于http_client.fetch()函数,这个http_client是一个异步的client,也就是说原本fetch内部需要实现callback函数的,但是这里又采用了corroutine注解,结合yield可以使得fetch能够用阻塞的方式进行书写。所以问题的本质在于http_client是如何和fetch进行联动的,这个是tornado内部的问题,不是pyspider实现的。
b.run中
 
2.phantomjs_fetcher
phantomjs不是简单的无页面浏览器,而是提供了多种接口的平台。
phantomjs通过require方法获得相应的module。
在phantomjs_fetcher里面,就使用了web_server_module,进行端口监听,使用page module请求,执行javaScript,然后封装好response返回给请求者。
 
 
 
 
三、processor
这里的processor也不是简单的一个页面解析器的概念,而是一个大的组件,接收来自于fetcher的task,调用task内封装好的处理函数(callback),并将合适的进行输出(到result),其他的有后续任务的重新放入消息队列返回scheduler之中。
这一部分引入了project的概念,也就是项目管理,例如对于过期的project进行重新爬取,update爬取时间。都放在project_module中处理。
注意,对于爬虫框架而言,页面解析工作是调用者自定义的,框架只需要调用用户定义的解析方法,框架提供的拉取和解析中的解析是指对页面元素的解析,这个已经由fetcher完成。
大型框架的设计思路是,将流程拆分成大的组件,组件之间使用队列进行连接,队列中传输的task内部封装了所有需要传递给组件进行使用或调用的数据。
用户的整个spider会被翻译成一系列的task,在组件中进行传递,最后获取到结果。
run是整体处理方法,on_task是单个处理方法,这一点和上面一样。
 
四、scheduler
在此处主要实现调度策略。
 
五、database & result_worker
result是一个大组件,将queue里面的result都通过database的handler写入数据库,而database是对原生数据库的适配器,提供统一的接口(put/get/save等等)。
 
六、webui
使用flask搭建的web。
 
 
 
 
 
 

猜你喜欢

转载自www.cnblogs.com/songdongdong6/p/9832982.html