爬虫进阶深入目标

初级阶段:

1)给定的种子URLs,爬虫程序将所有种子URL页面爬取下来
2)爬虫程序解析爬取到的URL页面中的链接,将这些链接放入待爬取URL集合中
3)重复1、2步,直到达到指定条件才结束爬取
E.G:

import requests #用来爬取网页 
from bs4 import BeautifulSoup #用来解析网页 
seds = ["http://www.hao123.com","http://www.csdn.net",
 "http://www.cricode.com"]  #urllist                                                                          
sum = 0 #我们设定终止条件为:爬取到100000个页面
while sum < 10000 : 
if sum < len(seds): 
    r = requests.get(seds[sum]) 
    sum = sum + 1 
    do_save_action(r) 
    soup = BeautifulSoup(r.content) 
    urls = soup.find_all("href",.....) //解析网页 
    for url in urls: 
        seds.append(url) 
else: break

存在问题:

1:网页数量大,应该考虑开启多个线程(池)去一起爬取,或者用分布式架构去并发的爬取网页
2:URL都放在一个列表里,我们应该设计一个更合理的数据结构来存放这些待爬取的URL,比如队列或者优先队列。
3:对于各个网站的URL,大站好站优先原则应当予以考虑
4:每次发起请求,我们都是根据url发起请求,而这个过程中会牵涉到DNS解析,将url转换成ip地址。一个网站通常由成千上万的URL,因此,我们可以考虑将这些网站域名的IP地址进行缓存,避免每次都发起DNS请求,费时费力。
5:解析到网页中的urls后,我们没有做任何去重处理,全部放入待爬取的列表中。事实上,可能有很多链接是重复的,我们做了很多重复劳动。


解决方案

1:并行爬取:
多线程或者线程池方式,一个爬虫程序内部开启多个线程。同一台机器开启多个爬虫程序;
常见的分布式架构有:主从(Master——Slave)架构、点对点(Peer to Peer)架构,混合架构等。
分布式:

  1. 分配任务
  2. 各个爬虫之间需要通信合作,共同完成任务
  3. 不要重复爬取相同的网页
  4. 分配任务需要考虑如何进行负载均衡,比如根据网站域名进行HASH。

PS:针对分配后完任务后,失败情况(A机器挂了呢?原先指派给A机器的任务指派给谁?又或者哪天要增加几台机器,任务又该如何进行重新分配),暂时采用一致性Hash算法。

2:待爬取网页队列
如何对待待抓取队列,跟操作系统如何调度进程是类似的场景。
不同网站,重要程度不同,因此,可以设计一个优先级队列来存放待爬起的网页链接。每次抓取时,优先爬取重要的网页。
也可效仿操作系统的进程调度策略之多级反馈队列调度算法。

3:DNS缓存
避免每次都发起DNS查询,我们可以将DNS进行缓存。DNS缓存当然是设计一个hash表来存储已有的域名及其IP

4:网页去重
Bloom Filter(布隆过滤器)
建立一个大的位数组,然后用多个Hash函数对同一个url进行hash得到多个数字,然后将位数组中这些数字对应的位置为1。下次再来一个url时,同样是用多个Hash函数进行hash,得到多个数字,我们只需要判断位数组中这些数字对应的为是全为1,如果全为1,那么说明这个url已经出现过。如此,便完成了url去重的问题。有一定误差。

5:数据存储
用关系数据库存取还是用NoSQL,抑或是自己设计特定的文件格式进行存储。

6:进程间通信
可以以规定的数据格式进行数据交互,完成进程间通信

猜你喜欢

转载自blog.csdn.net/sinat_32435311/article/details/70584054