咱们爬来了一些数据,接下来以豆瓣畅销书为例。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