python過濾器 布隆過濾器 python實現

2021-10-13 04:46:51 字數 2625 閱讀 3996

布隆過濾器是什麼?

在爬蟲爬取網頁的時候,我們會做的一件事情是判斷這個網頁是否之前已經爬取過。這個檢驗步驟在之前的文章裡我是用了乙個#集合#來儲存已經爬取過的網頁,而在計算機當中,使用hash表來儲存。hash表的好處就是能夠快速定位,而它的缺點也眾所皆知,就是儲存空間的浪費。

為什麼會浪費儲存空間呢?雜湊表方法需要把實實在在的具有特定長度的元素的資訊指紋儲存在記憶體或硬碟中的雜湊表中(比如每個email位址對應成乙個8位元組的資訊指紋),這個儲存量在實際應用中一般是相當大的。比如每儲存一億個email位址,需要0.8g大小的數字指紋儲存空間,考慮到雜湊表的儲存空間利用率一般只有一半,所以需要1.6g的儲存空間。如果儲存幾十億上百億的email位址,那就需要百億位元組的記憶體儲存空間。

為了解決空間浪費嚴重這一問題,我們採用布隆過濾器。布隆過濾器實際上是乙個很長的二進位制向量和一系列的隨機對映函式。

布隆過濾器是n位的二進位制陣列,其中n是位陣列的大小。它還有另乙個引數k,表示使用雜湊函式的個數。這些雜湊函式用來設定位陣列的值。當往過濾器中插入元素x時,h1(x), h2(x), …, hk(x)所對應索引位置的值被置「1」,索引值由各個雜湊函式計算得到。注意,如果我們增加雜湊函式的數量,誤報的概率會趨近於0.但是,插入和查詢的時間開銷更大,布隆過濾器的容量也會減小。

為了用布隆過濾器檢驗元素是否存在,我們需要校驗是否所有的位置都被置「1」,與我們插入元素的過程非常相似。如果所有位置都被置「1」,那也就意味著該元素很有可能存在於布隆過濾器中。若有位置未被置「1」,那該元素一定不存在。誤報

示意圖以上圖為例,具體的操作流程:假設集合裡面有3個元素,雜湊函式的個數為3。首先將位陣列進行初始化,將裡面每個位都設定位0。對於集合裡面的每乙個元素,將元素依次通過3個雜湊函式進行對映,每次對映都會產生乙個雜湊值,這個值對應位陣列上面的乙個點,然後將位陣列對應的位置標記為1。查詢w元素是否存在集合中的時候,同樣的方法將w通過雜湊對映到位陣列上的3個點。如果3個點的其中有乙個點不為1,則可以判斷該元素一定不存在集合中。反之,如果3個點都為1,則該元素可能存在集合中。注意:此處不能判斷該元素是否一定存在集合中,可能存在一定的誤判率。可以從圖中可以看到:假設某個元素通過對映對應下標為4,5,6這3個點。雖然這3個點都為1,但是很明顯這3個點是不同元素經過雜湊得到的位置,因此這種情況說明元素雖然不在集合中,也可能對應的都是1,這是誤判率存在的原因。from bitarray import bitarray

import mmh3class bloomfilter(set):

def __init__(self,size,hash_count):        #size:the num of the bitarray

#hash_count:the num of hash function

super(bloomfilter,self).__init__()        self.bit_array = bitarray(size)        self.bit_array.setall(0) #初始化為0

self.size = size        self.hash_count = hash_count        def __len__(self):            return self.size        def __iter__(self):            return iter(self.bit_array)        def add(self,item):            for i in range(self.hash_count):

index = mmh3.hash(item,i) % self.size                self.bit_array[index] = 1

return self

def __contains__(self,item):

out = true            for i in range(self.hash_count):

index = mmh3.hash(item,i)%self.size                if bit_array[index] == 0:

out = false

return outdef main():

bloom = bloomfilter(100,5)

fd = open("urls.txt")  #有重複的** 

bloomfilter = bloomfilter(100,10)

while true:

url = fd.readline().strip()

if (url == 'exit') :

print ('complete and exit now')            break

elif url not in bloomfilter:

bloomfilter.add(url)            # print(url)

else:

print ('url :%s has exist' % url )if __name__ == '__main__':

main()

**執行結果:

執行結果布隆過濾器的缺點:無法返回元素本身

布隆過濾器並不會儲存插入元素的內容,只能檢索某個元素是否存在。

刪除某個元素

想從布隆過濾器中刪除某個元素可不是一件容易的事情,你無法撤回某次插入操作,因為不同專案的雜湊結果可以被索引在同一位置。

布隆過濾器

布隆過濾器 bloom filter 是1970年由布隆提出的。它實際上是乙個很長的二進位制向量和一系列隨機對映函式。布隆過濾器可以用於檢索乙個元素是否在乙個集合中。它的優點是空間效率和查詢時間都遠遠超過一般的演算法,缺點是有一定的誤識別率和刪除困難。如果想要判斷乙個元素是不是在乙個集合裡,一般想到...

布隆過濾器

布隆過濾器的概念 如果想要判斷乙個元素是不是在乙個集合裡,一般想到的是將所有元素儲存起來,然後通過比較確定。鍊錶,樹等等資料結構都是這種思路.但是隨著集合中元素的增加,我們需要的儲存空間越來越大,檢索速度也越來越慢 o n o logn 不過世界上還有一種叫作雜湊表 又叫 雜湊表,hash tabl...

布隆過濾器

如果想判斷乙個元素是不是在乙個集合裡,一般想到的是將集合中所有元素儲存起來,然後通過比較確定。鍊錶 樹 雜湊表 又叫雜湊表,hash table 等等資料結構都是這種思路。但是隨著集合中元素的增加,我們需要的儲存空間越來越大。同時檢索速度也越來越慢。bloom filter 是一種空間效率很高的隨機...