今天
小帅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


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






使用 add 方法

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

如果不存在就返回 False








此外

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







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


那么
我们下回见啦
peace
  


扫一扫

学习 Python 没烦恼




ps:如果你想获取更多小帅b提供的私密非公开且纯净无广告的干货 vip 教程,可以了解一下:跟小帅b一起通往「Python高手之路」