所謂的URL去重眨补,就是爬蟲將重復(fù)抓取的URL去除,避免多次抓取同一網(wǎng)頁翔始。爬蟲一般會將待抓取的URL放在一個隊列中罗心,從抓取后的網(wǎng)頁中提取到新的URL,在他們被放入隊列之前城瞎,首先要確定這些新的URL沒有被抓取過渤闷,如果之前已經(jīng)抓取過了,就不再放入隊列脖镀。
URL的去重方法有很多種飒箭,從次到優(yōu)依次可以分為以下5種:
1、將URL保存到數(shù)據(jù)庫進行去重(假設(shè)單個URL的平均長度是100 byte)。
2补憾、將URL放到HashSet中去重(一億條占用10G內(nèi)存)漫萄。
3、將URL經(jīng)過MD5之后保存到HashSet(MD5的結(jié)果是128 bit也就是16 byte的長度盈匾,一億條占用1.6G的內(nèi)存腾务,Scrapy采用的就是類似方法)。
4削饵、使用Bitmap或Bloomfilter方法去重(URL經(jīng)過hash后映射到bit的每一個位上岩瘦,一億URL占用約12M,問題是存在沖突)窿撬。
去重方法介紹
一启昧、將URL保存到數(shù)據(jù)庫進行去重
為了盡快把整個爬蟲搭建起來,最開始的URL去重采用方案是直接利用數(shù)據(jù)庫的唯一約束進行去重劈伴,這是最省時的做法密末,所有人都能想得到和做到。
二跛璧、將URL放到HashSet中去重
在數(shù)據(jù)庫中去重严里,每次比較都有一次請求數(shù)據(jù)庫的過程,這里對數(shù)據(jù)庫的性能消耗是很大的追城。于是可以使用將URL放到內(nèi)存中的HashSet中去重刹碾,HashSet中放置的就是URL的字符串,任何一個新的URL首先在HashSet中進行查找座柱,如果HashSet中沒有迷帜,就將新的URL插入HashSet,并將URL放入待抓取隊列色洞。?
這個方案的好處是它的去重效果精確戏锹,不會漏過一個重復(fù)的URL。它的缺點是火诸,隨著數(shù)據(jù)的增加會出現(xiàn)Out Of Memory锦针。
假設(shè)單個URL的平均長度是100 byte,那么一億條數(shù)據(jù)占用10G內(nèi)存惭蹂,大部分的電腦內(nèi)存在4G和8G伞插,那么留給JVM的內(nèi)存就更少啦割粮,那么出現(xiàn)內(nèi)存泄漏是遲早的事盾碗。
3、將URL經(jīng)過MD5之后保存到HashSet
遲早到底有多早呢舀瓢?也許是一個月廷雅,那么我們可以把這一個月擴展到半年。
這里的處理方式就是HashSet中不存儲原始的URL,而是將URL壓縮后再放進去航缀。壓縮的方式有很大商架,用MD5對URL做編碼是比較省時的一種方式。?
MD5的結(jié)果是128 bit也就是16 byte的長度芥玉,相比于之間估計的URL平均長度100byte已經(jīng)縮小了6倍多蛇摸,一億條數(shù)據(jù)占用1.6G的內(nèi)存,Scrapy采用的就是類似方法灿巧。
當然赶袄,不管使用那種壓縮算法,隨著URL越來越多抠藕,終有一天還是會Out Of Memory饿肺。所以,這個方案不解決本質(zhì)問題盾似。?
MD5另外一個問題是敬辣,有可能兩個相同的URL被映射成同一個MD5值,這樣的話零院,它們中有一個就永遠不會被抓取了溉跃。
4、使用Bitmap方法去重
使用Bitmap方法去重的原理是把URL經(jīng)過hash后映射到bit的每一個位上门粪,一億URL占用約12M喊积,主要缺點是去重沒那么精準,存在沖突玄妈。
總結(jié)
關(guān)于1乾吻、2、3我是有實踐過拟蜻,4的話沒有實踐绎签,同時為了解決內(nèi)存的問題,現(xiàn)在也可以使NoSQL的方案去解決酝锅,具體的沒有操作過就不多講啦诡必。
不過我們馬上就要去實踐啦,回頭我把實踐的結(jié)果再同步到這篇文章中來搔扁,歡迎關(guān)注爸舒。