如何对url去重?

  1. 将访问url保存到数据库中,效率低,最简单
  2. 将url保存到set中,查询速度快,但当url达到1亿多条时候,占用太多内存空间
  3. 将url经过md5等方法哈希后保存到set中
  4. 用bitmap,讲访问过的url通过hash函数映射到某一位,很容易出现冲突,更能压缩
  5. bloomfilter方法对bitmap进行改进,多重hash函数,避免冲突

那,如何实现bloomfilter方式url去重?

  1. #!/usr/bin/python3
  2.  
  3. __author__ = 'beimenchuixue'
  4. __blog__ = 'http://www.cnblogs.com/2bjiujiu/'
  5.  
  6. import mmh3
  7. import redis
  8. import math
  9. import time
  10.  
  11. class PyBloomFilter():
  12. #内置100个随机种子
  13. SEEDS = [543, 460, 171, 876, 796, 607, 650, 81, 837, 545, 591, 946, 846, 521, 913, 636, 878, 735, 414, 372,
  14. 344, 324, 223, 180, 327, 891, 798, 933, 493, 293, 836, 10, 6, 544, 924, 849, 438, 41, 862, 648, 338,
  15. 465, 562, 693, 979, 52, 763, 103, 387, 374, 349, 94, 384, 680, 574, 480, 307, 580, 71, 535, 300, 53,
  16. 481, 519, 644, 219, 686, 236, 424, 326, 244, 212, 909, 202, 951, 56, 812, 901, 926, 250, 507, 739, 371,
  17. 63, 584, 154, 7, 284, 617, 332, 472, 140, 605, 262, 355, 526, 647, 923, 199, 518]
  18.  
  19. #capacity是预先估计要去重的数量
  20. #error_rate表示错误率
  21. #conn表示redis的连接客户端
  22. #key表示在redis中的键的名字前缀
  23. def __init__(self, capacity=1000000000, error_rate=0.00000001, conn=None, key='BloomFilter'):
  24. self.m = math.ceil(capacity*math.log2(math.e)*math.log2(1/error_rate)) #需要的总bit位数
  25. self.k = math.ceil(math.log1p(2)*self.m/capacity) #需要最少的hash次数
  26. self.mem = math.ceil(self.m/8/1024/1024) #需要的多少M内存
  27. self.blocknum = math.ceil(self.mem/512) #需要多少个512M的内存块,value的第一个字符必须是ascii码,所有最多有256个内存块
  28. self.seeds = self.SEEDS[0:self.k]
  29. self.key = key
  30. self.N = 2**31-1
  31. self.redis = conn
  32. print(self.mem)
  33. print(self.k)
  34.  
  35. def add(self, value):
  36. name = self.key + "_" + str(ord(value[0]) % self.blocknum)
  37. hashs = self.get_hashs(value)
  38. for hash in hashs:
  39. self.redis.setbit(name, hash, 1)
  40.  
  41. def is_exist(self, value):
  42. name = self.key + "_" + str(ord(value[0]) % self.blocknum)
  43. hashs = self.get_hashs(value)
  44. exist = True
  45. for hash in hashs:
  46. exist = exist & self.redis.getbit(name, hash)
  47. return exist
  48.  
  49. def get_hashs(self, value):
  50. hashs = list()
  51. for seed in self.seeds:
  52. hash = mmh3.hash(value, seed)
  53. if hash >= 0:
  54. hashs.append(hash)
  55. else:
  56. hashs.append(self.N - hash)
  57. return hashs
  58.  
  59. pool = redis.ConnectionPool(host='127.0.0.1', port=6379, db=0)
  60. conn = redis.StrictRedis(connection_pool=pool)
  61.  
  62. if __name__ == '__main__':
  63. start = time.time()
  64. bf = PyBloomFilter(conn=conn)
  65. bf.add('www.jobbole.com')
  66. bf.add('www.zhihu.com')
  67. print(bf.is_exist('www.zhihu.com'))
  68. print(bf.is_exist('www.lagou.com'))

  

