一、url去重的几种方式

1.使用 Java 的 Set 集合判重

Set 集合天生具备不可重复性,使用它只能存储值不相同的元素,如果值相同添加就会失败,因此我们可以通过添加 Set 集合时的结果来判定 URL 是否重复

通过研究java的set集合底层源码可以知道,Set底层是Hash来实现的,Hash类型是散列,所以是无序的。以传入的值作为key值,PERSENT作为value来存储到map中,如果key值相同,将会覆盖,这就是set为什么能去重的原因(key相同会覆盖)。

2.Redis Set 集合去重

Redis Set 集合是一个无序的、自动去重的集合数据类型,Set底层用两种数据结构存储,一个是hashtable,一个是inset,
通俗地讲使用 Redis 的 Set 集合的实现思路和 Java 中的 Set 集合思想思路是一致的,都是利用 Set 的不可重复性实现的;

从上述结果可以看出,当添加成功时表示 URL 没有重复,但添加失败时(结果为 0)表示此 URL 已经存在了。

3.数据库去重

我们也可以借助数据库实现 URL 的重复判断,首先我们先来设计一张 URL 的存储表,如下图所示:

4.唯一索引去重

我们也可以使用数据库的唯一索引来防止 URL 重复,它的实现思路和前面 Set 集合的思想思路非常像。

5.Guava 布隆过滤器去重

我们以网络爬虫为例。网络间的链接错综复杂,爬虫程序在网络间“爬行”很可能会形成“环”。为了避免形成“环”,程序需要知道已经访问过网站的URL。当程序又遇到一个网站,根据它的URL,怎么判断是否已经访问过呢?
第一个想法就是将已有URL放置在 HashSet中,然后利用 HashSet的特性进行判断。它只花费O(1)的时间。但是,该方法消耗的内存空间很大,就算只有1亿个URL,每个URL只算50个字符,就需要大约5GB内存。
如何减少内存占用呢?URL可能太长,我们使用MD5等单向哈希处理后再存到HashSet中吧,处理后的字段只有128Bit,这样可以节省大量的空间。我们的网络爬虫程序又可以继续执行了。
但是好景不长,网络世界浩瀚如海,URL的数量急速增加,以128bit的大小进行存储也要占据大量的内存。
这种情况下,我们还可以使用 BitSet,使用哈希函数将URL处理为1bit,存储在BitSet中。但是,哈希函数发生冲突的概率比较高,若要降低冲突概率到1%,就要将 BitSet的长度设置为URL个数的100倍。
但是冲突无法避免,这就带来了误判。理想中的算法总是又准确又快捷,但是现实中往往是“一地鸡毛”。我们真的需要100%的正确率吗?如果需要,时间和空间的开销无法避免;如果能够忍受低概率的错误,就有极大地降低时间和空间的开销的方法。
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

6.Redis 布隆过滤器去重

除了 Guava 的布隆过滤器,我们还可以使用 Redis 的布隆过滤器来实现 URL 判重。在使用之前,我们先要确保 Redis 服务器版本大于 4.0(此版本以上才支持布隆过滤器),并且开启了 Redis 布隆过滤器功能才能正常使用。

误差率的体现?

7.scrapy里面的指纹去重

Scrapy 有自动去重功能,它的去重使用了 Python 中的集合。这个集合记录了 Scrapy 中每个 Request 的指纹,这个指纹实际上就是 Request 的散列值。利用集合元素的不重复特性来实现 Request 的去重。

8.scrapy_redis共享的集合去重

Scrapy 的去重是利用集合来实现的,而scrapy-redis的去重就需要利用共享的集合,只不过是将指纹池储存到了redis中。

9.scrapy+布隆过滤器对接的使用

①安装scrapy-redis-bloomfilter 模块:pip install scrapy-redis-bloomfilter
②配置setting文件:
scrapy+布隆过滤器的使用

Ensure use this Scheduler

SCHEDULER = “scrapy_redis_bloomfilter.scheduler.Scheduler”

把去重模块更改为scrapy-redis-bloomfilter写好的模块

DUPEFILTER_CLASS = “scrapy_redis_bloomfilter.dupefilter.RFPDupeFilter”

Redis URL

REDIS_URL = ‘redis://localhost:6379/0’

散列函数的个数,个人偏向设置为10,不设置则默认为6,

BLOOMFILTER_HASH_NUMBER = 6

Bloom Filter的bit参数,默认30(一亿级指纹池)

BLOOMFILTER_BIT = 30

Persist

SCHEDULER_PERSIST = True
DUPEFILTER_CLASS 是去重类,如果要使用 BloomFilter 需要将 DUPEFILTER_CLASS 修改为该包的去重类。
BLOOMFILTER_HASH_NUMBER 是 BloomFilter 使用的哈希函数的个数,默认为 6,可以根据去重量级自行修改。
BLOOMFILTER_BIT 即前文所介绍的 BloomFilter 类的 bit 参数,它决定了位数组的位数,如果 BLOOMFILTER_BIT 为 30,那么位数组位数为 2 的 30 次方,将占用 Redis 128MB 的存储空间,去重量级在 1 亿左右,即对应爬取量级 1 亿左右。如果爬取量级在 10 亿、20 亿甚至 100 亿,请务必将此参数对应调高。

