在互聯網出現以前,「抄」很不方便,一是「源」少,而是發佈渠道少;而在互聯網出現以後,「抄」變得很簡單,鋪天蓋地的「源」源源不斷,發佈渠道也數不勝數,博客論壇甚至是自建網站,而爬蟲還可讓「抄」徹底自動化不費勁。這就致使了互聯網上的「文章」重複性很高。這裏的「文章」只新聞、博客等文字佔據絕大部份內容的網頁。python
中文新聞網站的「轉載」(其實就是抄)現象很是嚴重,這種「轉載」幾乎是全文照抄,或改下標題,或是改下編輯姓名,或是文字個別字修改。因此,對新聞網頁的去重頗有必要。web
文章去重(或叫網頁去重)是根據文章(或網頁)的文字內容來判斷多個文章之間是否重複。這是爬蟲爬取大量的文本行網頁(新聞網頁、博客網頁等)後要進行的很是重要的一項操做,也是搜索引擎很是關心的一個問題。搜索引擎中抓取的網頁是海量的,海量文本的去重算法也出現了不少,好比minihash, simhash等等。算法
在工程實踐中,對simhash使用了很長一段時間,有些缺點,一是算法比較複雜、效率較差;二是準確率通常。數據庫
網上也流傳着百度採用的一種方法,用文章最長句子的hash值做爲文章的標識,hash相同的文章(網頁)就認爲其內容同樣,是重複的文章(網頁)。django
這個所謂的「百度算法」對工程很友好,可是實際中仍是會有不少問題。中文網頁的一大特色就是「天下文章一大抄」,各類博文、新聞幾乎一字不改或稍做修改就被網站發表了。這個特色,很適合這個「百度算法」。可是,實際中個別字的修改,會致使被轉載的最長的那句話不同,從而其hash值也不同了,最終結果是,準確率很高,召回率較低。函數
爲了解決這個問題,我提出了nshash(top-n longest sentences hash)算法,即:取文章的最長n句話(實踐下來,n=5效果不錯)分別作hash值,這n個hash值做爲文章的指紋,就像是人的5個手指的指紋,每一個指紋均可以惟一確認文章的惟一性。這是對「百度算法」的延伸,準確率仍是很高,可是召回率大大提升,原先一個指紋來肯定,如今有n個指紋來招回了。學習
你們在學python的時候確定會遇到不少難題,以及對於新技術的追求,這裏推薦一下咱們的Python學習扣qun:784,758,214,這裏是python學習者彙集地!!同時,本身是一名高級python開發工程師,從基礎的python腳本到web開發、爬蟲、django、數據挖掘等,零基礎到項目實戰的資料都有整理。送給每一位python的小夥伴!每日分享一些學習的方法和須要注意的小細節測試
點擊:python技術分享交流網站
該算法的原理簡單,實現起來也不難。比較複雜一點的是對於一篇文章(網頁)返回一個similar_id,只要該ID相同則文章類似,經過groupby similar_id便可達到去重目的。搜索引擎
爲了記錄文章指紋和similar_id的關係,咱們須要一個key-value數據庫,本算法實現了內存和硬盤兩種key-value數據庫類來記錄這種關係:
HashDBLeveldb 類:基於leveldb實現, 可用於海量文本的去重;
HashDBMemory 類:基於Python的dict實現,可用於中等數量(只要Python的dict不報內存錯誤)的文本去重。
這兩個類都具備get()和put()兩個方法,若是你想用Redis或MySQL等其它數據庫來實現HashDB,能夠參照這兩個類的實現進行實現。
HashDBLeveldb類的實現
HashDBMemory類的實現
從效率上看,確定是HashDBMemory速度更快。利用nshash對17400篇新聞網頁內容的測試結果以下:
HashDBLeveldb: 耗時2.47秒;
HashDBMemory: 耗時1.6秒;
具體測試代碼請看 example/test.py。
有了這兩個類,就能夠實現nshash的核心算法了。
首先,對文本進行分句,以句號、感嘆號、問號、換行符做爲句子的結尾標識,一個正在表達式就能夠分好句了。
其次,挑選最長的n句話,分別進行hash計算。hash函數能夠用Python自帶模塊hashlib中的md5, sha等等,也能夠用我在爬蟲教程中屢次提到的farmhash。
最後,咱們須要根據這n個hash值給文本內容一個similar_id,經過上面兩種HashDB的類的任意一種均可以比較容易實現。其原理就是,similar_id從0開始,從HashDB中查找這n個hash值是否有對應的similar_id,若是有就返回這個對應的similar_id;若是沒有,就讓當前similar_id加1做爲這n個hash值對應的similar_id,將這種對應關係存入HashDB,並返回該similar_id便可。
這個算法實現爲NSHash類:
NSHash類的實現
import nshash nsh = nshash.NSHash(name='test', hashfunc='farmhash', hashdb='memory') similar_id = nsh.get_similar(doc_text)
NSHash
類有三個參數:
name
: 用於hashdb保存到硬盤的文件名,若是hashdb是HashDBMemory, 則用pickle序列化到硬盤;若是是HashDBLeveldb,則leveldb目錄名爲:name+’.hashdb’。name按需隨便起便可。hashfunc
: 計算hash值的具體函數類別,目前實現兩種類型:md5
和farmhash
。默認是md5
,方便Windows上安裝farmhash不方便。hashdb
:默認是memory
即選擇HashDBMemory,不然是HashDBLeveldb。至於如何利用similar_id進行海量文本的去重,這要結合你如何存儲、索引這些海量文本。可參考example/test.py
文件。這個test是對excel中保存的新聞網頁進行去重的例子。