爬虫技术之——bloom filter(含java代码)

  在爬虫系统中,在内存中维护着两个关于URL的队列,ToDo队列和Visited队列,ToDo队列存放的是爬虫从已经爬取的网页中解析出来的即将爬取的URL,但是网页是互联的,很可能解析出来的URL是已经爬取到的,因此需要VIsited队列来存放已经爬取过的URL。当爬虫从ToDo队列中取出一个URL的时候,先和Visited队列中的URL进行对比,确认此URL没有被爬取后就可以下载分析来。否则舍弃此URL,从Todo队列取出下一个URL继续工作。

  然后,我们知道爬虫在爬取网页时,网页的量是比较大的,直接将所有的URL直接放入Visited队列是很浪费空间的。因此引入bloom filter!

  我们把bloom filer设置为m个bit,全部初始为0。

  对每一个URL,进行K(K<m)次相互独立的哈希,一共得到K个值,将这K个值在bloom filter中对应的bit位置1。

  经过上述处理的bloom filter实际上构成了我们所说的Visited队列,当我们从ToDo队列中取出一个新的URL时,同样,进行相同的K次哈希,每进行一次哈希,查看bloom filter中对应位,只要发现某位是0,就可以确定这个URL是没有处理过的,可以继续下载处理。

  那么,原理清楚之后,还有几个问题没有解决。

  1、bloom filter是有可能发生错误的,因为不处理碰撞,也就是说,有可能把不属于这个集合的元素误认为属于这个集合

  错误率的计算:

  在n个URL都进行k次散列加入之后,bloomfilter中某位是0的概率

    

  错误率(即一个新的URL恰好k次散列的值对应的位都已经是1的概率)

   

  2、哈希函数个数K的确定

  k = ln2· (m/n)时(具体数学分析见http://blog.csdn.net/jiaomeng/article/details/1495500)

  3、bloomfilter位数M的确定

  我们可以想到,M的大小越大,错误率就会越小,但是数学证明给出了一个下界。即M = logN = 1.44N。

  附上java代码

复制代码
 1 /**屈永泉 布隆过滤器 快速确定哪些网页已经被下载过*/
 2 
 3 package crawler;
 4 
 5 import java.util.BitSet;
 6 
 7 public class BloomFilter {
 8     private int defaultSize = 5000 << 10000;
 9     private int basic = defaultSize - 1;
10     private BitSet bits = new BitSet(defaultSize);
11 
12     private int[] lrandom(String key) { // 产生八个随机数并返回
13         int[] randomsum = new int[8];
14         for (int i = 0; i < 8; i++)
15             randomsum[0] = hashCode(key, i + 1);
16         return randomsum;
17     }
18    
19     // 将一个URL加入
20     public synchronized void add(String key) {
21         int keyCode[] = lrandom(key);
22         for (int i = 0; i < 8; i++)
23             bits.set(keyCode[i]); // 将指定索引处的位设置为 true
24         }
25     }
26 
27     // 判断一个URL是否存在
28     public boolean exist(String key) {
29         int keyCode[] = lrandom(key);
30         if (bits.get(keyCode[0])
31                 && bits.get(keyCode[1]) // 返回指定索引处的位值。
32                 && bits.get(keyCode[2]) && bits.get(keyCode[3])
33                 && bits.get(keyCode[4]) && bits.get(keyCode[5])
34                 && bits.get(keyCode[6]) && bits.get(keyCode[7])) {
35             return true;
36         }
37         return false;
38     }
39 
40 
41     private int hashCode(String key, int Q) {
42         int h = 0;
43         int off = 0;
44         char val[] = key.toCharArray(); // 将此URl转换为一个新的字符数组
45         int len = key.length();
46         for (int i = 0; i < len; i++) {
47             h = (30 + Q) * h + val[off++];
48         }
49         return basic & h;
50     }
51 
52     
53      /* public static void main(String[] args) { // TODO Auto-generated method
54       long pre = 0;
55       long post = 0;
56       pre = System.nanoTime();
57           BloomFilter f = new BloomFilter(); //初始化
58       f.add("http://www.agrilink.cn/"); f.add("http://www.baidu.com/");
59       System.out.println(f.exist("http://www.baidu.com/"));
60       System.out.println(f.exist("http://www.baidud.com/"));
61       post = System.nanoTime();
62       System.out.println("Time: " + (post - pre));
63       
64       }
65      */
66 
67 }
复制代码
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值