爬虫应用-bloomfilter-URL去重

一 序:

  小规模的定向爬取,url管理方式比较多,:

  1.直接存库

  2.md5后存库

 或者保存到hashset都能起到类似效果,但是数据量大了之后,上面的方法就扛不住了。

二 Bloom Filter

详情参考这篇,http://www.cnblogs.com/heaad/archive/2011/01/02/1924195.html    

Bloom Filter算法如下:

    创建一个m位BitSet,先将所有位初始化为0,然后选择k个不同的哈希函数。第i个哈希函数对字符串str哈希的结果记为h(i,str),且h(i,str)的范围是0到m-1 。

下图是Bloom Filter加入字符串过程


        适用场景:BloomFilter一般适用于大数据量的对精确度要求不是100%的去重场景。

  爬虫链接的去重:大的爬虫系统有成千上万的链接需要去爬,而且需要保证爬虫链接不能循环。这样就需要链接列表的去重。把链接Hash后存放在BitSet中,然后在爬取之前判断是否存在。

  网站UV统计:一般同一个用户的多次访问是要过滤掉的,一般大型网站的UV是巨大的,这样使用BloomFilter就能较高效的实现。

demo:

package com.daojia.bloomfilter;

import java.util.BitSet;

public class BloomFilter {
	/* BitSet初始分配2^24个bit */
	private static final int DEFAULT_SIZE = 1 << 25;
	/* 不同哈希函数的种子,一般应取质数 */
	private static final int[] seeds = new int[] { 5, 7, 11, 13, 31, 37, 61 };
	private BitSet bits = new BitSet(DEFAULT_SIZE);
	/* 哈希函数对象 */
	private SimpleHash[] func = new SimpleHash[seeds.length];

	public BloomFilter() {
		for (int i = 0; i < seeds.length; i++) {
			func[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]);
		}
	}

	// 将字符串标记到bits中
	public void add(String value) {
		for (SimpleHash f : func) {
			bits.set(f.hash(value), true);
		}
	}

	// 判断字符串是否已经被bits标记
	public boolean contains(String value) 
	{
	if (value ==null) 
	{
	return false;
	}
	boolean ret =true;
	for (SimpleHash f : func) 
	{
	ret = ret && bits.get(f.hash(value));
	}
	return ret;
	}

	/* 哈希函数类 */
	public static class SimpleHash {
		private int cap;
		private int seed;

		public SimpleHash(int cap, int seed) {
			this.cap = cap;
			this.seed = seed;
		}

		// hash函数,采用简单的加权和hash
		public int hash(String value) {
			int result = 0;
			int len = value.length();
			for (int i = 0; i < len; i++) {
				result = seed * result + value.charAt(i);
			}
			return (cap - 1) & result;
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		BloomFilter f = new BloomFilter();
		f.add("http://www.baidu.com/");
		f.add("http://www.sina.com/");
		System.out.println(f.contains("http://www.baidu.com/"));
		System.out.println(f.contains("http://www.taobao.com/")); 
	}

}
输出:

true
false

三 关于分布式:

上面我们是自己基于单节点JDK的filter,我们通常的爬虫会采用分布式多节点多线程来处理的,因为毕竟目标target很多。

所以网上提出了一种改进的策略:结合Redis的BitMap就能够完美的实现这一需求。利用redis的高性能以及通过pipeline将多条bit操作命令批量提交,实现了多机BloomFilter的bit数据共享。

这块我没有去测试,实际项目中使用前应该结合数据去测试下,主要验证下存储数据占用内存及误判率大小等。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值