1. 程式人生 > >[Python3.4]通過Redis利用BloomFilter實現資料去重

[Python3.4]通過Redis利用BloomFilter實現資料去重

寫爬蟲的時候需要解決的一個很重要的問題就是需要判斷得來的新連結是否之前已經爬過。如果已經爬過,則沒有必要再爬。我之前採用的是非常笨拙的方法,就是把所有已經爬過的地址放在mysql的一張表中,但是問題在於,這樣每一個新連結到來,都會查詢一次是否該連結在表格中。這樣的話,單單查詢過程就會耗費磁碟大量的讀寫效能。而且實際執行的過程中也發現,磁碟的讀取速率是寫入速率的10倍以上,這顯然是不可接受的。
一個可行的改進方案是使用記憶體資料庫作為mysql的快取。這裡選用的是redis,是一種鍵值型資料庫。通過將需要頻繁查詢的內容讀入Redis,這樣可以直接通過redis查詢是否該連結已經存在,從而避免了直接從磁碟讀取資料,提高讀寫效能。

——————————資料庫————————————
●redis官網 點我
●然而,redis官方並不支援windows(你們這是對軟狗的歧視,哼!(╯‵□′)╯︵┻━┻)所以像我這樣想在win下使用的,可以去找Microsoft Open Tech group在github下的一個64位版本。 點我點我
●基礎設定教程:點我點我點我
●指令教程(bloomfilter主要通過setbit和getbit來實現)點我
——————————↑↑↑↑↑↑————————————

有個問題是,把所有資料都讀入記憶體是不可行的,因為資料量太大,而記憶體太小。所以這就需要bloomfilter出場了. 簡單的說,bloomfilter是通過多個hash函式,將字串對映到不同的位元位。通過查詢相應的位元位上的值是否全為1,來判斷該資料是否已存入資料庫中。值得注意的是,bloomfilter是有出錯概率的。簡單的說就是:
如果bloomfilter判斷不存在,則一定不存在
如果bloomfilter判斷存在,則可能不存在
看完發現簡直是為爬蟲量身定製啊有沒有!對於爬蟲而言,出錯的代價微乎其微,大不了少爬幾個就是了,反正不會重複爬。

bloomfilter介紹:這裡

對於python2.7來說,好像有個叫pybloomfilter的庫可以用。但那個是單執行緒的,當需要多執行緒合作時就不行了,而且不太適合3.4版本。所以我對網上別人寫的針對3.4版本的小程式稍加改進,使之能夠適合redis.

import redis

class SimpleHash():
    def __init__(self,cap,seed):
        self.cap=cap
        self.seed=seed
    def hash(self,value):
        ret=0
        for i in
range(value.__len__()): ret+=self.seed*ret+ord(value[i]) return ((self.cap-1) & ret) class BloomFilter(): def __init__(self): self.bit_size=1<<25 self.seeds=[5,7,11,13,31,37,61] self.r=redis.StrictRedis(host='127.0.0.1',port=6379,db=0) self.hashFunc=[] for i in range(self.seeds.__len__()): self.hashFunc.append(SimpleHash(self.bit_size,self.seeds[i])) def isContains(self,str_input,name): if str_input==None: return False if str_input.__len__()==0: return False ret=True for f in self.hashFunc: loc=f.hash(str_input) ret=ret & self.r.getbit(name,loc) return ret def insert(self,str_input,name): for f in self.hashFunc: loc=f.hash(str_input) self.r.setbit(name,loc,1) uid=['alskdjflkasjdf','kajdsklfjlkasdf','lhjkkjhrwqer','alskdjflkasjdf'] bf=BloomFilter() err_time=0 for id in uid: if bf.isContains(id,'test'): err_time+=1 else: bf.insert(id,'test') print(err_time)

相關推薦

[Python3.4]通過Redis利用BloomFilter實現資料

寫爬蟲的時候需要解決的一個很重要的問題就是需要判斷得來的新連結是否之前已經爬過。如果已經爬過,則沒有必要再爬。我之前採用的是非常笨拙的方法,就是把所有已經爬過的地址放在mysql的一張表中,但是問題在於,這樣每一個新連結到來,都會查詢一次是否該連結在表格中。這樣

使用Hadoop的MapReduce來實現資料

最近在系統學習大資料知識,學了沒有記錄過幾天又忘光了,所以把學習內容記錄下來,方便以後檢視  import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.

python3 利用tcp實現資料夾的遠端傳輸

實現功能: 通過tcp協議模擬資料夾的下載,注意是資料夾,不是檔案. 下面讓我們實現以下: 其中有部分功能還未實現有興趣的可以將程式碼自行補全 伺服器端程式碼: import os impor

BloomFilter(大資料)+Redis(持久化)策略

之前在重構一套文章爬蟲系統時,其中有塊邏輯是根據文章標題去重,原先去重的方式是,插入文章之前檢查待插入文章的標題是否在ElasticSearch中存在,這無疑加重了ElasticSearch的負擔也勢必會影響程式的效能! BloomFilter演算法 簡介:布隆過濾器實際上

利用python實現資料分析的大致主要流程(簡)

前提:這段程式碼只適用於對資料分析有簡單的基礎認識者 data是樣本資料集,target是對應的樣本目標 1. 分析特徵值 如果特徵值過多,將不需要的特徵值刪減,保留有影響或者影響較大的特徵值 2. 分解data和target 如果target目標值的資料量差異

