咱們爬來了一些數據,接下來以豆瓣暢銷書爲例。html
爬蟲爬來的數據有前端
['艾倫•圖靈傳','深刻理解計算機系統(原書第2版)','C++ Primer 中文版(第 5 版)','深刻理解計算機系統','Web性能權威指南']
而咱們系統中原有的數據有python
['艾倫·圖靈傳','深刻理解計算機系統(原書第2版)','C++ Primer 中文版(第 4 版)','深刻理解計算機系統']
作前端的同志可能一眼就看出來了,兩個數組中有三個元素是由於全半角的緣故,是不能全詞匹配的,而前兩本書事實上是同一本書。而《深刻理解計算機系統》是能夠全詞匹配到的,《Web性能權威指南》一書是能夠直接添加到數據庫的。git
解決方案一:算法
這個任務大能夠交給編輯去作,可是時間複雜度爲 N^2,連程序都吃不消跑,更別提讓編輯作了。數據庫
解決方案二:數組
去除全部的標點符號,或者將全部全角符號轉化爲半角。 去掉全部空格。 而後進行全詞匹配,這樣作有些魯莽,可是速度一點也不慢。機器學習
解決方案三:函數
我想到了用 jieba 進行中文分詞,性能
import jieba book = '艾倫·圖靈傳' word = jieba.cut(book) words = list(word) # words = ['艾倫', '·', '圖靈', '傳']
對於每本書咱們均可以進行這樣一個分詞操做,並能夠考慮將標點符號去除。 而後看每兩個數組的元素的重合狀況,但要考慮歸一化,緣由以下:
顯然第 1 組看起來會比第 2 組類似一些,可是重合數是同樣的。使用重合數顯然不科學,咱們能夠經過除以分詞後單詞總數來計算它們的重合率。
解決方案四:
在想解決方案三的時候,我回憶起了之前作聚類算法的時候用的各類距離算法,對於實數的歐幾里得距離,用在 k-modes 中的對於類型數據的相異度量算法,前者在這裏顯然不適用,後者又顯得有點小題大作。而後我發現了一種叫作編輯距離 Edit Distance 的算法,又稱 Levenshtein 距離。[1]
編輯距離是指兩個字串之間,由一個轉成另外一個所需的最少編輯操做次數。 維基上給出了一個例子: 'kitten' 和 'sitting' 的編輯距離爲3:
碰巧的是有一個開源的 python 包恰好能夠計算 Levenshtein 距離,能夠經過如下安裝:
pip install python-Levenshtein
而後就能夠計算編輯距離了:
import Levenshtein texta = '艾倫·圖靈傳' textb = '艾倫•圖靈傳' print Levenshtein.distance(texta,textb) # 3
很天然地會有這個疑問,爲何這裏的編輯距離會是3,咱們來看看具體進行的編輯操做。
Levenshtein.editops('艾倫·圖靈傳', '艾倫•圖靈傳') [('insert', 6, 6), ('replace', 6, 7), ('replace', 7, 8)]
看起來只有一個字符的區別,可是這裏作了三次編輯操做,爲何?咱們來打印一下這兩個字符串的具體表達:
In [4]: a='艾倫·圖靈傳' In [5]: a Out[5]: '\xe8\x89\xbe\xe4\xbc\xa6\xc2\xb7\xe5\x9b\xbe\xe7\x81\xb5\xe4\xbc\xa0' In [6]: a='艾' In [7]: a Out[7]: '\xe8\x89\xbe'
看到這裏就明白了,咱們犯了一個錯誤,把這兩個字符串存成了 string 類型,而在 string 類型中,默認的 utf-8 編碼下,一箇中文字符是用三個字節來表示的。因而這裏又牽扯到了 Python 中的 string 和 unicode 的區別。然而在這個字節串中,咱們的編輯距離,的的確確是3。
如今從新來計算距離。
print Levenshtein.distance(u'艾倫·圖靈傳',u'艾倫•圖靈傳') # 1
如今就正確了,如今的編輯距離1就表明了兩本書的名字的差異度量。這時候就要開始作歸一化了,而巧的是,咱們發現這個 Levenshtein 包中自帶了一個類似度函數 jaro(),它能夠接受兩個字符串並給出從0到1範圍內的類似度。下面所顯示的0.888888888889便表示了這兩個字符串的類似度。
print Levenshtein.jaro(u'艾倫·圖靈傳',u'艾倫•圖靈傳') # 0.888888888889
而後咱們能夠寫個嵌套的 for 循環,設置一個閾值 threshold,計算每一對書本的類似度,當他們超過某一閾值時,進行處理。這裏要注意的就是,不要重複檢驗書本對,即檢測(書本 A,書本 B)和(書本 B,書本 A),這樣能夠避免 N^2 的時間複雜度。
固然最後其實仍是須要人工介入的,好比遇到第三本書這種狀況,版次不同並不算同一本書。再固然,咱們是能夠對全部版次有關的字符進行特殊處理,好比出現版次字符,並且兩本書不相同的時候,把距離函數的輸出值加上一個修正參數。不過,這種狀況太多太多,仍是用人工處理好了,此時的兩本書爲同一本書的機率是很高的。再否則,只能上機器學習了,可是也是要你有訓練樣本的。
參考文獻: [1] wikipedia Levenshtein_distance [2] Levenshtein Document