爬虫_url去重策略的更多相关文章

  1. aio 爬虫,去重,入库

    #aio 爬虫,去重,入库 import asyncio import aiohttp import aiomysql import re from pyquery import PyQuery st ...

  2. RocketMQ学习笔记(14)----RocketMQ的去重策略

    1. Exactly Only Once (1). 发送消息阶段,不允许发送重复的消息 (2). 消费消息阶段,不允许消费重复的消息. 只有以上两个条件都满足情况下,才能认为消息是“Exactly O ...

  3. 【Python必学】Python爬虫反爬策略你肯定不会吧?

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 正文 Python爬虫反爬策略三部曲,拥有这三步曲就可以在爬虫界立足了: ...

  4. python爬虫爬取策略

    爬取策略 关注公众号"轻松学编程"了解更多. 在爬虫系统中,待抓取URL队列是很重要的一部分.待抓取URL队列中的URL以什么样的顺序排列也是一个很重要的问题,因为这涉及到先抓取那 ...

  5. python scrapy爬虫数据库去重方法

    1. scrapy对request的URL去重 yield scrapy.Request(url, self.parse, dont_filter=False) 注意这个参数:dont_filter= ...

  6. 爬虫URL去重

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

  7. Python分布式爬虫打造搜索引擎完整版-基于Scrapy、Redis、elasticsearch和django打造一个完整的搜索引擎网站

    Python分布式爬虫打造搜索引擎 基于Scrapy.Redis.elasticsearch和django打造一个完整的搜索引擎网站 https://github.com/mtianyan/Artic ...

  8. crawler_爬虫_反爬虫策略

    关于反爬虫和恶意攻击的一些策略和思路   有时网站经常受到恶意spider攻击,疯狂抓取网站内容,对网站性能有较大影响. 下面我说说一些反恶意spider和spam的策略和思路. 1. 通过日志分析来 ...

  9. 网络爬虫(java)

       陆陆续续做了有一个月,期间因为各种技术问题被多次暂停,最关键的一次主要是因为存储容器使用的普通二叉树,在节点权重相同的情况下导致树高增高,在进行遍历的时候效率大大降低,甚至在使用递归的时候导致栈 ...

随机推荐

  1. Python(三)字典的增删改查和遍历

    一.增加

  2. Java学习笔记14(面向对象七:final、static)

    final:意为最终,不可变,是一个修饰词 有时候一个类地功能被开发好了,不想让子类重写,修改,这里就会用到final关键字 final修饰类: 不可以被继承,但是可以继承其他类 示例: public ...

  3. Mac下安装ant(利用brew)

    安装ant最简单的方法就是通过brew.步骤如下:1. 安装brew(如果已经安装可以跳过这步). ruby -e "$(curl -fsSL https://raw.github.com/ ...

  4. mysql 半同步复制 插件安装以及测试

    mysql Server version:         5.5.18-log MySQL Community Server (GPL)   1.安装插件 检查mysql是否支持动态添加插件: ro ...

  5. centos6.8 docker0: iptables: No chain/target/match by that name

    现象:之前docker gitlab运行的一直好好的,突然有一天访问不了,但容器却还运行着.于是我把gitlab容器重启,发现启动不了了,报错:docker0: iptables: No chain/ ...

  6. 获取 JavaScript 异步函数返回值的笔记

    wrong action function asyncfunc() { let ret = 100; setTimeout(() => { return ret; }, 1000) } let ...

  7. [PHP] PHP与Apache的模块配合说明

    1.当PHP需要在Apache服务器下运行时 一般来说,它可以mod_php5模块的形式集成, 此时mod_php5模块的作用是接收Apache传递过来的PHP文件请求,并处理这些请求, 然后将处理后 ...

  8. d3 画地图终极自适应大小方案

    d3,v4以前用d3画地图的时候,为了让地图差不多正好画在容器的上下左右正中间,不得不慢慢的这样调: const projection = d3.geoMercator() .center([108. ...

  9. Python3——让我们像孩子一样的去看书

    用tkinter来画高级图形 让我们一起创造一个按钮吧!"按住我:0  :" 那我们先做一个小例子,让我们第一眼先认识到这个它(tkinter)吧! 输入以下代码: from tk ...

  10. Linux下gdb的安装及使用入门

    1.安装gdb. 在root用户权限下: root@iZ2zeeailqvwws5dcuivdbZ:~# apt-get update ...... ...... ...... root@iZ2zee ...