1.bloom filter算法

传说中,larbin使用bloom filter算法来进行url去重。那我们就先来了解下bloom filter算法好了。

【以下转自:http://hi.baidu.com/fengfengchang/item/050b11390ff61fbd633affac】

先解释一下什么是哈希函数。哈希函数简单来说就是一种映射,它可取值的范围(定义域)通常很大,但值域相对较小。哈希函数所作的工作就是将一个很大定义域内的值映射到一个相对较小的值域内。

传统的哈希存储

假设要哈希的集合为S,它有n个元素。传统的哈希方法是,将哈希区域组织成h(h > n)个格子的列表,每一个格子都能存储S中的一个元素。存储时将S中的每一个元素映射到{0, 1, … , h-1}的范围内,然后以这个值为索引将此元素存储到对应的格子内。由于哈希函数将一个大集合映射到一个小集合中,所以存在将大集合中的多个元素映射到同 一位置的情况,这就是所谓的碰撞(Collision)。当碰撞发生时,有多种策略可供选择,比如用链表将映射到同一位置的元素串起来,或者在碰撞发生时 再进行哈希映射直到找到空位为止等等。

传统的哈希方法不会发生错误,而且存储的元素还可以复原。如果哈希 函数选择得当,碰撞出现的情况比较少,那么查找某一个元素也很快。但是,如果你哈希某个集合只是为了判断某个元素是否在这个集合中,那么你会发现好像存储 整个集合有点浪费。按传统的哈希方法判断某个元素是否属于集合时,会把这个元素和它映射位置上的元素进行匹配,如果完全匹配则说明属于集合,如果不匹配则 不属于。在绝大部分查找都不能匹配的情况下(这常常是实际中的情况),我们会发现匹配的过程经常用不到整个元素,因为元素的一部分就可以判断不匹配了。基 于“部分信息就能判断不匹配”这个思路,Burton Bloom(Bloom Filter的发明者)提出了一种改进的方法。

改进的哈希存储

在这种改进的方法中,哈希区域和前面一样仍然被组织成格子的列表。但这次并不直接将集合元素存在格子里,而是将每一个元素编码然后将编码存在格子里。假设每个集合元素要占b位,编码后要占c(c < b)位。由于编码位数少于元素位数,不同元素的编码有可能相同,因此在查找元素时可能会出现错误。编码位数取决于你期望的错误率:编码位数越多,错误就越 少,反之则越大;当错误少到一定程度(大约2-b),编码位数就足以存下整个元素,因此就变回了传统的哈希存储。

这种方法对传统的哈希存储进行了改良,允许用户在错误率和存储空间之间作权衡。这里我们已经能够看到Bloom Filter的一点端倪。如果说这种方法已经孕育了“正确率换空间”的思想的话,那么Bloom Filter更是这个思想的大胆实践,它完全摆脱了传统的哈希存储方法,在存储空间使用和减少错误率方面又进了一步。

Bloom Filter

在Bloom Filter中,哈希区域的每一位都被当成是独立的可寻址的单元。在对集合元素进行编码时,同时使用若干个独立的哈希函数,将每一个哈希函数映射的地址都 置为1。这种编码方法可谓是另辟蹊径,摆脱了原来一个格子一个格子的存储方法。在改进的哈希存储中,编码位数是和正确率交换的筹码,而在Bloom Filter中,筹码变成了哈希函数的个数以及整个哈希区域(即位数组)的大小。如果想具体知道合适的哈希函数个数和位数组大小,请参阅第一篇Bloom Filter概念和原理。

和前面两种哈希存储方法相比,Bloom Filter最大的优势自然是它的空间效率。另外,由于Bloom Filter不用处理碰撞(Collision),因此它在增加或查找集合元素时所用的时间完全恒定(哈希函数的计算时间),无论集合元素本身有多大,也 无论多少集合元素已经加入到了位数组中。由于Bloom Filter和改进的哈希存储都对集合元素进行了编码,因此想要从哈希区域中恢复集合元素并不容易。但同时,如果你不想让别人直接看到集合元素,这样的编 码处理倒可以看成是一种加密,有效保护了你的隐私。

Bloom Filter很大的一个缺点就是不能删除元素。由于Bloom Filter不处理碰撞,有可能多个哈希函数都映射到了同一位,因此不能简单地在删除时将1置为0。后面我们会看到,Counting Bloom Filter通过将每一位扩展为一个Counter来解决这一问题。

2. larbin2.3中的url去重算法

larbin的url去重算法在hashTable.cc文件中实现。其中hashTable::testSet用以测试url是否已被爬取过;并在table的相应位置上置0或1.

bool hashTable::testSet (url *U) {
unsigned int code = U->hashCode();
unsigned int pos = code / 8;
unsigned int bits = 1 << (code % 8);
int res = table[pos] & bits;
table[pos] |= bits;
return !res;
}

使用hashTable类中的私有成员char *table变量来记录url是否被访问过。在hashTable类的构造函数中,table = new char[total]。char为1个字节,占8位,pos表示code处于哪个字节上,pos表示code处于这个字节上的哪些位。如果url被访问过,则res 为真,testSet的返回值即为false;如果url未被访问过,则table[pos]字节上对应的bits的位的值应为0,所以res为假,testSet返回值为true。在结束后,在table中再将这个没有被访问过的url标记为已访问。这样,当url越来越多时,误判为已访问的概率也会越来越大。

