网页爬虫之布隆滤波原理及java实现

Posted xxniuren

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网页爬虫之布隆滤波原理及java实现相关的知识,希望对你有一定的参考价值。

前续:网页上已经有很多布隆过滤器很全的资料了,由于博主最近在做网页爬虫,遇到url防重问题,所以认真分析了布隆滤波器原理,也参考了相关博文。旨在给出不同人对其不同的理解,好给大家更全面的参考。

1、布隆过滤器原理

布隆过滤器=位图+哈希。一个空的布隆过滤器是一个m位的位图,所以位值开始均为0,定义k个不同的符合均匀随机分布的哈希函数,每个函数把集合元素映射到位图m位中的某一位。插入时,先把这个元素作为k个哈希函数的输入,拿到k组数组位置,然后把这所有的位置设置为1,。查询时,把这个元素作为k个哈希函数的输入,得到k组数组位置。这些位置只要有任意一个是0,元素肯定不会在这个集合里面。如果元素在集合里面,那么这些位置在元素插入时都被设置为1了。如果这些位置都是1,那么要么元素在集合里面,要么所有这些位置在其他元素插入时都被设置为1了,发生了“虚报”。 该过程这样理解:首先插入 “A”  “B”  “C”三个元素,可以通过散列表拿到A B C所对应的哈希码。如果 A元素对应的哈希码为 000101,位图开始是m位的全零的bits,那我把位图的最低位和从最低位开始第三位设置为1。B也是同样的道理,如果B对应的哈希码为0010,那么现在的位图为000111,如果c对应为10000,此时位图为010111,如果再来一个c,发现位图的最低位开始第五位为1,那么证明该位图中含有c元素,所以不对c元素进行存储。这里存在另一种情况,如果a对应的是001111,b对应的是000001,先进来a,然后进来b的时候发现最低位置一了,就会判断b已经存在(其实b还没存在集合中),所以就会产生漏判。但是不会出现误判现象,即a已经存在集合中,但是判断的时候说没存在集合中,这种情况不会产生。所以该布隆过滤器会存在一个漏判率。 优缺点: 优点:1、存储空间和插入/查询时间都是常数,远远超过一般的算法;             2、Hash函数相互之间没有关系,生成hash码时可以并行处理;             3、不需要存储本身值,对保密性要求高的场合有很强的实用性;             4、耗费空间减少到散列表的1/8到1/4; 缺点:1、有一定的漏判概率;             2、删除元素有困难,这个也好理解A对应的码是001111,B如果对应的码是000001,那么删除A时无法保证不误删掉和A共用最低位B对应的码。所以删除很不方便,如果要保证正确删除的话,需要做辅助变量和相应逻辑。

 布隆滤波器的误报率介绍:  给定一个布隆过滤器,m是该位数组的大小,K是hash函数的个数,n是要插入的元素个数,则误报的概率近似为:,可以看出:随着位数m的增加,假正例(false positives)的概率会下降,同时随着插入元素的个数n的增加,假正例的概率会增加,所以误报率最小的k约等于0.7*m/n。

2、java代码实现

package edu.bit.ys.spider.method;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

public class BloomFilterNew 
	
	public static final int BLOOMSIZE=2<<24;						//规定bloom的长度24bits
	public static final int[] seeds=3,5,7,11,13,31,37,61,131;			        //8个hashset函数
	private BitSet bits=new BitSet(BLOOMSIZE);						//定义一个24位长的bit 所有位初始值都是false
	
	//把字符串加到布隆滤波器中,简而言之就是把该字符串的相应hashcode映射到bits上
	public boolean add(String s)
		if(s.equals("")||(s==null))
			return false;
		
		for(int i=0;i<seeds.length;i++)
			HashCodeGen hcg=new HashCodeGen(seeds[i]);
			int codeGen=hcg.hashCodeGen(s);
			bits.set(codeGen,true);
		
		return true;		
	
	//判断该字符串是否存在
	public boolean contain(String s) throws Exception
		if(s.equals("")||(s==null))	//输入的字符串需要控制
			throw new Exception("非法输入字符串");
		
		boolean ret=true;
		for(int i=0;i<seeds.length;i++)
			HashCodeGen hcg=new HashCodeGen(seeds[i]);//生成seeds长度的对象
			ret=ret && bits.get(hcg.hashCodeGen(s));
			if(ret==false)break;
				
		return ret;
	
	
	public static void main(String[] args) 
		BloomFilterNew bfn=new BloomFilterNew();

		bfn.add("www.baidu.com");
		try 
			System.out.println(bfn.contain("www.baidu.com.cn"));
		 catch (Exception e) 
			e.printStackTrace();
		
	



class HashCodeGen
	private int seed=0;
	public HashCodeGen(int seed)
		this.seed=seed;
	
	//生成hash码
	public int hashCodeGen(String s)
		int hash=0;
		for(int i=0;i<s.length();i++)
			hash=hash*seed+s.charAt(i);
		
		return (hash & 0x7ffffff);
	

搞明白其原理,代码就相对好编写了。这里就hashCodeGen说明一下其来源:该哈希码的生成用的是BKDRhash,BKDRhash的c/c++代码如下:
unsigned int BKDRhash(char *s)

     unsigned int seed=131;//31 131 13131 131313 etc...
      unsigned int hash=0;
      while(*s)
       
            hash=hash*seed+(*str++);   
        
       return (hash & 0x7FFFFFFF);

         该哈希码生成算法用的相对很广泛,然后返回的是hash&(2^24-1)。这就是为什么在很多程序里面代码:c=2<<24; return hash & (c-1);了。这些代码是有其具体的原型。


以上是关于网页爬虫之布隆滤波原理及java实现的主要内容,如果未能解决你的问题,请参考以下文章

Java 网络爬虫获取网页源代码原理及实现

java实现网页爬虫

LC滤波电路分析,LC滤波电路原理及其时间常数的计算

五分钟小知识:布隆过滤器原理和应用分析

布隆过滤器原理及实现

布隆过滤大数据+查重过滤+爬虫领域精选算法Python,C++,Java实现源码放送