在企业级搜索引擎中,常用一个称为布隆过滤器(Bloom Filter)的算法来实现对已经抓取过的URL进行过滤。


布隆过滤器算法

我们经常要判断一个元素是否在一个集合里面,最直接的方法是将集合中的全部元素存储在计算机中,遇到一个新元素时,将它和集合中的元素直接比较。一般来讲,计算机中的集合是用哈希表(Hash Table)来存储的。它的好处是快速而准确,缺点是浪费存储空间。当集合比较小的时候,这个问题不显著,但是当集合巨大时,哈希表存储效率低的问题就显现出来了。
例如一个公众电子邮件的提供商总是需要过滤来自发件人的垃圾邮件。一个办法是记录下那些发垃圾的Email的地址。由于那些发件人不停地在注册新的地址,全世界至少 也有几十亿个发垃圾邮件的地址,将他们都存储起来需要大量的网路服务器。如果用哈希表(将每一个email地址对应成一个8字节的信息指纹,然后存入哈希表。由于哈希表存户效率一般只有50%,因此一个email地址需要占用16个字节,一亿个地址大约需要1.6GB )。因此存储几十亿个邮件地址可能需要几百个GB放入内存。
但是布隆过滤器只需要哈希表的1/8到1/4的大小就能够解决同样的问题。

算法描述

布隆过滤器是有巴顿·布隆于1970年提出来的,它实际上是一个很长的二进制向量和一系列随机映射函数。

建立过滤器

假设存储一亿个电子邮件的地址,需建立一个16亿二进制常量,即2亿字节的向量,然后将这个16亿个二进制位全部设置为0,对于每一个电子邮件地址X,用8个不同的随机数产生器(F1,F2,……F8)产生8个信息指纹(f1,f2,…….f8)。再用一个随机数产生器G把这8个信息指纹映射到1到16亿中的8个自然数g1,g2….g8。现在把这个8个位置的二进制位全部设为1。当我们对这个1亿个email地址都进行这样的处理后,一个针对这些email地址的布隆过滤器就建成了。

过滤器工作

对于电子邮件地址Y,我们用8个随机数产生器(F1,F2,……F8)对这个地址信息产生8个信息指纹S1,S2,….S8。然后将这8个指纹对应到布隆过滤器的8个二进制位,分别是T1,T2,…T8。如果Y在黑名单中,显然T1,T2,…..T8对用的8个二进制位一定是1,,这样在遇到任何黑名单中的电子邮件地址时,我们都能狗进行准确的判断。

不足之处

布隆过滤器会识别出所有在黑名单中的可疑地址,但是他也有极小的可能将一个不再黑名单中的邮件地址判定为黑名单,这种可能性很小。我们将它称之为误识概率。常见的补救办法是建立一个小的白名单,存储那些可能误判的邮件地址。

布隆过滤器Java实现

书上没有说所实现的接口visitedFrontier里面包含那几个函数,我也不能具体吧这个接口写出来,反正,不用继承接口,我们认为这是内部函数这也是一样的。
然后我将原来main函数里面的内容重新写了一个函数,然后在MAIN.main()里面调用,这样便于修改。

public class SimpleBloomFilter  {private static final int DEFAULT_SIZE = 2 << 24;private static final int[] seeds = new int[]{7, 11, 13, 31, 37, 61};private BitSet bits = new BitSet(DEFAULT_SIZE);private SimpleHash[] func = new SimpleHash[seeds.length];public SimpleBloomFilter() {for (int i = 0; i < seeds.length; i++) {func[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]);}}public void start(){String value = "stone2083@yahoo.cn";SimpleBloomFilter filter = new SimpleBloomFilter();System.out.println(filter.contains(value));filter.add(value);System.out.println(filter.contains(value));}//覆盖方法,把URL添加进来public void add(CrawlUrl value) {if (value != null) add(value.getOriUrl());}private void add(String value) {for (SimpleHash f : func) {bits.set(f.hash(value), true);}}public boolean contains(CrawlUrl value) {return contains(value.getOriUrl());}private 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;}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;}}
}

输出结果

布隆过滤器误判率表

比率(items:bits) 误判率(False-positive)
1:1 0.63212055882856
1:2 0.39957640089373
1:4 0.14689159766038
1:8 0.02157714146322
1:16 0.00046557303372
1:32 0.00000021167340
1:64 0.00000000000004

比较保守的实现是为每个URL分配4个字节,项目和位数的比是1:32,误判率是0.00000021167340。对于5000万数量级的URL,布隆过滤器只占用200MB,并且排重速度超快,一遍下来不到两分钟。

