手把手教你写网络爬虫(7)

来源:互联网 发布:广之旅待遇怎样知乎 编辑:程序博客网 时间:2024/05/06 23:31

本期我们来聊聊URL去重那些事儿。以前我们曾使用Python的字典来保存抓取过的URL,目的是将重复抓取的URL去除,避免多次抓取同一网页。爬虫会将待抓取的URL放在todo队列中,从抓取到的网页中提取到新的URL,在它们被放入队列之前,首先要确定这些新的URL是否被抓取过,如果之前已经抓取过了,就不再放入队列。

有别于单机系统,在分布式系统中,这些URL应该存放在公共缓存中,才能让多个爬虫实例共享,我们继续使用Redis缓存这些数据。URL既可以存储在Redis的Set数据结构中,也可以将URL作为Key存储为Redis的String类型。至于这两种方案各有什么优缺点,就留给读者自己去思考了。

直接存储URL

将URL以字符串的形式直接存储到内存中。保守估计一下URL的平均长度是100字节,那么1亿个URL所占的内存是: 100000000 * 0.0001MB = 10000MB,约等于10G。这也不是不能用,占用的空间再大都能通过扩容来解决。

问题是,如果一个服务器存不下这么多URL该怎么办呢?其实也简单,明确每台服务器的分工,也就是说得到一个URL就知道要交给哪台服务器存储,每台服务器只存储一类URL,比较简单的实现方式就是对URL先哈希再取模。虽然能用,但还是有很大优化空间的。

存储消息摘要

MD5是一个消息摘要算法,它的用途很广泛,我们这里用它来压缩URL。

消息摘要算法的特点:

  1. 无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。

  2. 只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出。

  3. 消息摘要是单向、不可逆的。只能进行正向的信息摘要,而无法从摘要中恢复出任何的原始消息。

以上特点说明我们可以通过存储URL的MD5来实现去重功能,因为不同的URL,MD5不同,相同的URL,MD5相同嘛。

以前我们要存的URL是这样的:

http://news.baidu.com/ns?ct=1&rn=20&ie=utf-8&bs=%E4%BA%AC%E4%B8%9C%E9%87%91%E8%9E%8D&rsv_bp=1&sr=0&cl=2&f=8&prevct=no&tn=news&word=%E4%BA%AC%E4%B8%9C%E9%87%91%E8%9E%8D&rsv_sug3=1&rsv_sug4=6&rsv_sug1=1&rsv_sug=1

对应的MD5值是这样的:

d552b0b40e21d06d73a1a0938635eb1a

怎么样?省了不少空间吧?

有人说,小编你不要骗我,这个算法的输入是个无穷集合,而输出是一个有限集合,必然会存在碰撞的,也就是存在不同的URL算出相同的MD5。这会导致去重时误判,少抓数据!

好吧,从理论上来说,必然会出现这种情况。可是出现这种情况的概率是多少呢?下面就算算两个不同URL产生相同消息摘要的概率。

以下是三种常见的消息摘要算法,分别是32、64、128字节,每个字节是十六进制数字的字符,它们的可能值数量分别是:

md5:   16^32 = 2^128 = 3.4 * 10^38

sha256:16^64  = 2^256 = 1.2 × 10^77

sha512:16^128 = 2^512 = 1.3 × 10^154

你可能会说,我是数字盲,我不知道这个数大不大。好吧,我为你找到了两个直观的参照物:

IPv6编码地址数:2^128(约3.4×10^38)

IPv6是IETF设计的用于替代现行版本IP协议(IPv4)的下一代IP协议,号称可以为全世界的每一粒沙子编上一个网址。

可观测宇宙中的原子总数:10^80

上图是哈勃望远镜对准天球上一个特定的区域(相当于整个天球面积的1/12700000)进行长时间的图像拍摄,最后在这个区域里面找到了约有10000个星系。这样可以合理的推测,目前我们能用天文望远镜观测到的宇宙范围内有1.27x10^11个星系。

一个星系的恒星数(行星忽略不计了)目前普遍接受的一个数量级是4x10^11个。

像太阳这样的恒星的质量是1.96x10^30kg。

这就可以算出宇宙的总质量为9.96x10^55kg。

一个氢原子的质量是1.66x10^-24g。

用宇宙质量除以一个氢原子的质量就得出了目前可观测宇宙中的近似原子个数是10^80个。

可见,不同URL产生相同消息摘要的可能性非常小,简直像大海捞针。。。不是,简直像宇宙中捞原子一样难,所以就放心使用吧。

