【转】larbin中的url去重算法
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去重算法的更多相关文章
- [爬虫学习笔记]基于Bloom Filter的url去重模块UrlSeen
Url Seen用来做url去重.对于一个大的爬虫系统,它可能已经有百亿或者千亿的url,新来一个url如何能快速的判断url是否已经出现过非常关键.因为大的爬虫系统可能一秒钟就会下载 ...
- [原创]手把手教你写网络爬虫(7):URL去重
手把手教你写网络爬虫(7) 作者:拓海 摘要:从零开始写爬虫,初学者的速成指南! 封面: 本期我们来聊聊URL去重那些事儿.以前我们曾使用Python的字典来保存抓取过的URL,目的是将重复抓取的UR ...
- 爬虫URL去重
这个要看你想抓取的网页数量是哪种规模的.如果是千万以下用hash表, set, 布隆过滤器基本可以解决,如果是海量的......嗯我也没做过海量的,不过hash表之类的就别想了,内存根本不够,分割线下 ...
- 大数据排序算法:外部排序,bitmap算法;大数据去重算法:hash算法,bitmap算法
外部排序算法相关:主要用到归并排序,堆排序,桶排序,重点是先分成不同的块,然后从每个块中找到最小值写入磁盘,分析过程可以看看http://blog.csdn.net/jeason29/article/ ...
- URL去重与文章去重的一些基本方法
一.url去重url存到数据库所有url放到set中(一亿条占用9G内存)md5之后放到set中(一亿条占用2,3G的内存)scrapy采用的就是类似方法bitmap方法(url经过hash后映射到b ...
- URL 去重的 6 种方案!(附详细实现代码)
URL 去重在我们日常工作中和面试中很常遇到,比如这些: 可以看出,包括阿里,网易云.优酷.作业帮等知名互联网公司都出现过类似的面试题,而且和 URL 去重比较类似的,如 IP 黑/白名单判断等也经常 ...
- CodeIgniter框架中关于URL(index.php)的那些事
最近,在做自己的个人网站时,采用了轻量级的php框架CodeIgniter.乍一看上去,代码清晰简洁,MVC模型非常容易维护.开发时我采用的工具是Netbeans IDE 8.0,当然,本文的内容和开 ...
- javascript数组去重算法-----3
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- javascript中数组的常用算法深入分析
Array数组是Javascript构成的一个重要的部分,它可以用来存储字符串.对象.函数.Number,它是非常强大的.因此深入了解Array是前端必修的功课.本文将给大家详细介绍了javascri ...
随机推荐
- Hibernate管理Session和批量操作
Hibernate管理Session Hibernate自身提供了三种管理Session对象的方法 Session对象的生命周期与本地线程绑定 Session对象的生命周期与JTA事务绑定 Hiber ...
- Linux应用层直接操作GPIO
Linux应用层直接操作GPIO 在一个老手的指导下,应用层可以直接操作GPIO,具体指设置GPIO的输入输出以及输出电平高或者低.这个大大地提高了灵活性,官方的文档有GPIO Sysfs Inter ...
- POJ 2549 Sumsets
Sumsets Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10593 Accepted: 2890 Descript ...
- 用Python操作Mysql
平时的主要编程语言是Java,开发时也主要用Mysql,经常为了测试,调试的目的需要操作数据库,比如备份,插入测试数据,修改测试数据,有些时候不能简单的用SQL就能完成任务,或都很好的完成任务,用Ja ...
- Activity生命周期与状态保存
弹出系统对话框,程序仍部分可见 onPause 对话框消失时 onResume 调用一个新的Activity,老的Activity不可见时 onPause->onStop 从新的Activi ...
- InputFormat,OutputFormat,InputSplit,RecordRead(一些常见面试题),使用yum安装64位Mysql
列举出hadoop常用的一些InputFormat InputFormat是用来对我们的输入数据进行格式化的.TextInputFormat是默认的. InputFormat有哪些类型? DBInpu ...
- c++ Map使用
引入头文件: #include <map>1.初始化map<int, int> a, b;map<sting, int> a, b;2.添加数据 map<in ...
- IIS中使用PUT方法錯誤記錄
在IIS7.5中使用PUT,DELETE方法時會遇到404,405錯誤,特記錄解決辦法:404: 405: 在web.config的system.webServer節點中加入 <modules ...
- MANACHER---求最长回文串
求最长回文串,如果是暴力的方法的话,会枚举每个字符为中心,然后向两边检测求出最长的回文串,时间复杂度在最坏的情况下就是0(n^2),为什么时间复杂度会这么高,因为对于每一个作为中心的字符的检测是独立的 ...
- [iOS基础控件 - 6.10.5] UIApplication
A.概念 1.UIApplication对象是应用程序的象征,每个应用都有 2.单例 3.[UIApplication sharedApplication] 获取 4.iOS启动创建的第一个对象 5. ...