《自己动手写网络爬虫》笔记6-使用布隆过滤器实现Visited表相关推荐

  1. 记录《自己动手写网络爬虫 》书中涉及的内容学习一些算法

    第1篇  自己动手抓取数据 第1章  全面剖析网络爬虫 3 1.1  抓取网页 4 1.1.1  深入理解URL 4 1.1.2  通过指定的URL抓取 网页内容 6 1.1.3  Java网页抓取示 ...

  2. Python 网络爬虫笔记11 -- Scrapy 实战

    Python 网络爬虫笔记11 – Scrapy 实战 Python 网络爬虫系列笔记是笔者在学习嵩天老师的<Python网络爬虫与信息提取>课程及笔者实践网络爬虫的笔记. 课程链接:Py ...

  3. 网络爬虫笔记—Selenium

    网络爬虫笔记-Selenium 1.简介及环境安装 Selenium是一种自动化测试工具,利用它可以操作浏览器执行固定动作,例如点击.下拉等操作.在日常工作中,如果你需要用浏览器并且重复某项操作,那S ...

  4. 《用Python写网络爬虫第2版》PDF中英文+代码分析

    互联网包含了迄今为止最有用的数据集,并且大部分可以免费公开访问.但是,这些数据难以复用.它们被嵌入在网站的结构和样式当中,需要抽取出来才能使用.从网页中抽取数据的过程又称为网络爬虫,随着越来越多的信息 ...

  5. 网络爬虫笔记—图形验证码获取

    网络爬虫笔记-图形验证码获取 1.验证码获取思路 1)使用selenium库操作谷歌浏览器,打开目标网站: 2)对目标网站进行截图,并将图片保存到本地: 3)获取验证码元素节点在屏幕上的位置,即横纵坐 ...

  6. python爬虫教程:Python写网络爬虫的优势和理由

    在本篇文章里小编给各位整理了一篇关于选择Python写网络爬虫的优势和理由以及相关代码实例,有兴趣的朋友们阅读下吧. 什么是网络爬虫? 网络爬虫是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页 ...

  7. 网络爬虫笔记—滑动验证码识别

    网络爬虫笔记-滑动验证码识别 一.什么是滑动验证码 点击之前 点击之后 像这种通过滑动图片,补全缺口的方式,就是滑动验证码. 二.识别思路 1)使用selenium库操作谷歌浏览器,打开目标网站:关于 ...

  8. 网页爬虫python代码_《用python写网络爬虫》完整版+源码

    原标题:<用python写网络爬虫>完整版+源码 <用python写网络爬虫>完整版+附书源码 本书讲解了如何使用Python来编写网络爬虫程序,内容包括网络爬虫简介,从页面中 ...

  9. 《用Python写网络爬虫》——1.5 本章小结

    本节书摘来自异步社区<用Python写网络爬虫>一书中的第1章,第1.5节,作者 [澳]Richard Lawson(理查德 劳森),李斌 译,更多章节内容可以访问云栖社区"异步 ...

  10. Python 网络爬虫笔记10 -- Scrapy 使用入门

    Python 网络爬虫笔记10 – Scrapy 使用入门 Python 网络爬虫系列笔记是笔者在学习嵩天老师的<Python网络爬虫与信息提取>课程及笔者实践网络爬虫的笔记. 课程链接: ...

最新文章

  1. .net core 源码解析-web app是如何启动并接收处理请求(二) kestrel的启动
  2. mysql游标表间数据迁移_FalseMySQL存储过程--gt;通过游标遍历和异常处理迁移数据到历史表-mysql-第二电脑网...
  3. 怎么把网页保存到本地计算机,在IE浏览器中,将网页保存到本地计算机中,若只需保存其中的文字、超链接和表格信息,应该选择的保存类型为( )...
  4. tornado实现基于websocket的好友一对一聊天功能
  5. 云小课|DGC数据开发之基础入门篇
  6. 项目管理-让什么人做什么事
  7. Ice-E(Embedded Internet Communications Engine)移植到s3c2440A(arm9)linux(2.6.12)上的 -转
  8. dingo php,Laravel+Dingo/Api 自定义响应的实现
  9. 宽带连接不上,拨号宽带连接的创建。
  10. double几位小数_算法竞赛入门之每日一题:分数化化小数(decimal) C语言
  11. ECMAScript 5 —— 基本包装类型之String(下)
  12. Win10下的Hp1020P打印机。
  13. java诸神47723_诸神战纪二-死神之谜
  14. html5经纬度定位 源码_HTML5获取地理经纬度并通过百度接口得到实时位置
  15. 如何使用条形码字体在Crystal Report中创建代码39?
  16. Take me to your heart(English Song)
  17. 文字编辑软件的颠峰作品——Word发展历史全析
  18. Python 赵云被动免伤计算
  19. java 判断两个经纬度差异_计算两个经纬度点的实际距离
  20. json oracle 导入,JsonToOracle(Json导入Oracle工具)

热门文章

  1. RedHat7 安装 MySQL 5.7
  2. word下禁止显示回车符号
  3. 单片机原理及接口技术(C51编程)(第2版)-习题答案
  4. FoxitReader3.0注册码和foxit pdf creator key foxit pdf editor v2.0 key
  5. 内外网切换,内网固定ip
  6. 计算机综合布线基本知识,综合布线系统基础知识学习
  7. java怎么生成class文件_怎样将java的class文件生成jar包
  8. python100以内的质数_100以内质数表
  9. 220套html模版百度云,220套静态网页模板
  10. 常见的10种配置管理工具