这个是bloom filter算法么?

【转】larbin中的url去重算法的更多相关文章

  1. [爬虫学习笔记]基于Bloom Filter的url去重模块UrlSeen

            Url Seen用来做url去重.对于一个大的爬虫系统,它可能已经有百亿或者千亿的url,新来一个url如何能快速的判断url是否已经出现过非常关键.因为大的爬虫系统可能一秒钟就会下载 ...

  2. [原创]手把手教你写网络爬虫(7):URL去重

    手把手教你写网络爬虫(7) 作者:拓海 摘要:从零开始写爬虫,初学者的速成指南! 封面: 本期我们来聊聊URL去重那些事儿.以前我们曾使用Python的字典来保存抓取过的URL,目的是将重复抓取的UR ...

  3. 爬虫URL去重

    这个要看你想抓取的网页数量是哪种规模的.如果是千万以下用hash表, set, 布隆过滤器基本可以解决,如果是海量的......嗯我也没做过海量的,不过hash表之类的就别想了,内存根本不够,分割线下 ...

  4. 大数据排序算法:外部排序,bitmap算法;大数据去重算法:hash算法,bitmap算法

    外部排序算法相关:主要用到归并排序,堆排序,桶排序,重点是先分成不同的块,然后从每个块中找到最小值写入磁盘,分析过程可以看看http://blog.csdn.net/jeason29/article/ ...

  5. URL去重与文章去重的一些基本方法

    一.url去重url存到数据库所有url放到set中(一亿条占用9G内存)md5之后放到set中(一亿条占用2,3G的内存)scrapy采用的就是类似方法bitmap方法(url经过hash后映射到b ...

  6. URL 去重的 6 种方案!(附详细实现代码)

    URL 去重在我们日常工作中和面试中很常遇到,比如这些: 可以看出,包括阿里,网易云.优酷.作业帮等知名互联网公司都出现过类似的面试题,而且和 URL 去重比较类似的,如 IP 黑/白名单判断等也经常 ...

  7. CodeIgniter框架中关于URL(index.php)的那些事

    最近,在做自己的个人网站时,采用了轻量级的php框架CodeIgniter.乍一看上去,代码清晰简洁,MVC模型非常容易维护.开发时我采用的工具是Netbeans IDE 8.0,当然,本文的内容和开 ...

  8. javascript数组去重算法-----3

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. javascript中数组的常用算法深入分析

    Array数组是Javascript构成的一个重要的部分,它可以用来存储字符串.对象.函数.Number,它是非常强大的.因此深入了解Array是前端必修的功课.本文将给大家详细介绍了javascri ...

随机推荐

  1. Informatica元数据库解析

    Informatica所有的元数据信息均以数据库表的方式存到了元数据库中.当然Infa本身工具提供了很多的人性化的功能,使我们在开发时可以很方便的进行操作,但人们的需求总是万变的,需要方便的取到自己需 ...

  2. js函数——倒计时模块+无缝滚动

    倒计时 效果: 代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...

  3. ASP.NET MVC+Bootstrap个人博客之修复UEditor编辑时Bug(四)

    我的个人博客站在使用百度富文本编辑器UEditor修改文章时,遇到了一些问题,(不知是bug,还是我没有配置好).但总算找到了解决方法,在此记录下来. 小站首页文章列表显示为(显示去除HTML标签后的 ...

  4. android 触摸事件、点击事件的区别

    针对屏幕上的一个View控件,Android如何区分应当触发onTouchEvent,还是onClick,亦或是onLongClick事件? 在Android中,一次用户操作可以被不同的View按次序 ...

  5. bjfu1211 推公式,筛素数

    题目是求fun(n)的值 fun(n)= Gcd(3)+Gcd(4)+…+Gcd(i)+…+Gcd(n).Gcd(n)=gcd(C[n][1],C[n][2],……,C[n][n-1])C[n][k] ...

  6. Android的AutoCompleteTextView在API17高版本添加的setText函数在低版本系统居然能正常调用?官方文档是不是不靠谱了?

    官方文档:https://developer.android.com/reference/android/widget/AutoCompleteTextView.html#setText(java.l ...

  7. 从python的yield说起

    前段时间在读trac 中wiki模块的源码的时候,发现了很多地方都使用了yiled这一关键词, 感觉是在需要返回某个值的地方通过yield来代替return, 不是很明白其用法,所以仔细研究下. 一个 ...

  8. DOM笔记(三):Element接口和HTMLElement接口

    一.Element接口 Element接口表示一个元素,该接口扩展自Node接口,自然继承了Node接口的属性和方法,也有一套针对元素的属性和方法. Element接口常见的属性比较少,常用的就是一个 ...

  9. ACM1996

    /* 汉诺塔VI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  10. File-nodejs

    文件系统模块是一个简单包装的标准 POSIX 文件 I/O 操作方法集.您可以通过调用require('fs')来获取该模块.文件系统模块中的所有方法均有异步和同步版本. 文件系统模块中的异步方法需要 ...