消息摘要实现了对URL的压缩,但压缩后的大小还是和原来在一个数量级,空间效率并没有质的提升。有没有办法只用几个bit来唯一标识一个URL呢?有!布隆过滤器就是专门解决这类问题的。

布隆过滤器

BloomFilter是一种空间效率很高的随机数据结构,它利用bit数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合。BloomFilter的这种高效是有一定代价的:在判断一个元素是否属于某个集合时,有可能会把不属于这个集合的元素误认为属于这个集合(false positive)。因此,Bloom Filter不适合那些“零错误”的应用场合。而在能容忍低错误率的应用场合下,Bloom Filter通过极少的错误换取了存储空间的极大节省。

它的原理很简单,首先需要准bit数组(所有位初始化为0)和k个独立hash函数。将hash函数对应的值的位数组置1,查找时如果发现所有hash函数对应位都是1说明存在,否则不存在。很明显这个过程并不保证查找的结果是100%正确的。

如何根据输入元素个数n,确定bit数组m的大小及hash函数个数呢?当hash函数个数k=(ln2)*(m/n)时错误率最小。在错误率不大于E的情况下,m至少要等于n*lg(1/E)才能表示任意n个元素的集合。但m还应该更大些,因为还要保证bit数组里至少一半为0,则m应该>=nlg(1/E)*lge ,大概就是nlg(1/E)的1.44倍。假设错误率为0.01,则此时m应是n的13倍。这样k大概是8个。

Google的Guava基础库里有布隆过滤器的实现,非常的简洁和有深度,我们一起来学习一下这段java代码。

01函数的功能是把一条数据hash后保存到BitArray中,如果BitArray有变化则返回true,否则返回false。参数是数据、hash函数个数、BitArray地址。

04使用murmur3 hash出一个long型的值。为什么是一个,不应该是numHashFunctions个吗?请往下看。

05 06把hash64切成两半,变成hash1和hash2。

09 10重点来了,numHashFunctions个hash函数原来是这么来的:hash1+(i*hash2)。Excuse me? 这种操作太随意了吧?不用担心,请看《Less Hashing, Same Performance: Building a Better Bloom Filter》,里面论述了这种操作不会影响布隆过滤器的性能:A standard technique from the hashing literature is to use two hashfunctions h1(x) and h2(x) to simulate additional hashfunctions of the form gi(x) =h1(x) + ih2(x). We demonstrate that this techniquecan be usefully applied to Bloom filters and related data structures.Specifically, only two hash functions are necessary to effectively implement aBloom filter without any loss in the asymptotic false positive probability.这个优化非常有用,毕竟hash的代价还是很大的。

12 13是负的就取反(这里的操作都很粗暴)。

15设置BitArray里对应的bit,下面进入set()里看看。

02先get()一下,看看是不是已经置为1。

03 index右移6位就是除以64,说明data是long型的数组,除以64就定位到了bit所在的数组下标。1L左移index位,定位到了bit在long中的位置。

下一步

以上就是URL去重的一点思路,希望对大家有帮助。下期打算为大家介绍下字符编解码,以及乱码的完美解决方案。再见!


微信扫一扫
关注该公众号

阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 鞋不透气脚臭怎么办 卫生间窗在厨房怎么办 联想保修期过了怎么办 s8背面碎了怎么办 三星c5玩游戏卡怎么办 三星关机键失灵怎么办 购机凭证丢了怎么办 滴滴没人接单怎么办 头发干怎么办才好 唯品会东西碎了怎么办 唯品会买东西有质量问题怎么办 来分期不能退货怎么办 商场不肯退衣服怎么办 唯品会衣服坏了怎么办 京东买电视拆机坏的怎么办 余额宝资金冻结怎么办? 余额宝金额冻结怎么办 adidas买了假货怎么办 余额宝冻结金额怎么办 买到不合格地板怎么办 买到翻新地板怎么办 食品里有头发怎么办 家具环保不达标怎么办 买到坏了的食物怎么办 空调检测不合格的怎么办 淘宝卖精仿遇到打假怎么办? 没有收到提货码怎么办 增值税发票超过180天怎么办 花呗借钱还不上怎么办 实体店里没人气怎么办 EMS快件无人签收怎么办 邮政快递丢失了怎么办 快递手机丢了怎么办 拍照签收没收到怎么办 拼多多开店货源怎么办 被购买鉴定投诉怎么办 淘宝上买东西错想用花呗怎么办 淘宝想用花呗买东西差一点怎么办 买了假货怎么办还用吗 免税店买完东西怎么办 淘宝恶意拍单怎么办