《推薦系統實踐》__第4章__利用使用者標籤資料

目錄   4.1 UGC標籤系統的代表應用 4.1.1 Delicious 4.1.2 CiteULike 4.1.3 Last.fm 4.1.4 豆瓣 4.1.5 Hulu 4.2 標籤系統中的推薦問題 4.2.1 使用者為什麼進行標註 4.2.2

【探索】利用 canvas 實現資料壓縮

前言 HTTP 支援 GZip 壓縮,可節省不少傳輸資源。但遺憾的是,只有下載才有,上傳並不支援。如果上傳也能壓縮,那就完美了。特別適合大量文字提交的場合,比如部落格園,就是很好的例子。 雖然標準不支援「上傳壓縮」,但仍可以自己來實現。 Flash 首選方案當然是 Flash,畢竟它提供了壓縮 API。除了

利用Promise實現資料多個請求載入完成時執行某個方法

在實際開發中常常有些業務的資料是來自多個介面的,因為ajax是非同步,這樣就導致我們需要判斷是否請求到了資料然後在做其他的邏輯,在Promise沒有出現之前,通常我們的解決方法是,第一粗暴的改非同步為同步,但這樣會造成阻塞,非同步好像又失去了意義,第二也就是大家常用的解決辦法

scrapy利用redis實現url與增量爬取

引言之前資料採集時有2個需求就是url去重與資料的增量爬去(只能夠請求增加的url,不然會增加被爬網站的伺服器負荷),最開始的想法是指用redis的set實現url去重,但在後面開發中無意的解決了增量爬去的類容。下面貼上主要程式碼。具體實現步驟將每次爬去的連結存入redis(

selenium webdriver學習--利用POI實現資料驅動

包:HSSF          讀寫Excel   xls格式文件;          XSSF          讀寫Excel   ooxml、xlsx格式;          HWPT       讀寫Word、doc格式          HSLF         

利用vc實現資料表格匯出到CSV檔案

CSV檔案為文字檔案,利用逗號(,)分隔,操作與txt檔案原理一樣。可以利用EXCEL軟體開啟; 採用MFC中提供的對檔案操作的類:CFile類的派生類CStdioFile中的WriteString()函式寫一行資料,最簡單;  CFile類是微軟基礎檔案類的基類,

利用ORACLE實現資料抽樣(sample block)

做資料分析的,免不了碰到記錄資料量很大,怎麼辦? 做全面分析是不現實也沒有必要。 介紹一下抽樣方法及實現 幾種常用的抽樣方法: 1.簡單隨機抽樣(simple random sampling) 將所有調查總體編號,再用抽籤法或隨機數字表隨機抽取部分觀察資料組成樣本。 優點:操作簡單,均數、率及

利用ORACLE實現資料抽樣

做資料分析的,免不了碰到記錄資料量很大,怎麼辦? 做全面分析是不現實也沒有必要。 介紹一下抽樣方法及實現 幾種常用的抽樣方法: 1.簡單隨機抽樣(simple random sampling) 將所有調查總體編號,再用抽籤法或隨機數字表隨機抽取部分觀察資料組成樣

通過百度echarts實現資料圖表展示功能

現在我們在工作中,在開發中都會或多或少的用到圖表統計資料顯示給使用者。通過圖表可以很直觀的,直接的將資料呈現出來。這裡我就介紹說一下利用百度開源的echarts圖表技術實現的具體功能。 1、對於不太理解echarts是個怎樣技術的開發者來說,可以到echarts

利用Python實現彩票網站數據&mdash;&mdash;小樣

編程語言 Python 寫這篇文章純屬自娛自樂。主要是近期在自學如何利用Python解決IT運維的一些問題時,總是不得其門而入,為了增加學習興趣,就想通過完成一個小小有趣的爬蟲程序激勵下自己,同時也把這次經歷跟各位道友分享下。Technorati Tags: Python,爬網,彩票,數據,夏明亮首先

java實現大批量json檔案資料

上週從資料採集部門拿到一批400份的json檔案,每個檔案裡30w+的json物件,物件裡有uid,對重複的uid,需要去重下. 本人電腦4核8G已經不能滿足了,總是記憶體不夠用.所以在伺服器上寫了一下(配置8核128G)  ,結果讀取檔案以及去重都沒問題, 在最後的寫入是又是

java程式碼實現MySQL資料庫表千萬條資料

  準備工作: 1.資料庫表:datatest5 2.欄位: id 主鍵自增,val 重複值欄位併為val建立索引 3.設定innodb緩衝池大小 show variables like "%_buffer%"; SET GLOBAL innod

js利用indexof方法實現陣列

var arr = [1, 2, 1, 4, 3, 4, 2, 6, 8]; var newArr=[]; for(var i = 0; i < arr.length; i++) { if(newArr.indexOf(arr[i

python3 requests 對資料入庫

對於自己使用requests創寫的類及方法想要對資料進行去重入庫 問題1:如何做到資料去重處理? 答:使用set,並且set能夠自動實現去重效果。 問題2:當列表中有大資料怎麼提高讀取速度? 答:轉換為set型別。 a = [1, 4, 7, 2, 1, 8, 7

Java 簡單實現物件資料處理

對於資料庫去重相當簡單,只需要在查詢語句上新增DISTINCT關鍵字就可以搞定,但是針對Nosql資料庫而言DISTINCT未必支援,這時候我們需要自己手動實現。這裡有一個數據不重複的最簡單的原理:字串