用python编写分布式爬虫
1、 网络连接需要持续连接(persistent connection),DNS解析的瓶颈(先查本地DNS缓存)
实现方法:基于python httplib(对http1.1完成对持续连接的支持(python的httplib完全支持http1.1),如果不是http1.1那么可以使用urlopen对其进行一次连接)并对其socket对象进行控制,关键是加入对读取DNS本地缓存(在我的机制下这个根本就不是主要问题可以暂时忽略),以及有settimeout(Igloo)(搞定,就用setdefaulttimeout())的支持(或者利用自己的DNS服务器,进行优化处理),以及对sock对象的settimeout进行设置,防止长时间的等待一个有可能连接不上的web服务器.(要测试一下连接模块和DNS解析模块在访问不存在url在默认情况下的时间消耗)对站点的ip解析出来后就直接用ip进行连接而避免了重复调用DNS解析.例子:socket.gethostbyname("www.163.com")
网络连接下载模块非常重要,需要精心反复测试,因为有可能碰到一些不规范的web服务器,如果没有加以考虑会使整个线程崩溃。
2、 多线程:机器任务的分配及站点任务的分配。
实现方法:(在某台机器上实现,在对本机内存cpu的消耗情况判断后对机器任务进行分配;在对和站点的连接情况进行判断后对站点任务进行分配)
机器任务的分配:对于机器负担的情况调整在一个机器开的线程的个数。(在关闭线程时注意要先让线程完成当前运行任务)
站点任务的分配:就是某个机器对一个站点开的线程的个数的分配。(同样是要注意关闭线程时先让其完成当前任务)
3、 对web文件树遍历过程更好的控制,对web文件树在广度优先遍历时层次的判断。(整个网络是一个图,而某个站点的模型更接近于一棵树)
实现方法:在每个地址进入队列时加一个层次号,那么要遍历第n层的话那么遍历到第一个n+1就停止读取。
4、 利用robotparser解析robots.txt
5、 单个机器spider的作用:
a) 同2多线程3文件树的遍历
b) 将获取的外部url发回*控制器,并从*控制器取回新的外部url。
6、 *控制器的作用:
a) 观察各机器的状态包括:cpu、内存、线程、站点、网络流量
b) 观察对外整体网络流量和连接状况,可以根据网络状况来调节timeout。
c) 接受各个机器发送过来的外部url并对每个url的重复数字计数。然后分配到各个机器。(分配时要用爬行策略控制器对外部url进行排序来分配,Igloo利用Page Rank,我们可以使用最简单的重复越多重要系数就越高来进行排序)
d) 分布式URL分配算法:Igloo1.2的二级哈希映射算法(集中式分配算法那个*控制器容易成为系统瓶颈)复习哈希算法,还有就是对url是否访问过的判断(Igloo使用的是URL Trie滞后合并策略)。可以使用Berkeley DB作为URL Trie的替代品。两种实现方式的比较:
i. 现在的想法:(面向站点,信息颗粒大)外部链接只是保存主机名比如:www.163.com, 站内访问用解析好的ip地址维持连接,用相对链接来得到各个页面,这样就要维护一个外部链接列表,几个站点的链接列表。优点:节省内存,对某个站点的信息获取全面,对站点的出现频率统计,排序,重要站点先取。 缺点:对链接的获取的全面性得不到保证,而且不能获取更多的重要页面,每个站点的重要页面也不会很多。
ii. 老方案:(面向页面,信息颗粒小)所有连接一视同仁。缺点:浪费资源,对单一站点的获取不一定全面。优点:可以得到全面的链接图,可以使用Page Rank对列表进行排序,页面更重要就在最前面。
7、 解析html(超级链接的提取)搞定(用python的sgmllib)缺点:速度太慢(可能会造成瓶颈,要好好包装好,以后有机会换掉它)