Scrpay解决增量重复过滤的URL

在使用scrapy抓取网页的时候,我们通常会有个增量的需求,但是在这个过程中就会牵涉到一个url去重功能.一般去重复我们可以使用不同的策略,根据数据量的大与少,使用的策略也不一样。

对于数据量不是很大的情况下,可以直接使用md5算法,然后把抓取过得存放到一个文本内容,下一次再抓取的时候直接对比文件

内容是否有,有的话就跳过,没有的话就重新抓取。

但是对于数量是海量的情况下,如果放在文本里面有几个缺点:

1 文本内容很大,检索对比文本越来越耗时

2 磁盘空间越来越大,空间利用效率很低

所以我们需要使用一个新的策略,这个时候可以使用布隆过滤器,它就是专门在海量数据的时候执行过滤的时候使用,比如hadoop,hbase都会使用它。

OK 我们看一下实现代码

import redis
from hashlib import md5

#主要通过hash算法+md5算法以及blommfilter实现URL去重机制
#主要是针对海量数据

#算法思路:通过hash算法+md5算法 把字符串转换为唯一标识
    # 使用bm可以压缩字符串大小 使用位存储
class SimpleHash(object):
    def __init__(self, cap, seed):
        self.cap = cap
        self.seed = seed

    #计算hash
    def hash(self, value):
        ret = 0
        for i in range(len(value)):
            ret += self.seed * ret + ord(value[i])
        return (self.cap - 1) & ret

#布隆过滤器
class DuplicateBloomFilter(object):
    def __init__(self, host='localhost', port=6379, db=0, blockNum=1, key='bloomfilter'):

        self.server = redis.Redis(host=host, port=port, db=db)
        self.bit_size = 1 << 31  # RedisString类型最大容量为512M,现使用256M
        self.seeds = [5, 7, 11, 13, 31, 37, 61]
        self.key = key
        self.blockNum = blockNum
        self.hashfunc = []
        for seed in self.seeds:
            self.hashfunc.append(SimpleHash(self.bit_size, seed))

    #判断字符串是否存在
    def isContains(self, str_input):
        if not str_input:
            return False
        #通过md5算进行识别唯一字符串
        m5 = md5()
        m5.update(str_input)
        str_input = m5.hexdigest()
        ret = True
        name = self.key + str(int(str_input[0:2], 16) % self.blockNum)
        for f in self.hashfunc:
            loc = f.hash(str_input)
            ret = ret & self.server.getbit(name, loc)
        return ret

    #插入
    def insert(self, str_input):
        m5 = md5()
        m5.update(str_input)
        str_input = m5.hexdigest()
        name = self.key + str(int(str_input[0:2], 16) % self.blockNum)
        for f in self.hashfunc:
            loc = f.hash(str_input)
            self.server.setbit(name, loc, 1)


if __name__ == '__main__':
    bf = DuplicateBloomFilter()
    if bf.isContains('http://www.qbao.com'):
        print ('对不起当前的URL已经爬取过了')
    else:
        print ('当前的URL不存在可以爬取')
        bf.insert('http://www.qbao.com')
其实主要就是利用位存储空间的优势和md5算法的不可逆,从而实现过滤机制
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值