今天

小帅b要跟你说说增量爬虫

是这样的当你去爬取某个网站的数据时

你会发现这些网站随着时间的推移会更新更多的网页数据

这时候你要爬取的是那些更新的网页数据

而不是又一次爬取整站的内容

对于一些稍微复杂点的网站它们的 url 之间会指来指去

如果你根据 url 的定向去爬取可能会出现这种情况





你的爬虫一直在里面绕圈圈
一直爬取重复的数据


这时候你的爬虫开始陷入了对人生的大思考





那么如何确保爬取的数据不要重复?


接下来就是
学习 python 的正确姿势



有朋友说
那就直接用数据库呗

在爬取前
把 url 存入数据库

下次爬取的时候再到数据库里面查询看下这个 url 是否存在数据库


如果存在那就说明这个 url 之前已经被爬取过了

如果不存在就把 url 保存到数据库中

这种方式虽然可行
但是如果数量一多查询速度就会大大降低
从而影响爬取效率了

其实
python 中有一个我们熟悉的数据结构


set

set 里面的元素是唯一不重复的所以我们可以将 url 塞进去

下次通过 in 来判断就可以了
因为它的平均复杂度为 O(1)

这样就比数据库的操作高效很多了








但是
这种方式有一个问题使用 python 的 set
是作用于内存的

一旦 url 的数量增多
就会很耗内存





不知道你还记得咱们之前说的这个如果你怕文件被篡改,那就这样做


在这里面咱们说到了 hash
通过散列可以生成唯一的指纹

那么这时候我们可以使用 url 进行 hash比如进行 MD5 加密

由于 MD5 值所占的内存更小 所以可以通过 MD5 来降低 url 的内存

也就是说直接把 url 进行 MD5然后把得到的 MD5 放进 set 就好了

可以做到缩短 url 的长度来降低内存的消耗


当然了
还有与之类似的


redis

redis 中也有和 Python 相似的 set我们可以使用它来存储 url 的 MD5

这种缓存数据库的优点在于
它可以作用于硬盘不会有消耗内存的压力

而对于海量数据的情况我们可以考虑使用

bloom filter

它的操作方式是这样的



使用 k 个 hash 函数来对集合中的 url 映射成位数组中的 k 个点


然后把他们置 1 

下次查询的时候
只要通过 hash 看看这个url 的结果是不是都是 1

如果都是 1这个 url 就可能存在

如果有任何一个 0就说明这个 url 一定不存在

懵逼了?我来画个图吧

一开始是这样的
假设我们集合有 n 个 url





这里初始化了位数组都是0

接着对集合中的 url 都进行 k 个 hash

这里以 url4 为例





可以看到
hash 之后映射到 1


当下次要判断新的 url 是否在集合中的时候就可以使用 hash 去查找





只要发现有 0
那么就说明这个 new_url 一定不存在于集合中

这样的方式可以节省超多的空间提高了空间的利用率

在 python 中早有实现了 bloomfilter 的库

pybloom

可以自己定义容量和容错率



听说你的爬虫一直在整站里循环绕圈圈爬取重复的数据?_java




使用 add 方法

如果元素存在就直接返回 True

如果不存在就返回 False




听说你的爬虫一直在整站里循环绕圈圈爬取重复的数据?_java_02





此外

还可以使用动态容量的方式




听说你的爬虫一直在整站里循环绕圈圈爬取重复的数据?_java_03




ok通过以上这些方法对于数据的去重相信你应该知道怎么做了

那么
我们下回见啦peace