二、优缺点

三、总结

其中 Redis Set、Redis 布隆过滤器、数据库和唯一索引这 4 种解决方案适用于分布式系统,如果是海量的分布式系统,建议使用 Redis 布隆过滤器来实现 URL 去重,如果是单机海量数据推荐使用 Guava 的布隆器来实现 URL 去重。

参考地址:①.scrapy去重原理,scrapy_redis去重原理和布隆过滤器的使用
②.url去重的六种方案
③java set去重底层源码解析

url去重的几种方式相关推荐

  1. php解析url并得到url中的参数及获取url参数的四种方式

    本文给大家介绍php解析url并得到url中的参数及获取url参数的四种方式,涉及到将字符串参数变为数组,将参数变为字符串的相关知识,本文代码简单易懂,感兴趣的朋友一起看看吧 下面一段代码是php解析 ...

  2. java steam 去重_List去重的5种方式

    原标题:List去重的5种方式 转自:多纤果冻 以下介绍五种-不同的方法去除 Java 中ArrayList中的重复数据 1.使用LinkedHashSet删除arraylist中的重复数据 Link ...

  3. List集合去重的几种方式

    List集合去重的几种方式 1. 通过set集合的特性,集合元素的唯一性 public static List heavyListMethod01(List list){         Set se ...

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

    来源 | Java中文社群(ID:javacn666) URL 去重在我们日常工作中和面试中很常遇到,比如这些: 可以看出,包括阿里,网易云.优酷.作业帮等知名互联网公司都出现过类似的面试题,而且和 ...

  5. URL去重的几种方法

    在爬虫启动工作的过程中,我们不希望同一个网页被多次下载,因为重复下载不仅会浪费CPU机时,还会为搜索引擎系统增加负荷.而想要控制这种重复性下载问题,就要考虑下载所依据的超链接,只要能够控制待下载的UR ...

  6. stream去重_重复数据如何处理?List集合去重的四种方式

    List集合在Java日常开发中是必不可少的,只要懂得运用各种各样的方法就可以大大提高我们开发的效率,适当活用各种方法才会使我们开发事半功倍.但是,有时候难免会遇到集合里的数据是重复的,需要进行去除. ...

  7. url 参数传递的两种方式_Java项目实践,支付功能实现方式,第三方支付与银行接口支付...

    1.第三方支付 B2C电商的支付,一般由于支付金额比较小,支付比较频繁,所以一般采用第三方支付,常用的第三方支付有:支付宝.微信等. 他们的原理都差不多,都是在点击支付时,直接调用第三方支付接口,传入 ...

  8. 数组对象去重的四种方式(强推最后一种!!!)

    哈喽哈喽,我又来了. 今天分享的是数组对象去重的方式,先看看数组对象的形式: let arrObj = [{ name: "小红", id: 1 },{ name: "小 ...

  9. python列表实现_Python列表去重如何实现?列表去重的4种方式

    在开发中对列表去重是非常常见的需求,列表去重也是Python中一种常见的处理方式.列表作为Python中最常用的数据结构,承担了Python中大多数的数据存储任务,但Python本身是不满足互异性的, ...

最新文章

  1. C#笔记2__Char类、String类、StringBuilder类 / 正则表达式 /
  2. SQL Server日期格式的转换
  3. 索引中丢失IN或OUT
  4. Linux集群和自动化维3.1 Python语言的应用领域
  5. Openwrt系统初始时间
  6. ubuntu安装VMware Tools
  7. .NET 6新特性试用 | 隐式using指令
  8. mysql挂载到iscsi_corosync+pacemaker+iscsi磁盘实现mysql高可用
  9. POI以SAX方式解析Excel2007大文件(包含空单元格的处理)
  10. File.WriteAllText 写入TXT文件时不能正确换行只显示方块
  11. 玻璃盖板丝印质量及尺寸在线检测方案
  12. 千里追踪“假疫苗”产销链
  13. iOS11 增加的新技能
  14. dubbo官网最新版导航
  15. word文档没保存就关了怎么恢复?别慌!试试这个操作
  16. 新手学Python之学习官网教程(五: Data Structures)
  17. HTML,css和JavaScript的基础学习—css篇
  18. 如何通过神经网络实现XNOR函数?
  19. [LOJ2568][可并堆]APIO2016:烟花表演
  20. 一、翻越前端的三座大山——继承/原型链

热门文章

  1. CCleaner解决的三个问题
  2. c51语言1秒延时程序,KeilC51程序设计中几种精确延时方法
  3. php 查询功能,php如何实现查询功能实现
  4. Microbit与Arduino的区别
  5. Oracle通过SPOOL导出数据Excel、CSV、TXT格式
  6. ABAP 负数符号在前面显示/如何将负数改为正数
  7. ORB-SLAM:精确多功能单目SLAM系统
  8. java项目遇到风险漏洞示例与解决方案
  9. selenium直接刚淘宝登录
  10. 北京科技大学,计算机考研情况