今天同事被告知要写一个查询商品相似度的系统,我以为事类似推荐系统一样的高大上系统,心中暗自庆幸没有被委以如此重任,不然在紧迫的时间里学习实现这套系统一定会睡眠不足的,后来同事讲解后我才知道只是一个商品名称相似度查找的小系统,说白了就是字符串相似度!
关于字符串相似度python也有很多库,比如自带的difflib库,第三方Levenshtein库等等
关于字符串相似度的原理我网上找了一篇博客看看,可惜太长了,理论知识太多,专业性太强,惭愧,我看了两行就没坚持下去,就直接用difflib库了,理由也很简单,不需要额外安装

直接上代码(不要在意为什么是卫生巾,我不是变态):

 
  1. # -* coding:utf-8 -*-

  2. import difflib

  3. query_str = "美妆 日本 Laurier花王乐而雅F系列日用护翼卫生巾(25cm*17片)瞬吸干爽超薄棉柔".decode("utf-8")

  4. str_2 = "Lauríer 乐而雅 F系列敏感肌超长夜用护翼型卫生巾 40厘米 7片".decode("utf-8")#8

  5. str_3 = "Lauríer 乐而雅 花王S系列超薄日用护翼卫生巾 25厘米 19片".decode("utf-8")#10

  6. str_4 = "Lauríer 乐而雅 S系列 超薄瞬吸量多夜用卫生巾 30厘米 15片/包".decode("utf-8")#8

  7. str_5 = "Lauríer 乐而雅 花王F系列敏感肌超量日用护翼型卫生巾 25厘米 18片".decode("utf-8")#10

  8. print(difflib.SequenceMatcher(None, query_str, str_2).quick_ratio())

  9. print(difflib.SequenceMatcher(None, query_str, str_3).quick_ratio())

  10. print(difflib.SequenceMatcher(None, query_str, str_4).quick_ratio())

  11. print(difflib.SequenceMatcher(None, query_str, str_5).quick_ratio())

quick_ratio()比 ratio() 效率高,好像

虽然这个库和函数用起来很方便,但是,仔细一看发现结果却是:

0.560975609756
0.691358024691
0.571428571429
0.658823529412

结果显示相似度最高的尽然是“Lauríer 乐而雅 花王S系列超薄日用护翼卫生巾 25厘米 19片”,明显不对啊,一个F系列,一个S系列

于是我试了Levenshtein库

 
  1. import Levenshtein

  2. print(Levenshtein.ratio(query_str,str_2))

  3. print(Levenshtein.ratio(query_str,str_3))

  4. print(Levenshtein.ratio(query_str,str_4))

  5. print(Levenshtein.ratio(query_str,str_5))

结果:

0.487804878049
0.543209876543
0.404761904762
0.541176470588

还是第二条相似度最高,见鬼啊,难道是程序比我更懂卫生巾,好吧,反正我对卫生巾的知识为零,比我强也不奇怪,但是作为字符串而言,怎么看都应该是最后一条相似度最高啊,于是我开始想怎么提高正确度,当然什么机器学习之类的高大上我是不懂,我只能自己想办法
第一个想法,分词,然后用分词得到的列表中的子字符串到对比字符串中看出现了几个,出现的越多我就认为它相似度越高

这时候就用到了结巴分词

 
  1. # -* coding:utf-8 -*-

  2. import jieba

  3. import Levenshtein

  4. import difflib

  5. import numpy as np

  6. #jieba.load_userdict("dict.txt") #可以使用自定义词典

  7. query_str = "美妆 日本 Laurier花王乐而雅F系列日用护翼卫生巾(25cm*17片)瞬吸干爽超薄棉柔".decode("utf-8")

  8. str_2 = "Lauríer 乐而雅 F系列敏感肌超长夜用护翼型卫生巾 40厘米 7片".decode("utf-8")#8

  9. str_3 = "Lauríer 乐而雅 花王S系列超薄日用护翼卫生巾 25厘米 19片".decode("utf-8")#10

  10. str_4 = "Lauríer 乐而雅 S系列 超薄瞬吸量多夜用卫生巾 30厘米 15片/包".decode("utf-8")#8

  11. str_5 = "Lauríer 乐而雅 花王F系列敏感肌超量日用护翼型卫生巾 25厘米 18片".decode("utf-8")#10

  12. str_list=[str_2,str_3,str_4,str_5]

  13. seg_list = list(jieba.cut(query_str.strip()))#默认精确模式

  14. dict_data={}

  15. sarticiple =list(seg_list)

  16. for strs in str_list:

  17. num=0

  18. for sart in sarticiple:

  19. if sart in strs:

  20. num = num+1

  21. else:

  22. num = num

  23. dict_data[strs]=num

  24. for k,v in dict_data.items():

  25. print(k)

  26. print(v)

  27. print("\n")

结果:
Lauríer 乐而雅 花王S系列超薄日用护翼卫生巾 25厘米 19片
10

Lauríer 乐而雅 花王F系列敏感肌超量日用护翼型卫生巾 25厘米 18片
10

Lauríer 乐而雅 S系列 超薄瞬吸量多夜用卫生巾 30厘米 15片/包
8

Lauríer 乐而雅 F系列敏感肌超长夜用护翼型卫生巾 40厘米 7片
8

结果发现相似度最高的S系列也是最多10个匹配,这样可以推断出相似度算法基本也有一部分是像我这样分词匹配,看匹配的多少,难道这就是字符串相似度其中一部分算法?
这样还是没有提高准确度,那该怎么办呢,我在想原始字符串和对比字符串的两个长度会不会有什么关联呢,毕竟两个相同的字符串长度一定一样啊,那相似的字符串是不是长度也就越接近呢,那我可以用原始字符串减去(原始字符串和比较字符串的中位数)然后取得绝对值得到一个值用来调节相似度算法所得到的偏差值,因为我看difflib给出的值是在0.0x左右,所以我打算给调节值再乘以0.017,让它的影响力稍微小一点,不至于大的夸张,对于长度相等的我直接给0这个调节值,不要问为什么,我瞎给的

上代码:

 
  1. # -* coding:utf-8 -*-

  2. import jieba

  3. # import Levenshtein

  4. import difflib

  5. import numpy as np

  6. #jieba.load_userdict("dict.txt")

  7. class StrSimilarity():

  8.     def __init__(self,word):

  9.         self.word = word

  10.     #Compared函数,参数str_list是对比字符串列表

  11.     #返回原始字符串分词后和对比字符串的匹配次数,返回一个字典

  12.     def Compared(self,str_list):

  13.         dict_data={}

  14.         sarticiple =list(jieba.cut(self.word.strip()))

  15.         for strs in str_list:

  16.             num=0

  17.             for sart in sarticiple:

  18.                 if sart in strs:

  19.                     num = num+1

  20.                 else:

  21.                     num = num

  22.             dict_data[strs]=num

  23.         return dict_data

  24.     #NumChecks函数,参数dict_data是原始字符串分词后和对比字符串的匹配次数的字典,也就是Compared函数的返回值

  25.     #返回出现次数最高的两个,返回一个字典

  26.     def NumChecks(self,dict_data):

  27.         list_data = sorted(dict_data.iteritems(), key=lambda asd:asd[1], reverse=True)

  28.         length = len(list_data)

  29.         json_data = {}

  30.         if length>=2:

  31.             datas = list_data[:2]

  32.         else:

  33.             datas = list_data[:length]

  34.         for data in datas:

  35.             json_data[data[0]]=data[1]

  36.         return json_data

  37.     #MMedian函数,参数dict_data是出现次数最高的两个对比字符串的字典,也就是NumChecks函数的返回值

  38.     #返回对比字符串和调节值的字典

  39.     def MMedian(self,dict_data):

  40.         median_list={}

  41.         length = len(self.word)

  42.         for k,v in dict_data.items():

  43.             num = np.median([len(k),length])

  44.             if abs(length-num) !=0 :

  45.                 # xx = (1.0/(abs(length-num)))*0.1

  46.                 xx = (abs(length - num)) * 0.017

  47.             else:

  48.                 xx = 0

  49.             median_list[k] = xx

  50.         return median_list

  51.     #Appear函数,参数dict_data是对比字符串和调节值的字典,也就是MMedian函数的返回值

  52.     #返回最相似的字符串

  53.     def Appear(self,dict_data):

  54.         json_data={}

  55.         for k,v in dict_data.items():

  56.             fraction = difflib.SequenceMatcher(None, self.word, k).quick_ratio()-v

  57.             # fraction = difflib.SequenceMatcher(None, self.word, k).quick_ratio() + v

  58.             # print(fraction)

  59.             # print(difflib.SequenceMatcher(None, self.word, k).quick_ratio())

  60.             # print("++++")

  61.             json_data[k]=fraction

  62.         tulp_data = sorted(json_data.iteritems(), key=lambda asd:asd[1], reverse=True)

  63.         return tulp_data[0][0]

  64. def main():

  65.     query_str = "美妆 日本 Laurier花王乐而雅F系列日用护翼卫生巾(25cm*17片)瞬吸干爽超薄棉柔".decode("utf-8")

  66.     str_2 = "Lauríer 乐而雅 F系列敏感肌超长夜用护翼型卫生巾 40厘米 7片".decode("utf-8")#8

  67.     str_3 = "Lauríer 乐而雅 花王S系列超薄日用护翼卫生巾 25厘米 19片".decode("utf-8")#10

  68.     str_4 = "Lauríer 乐而雅 S系列 超薄瞬吸量多夜用卫生巾 30厘米 15片/包".decode("utf-8")#8

  69.     str_5 = "Lauríer 乐而雅 花王F系列敏感肌超量日用护翼型卫生巾 25厘米 18片".decode("utf-8")#10

  70.     str_list=[str_2,str_3,str_4,str_5]

  71.     # query_str = "美妆 韩国 SNP燕窝面膜 深层补水保湿提亮美白水库 25ml*10 包邮".decode("utf-8")

  72.     # str_6 = "LEADERS 丽得姿 领先润美强化补水面膜 25毫升/片 10片/盒".decode("utf-8")  #

  73.     # str_7 = "SNP 海洋燕窝高倍补水美白面膜 25毫升/片10片装".decode("utf-8")  #

  74.     # str_8 = "SNP 钻石美白提亮安瓶精华面膜 25毫升/片 10片装".decode("utf-8")  #

  75.     # str_list = [str_6, str_7, str_8]

  76.     # query_str = "美妆 丽得姿(Leaders)水库面膜超强补水(25ml*10片)".decode("utf-8")

  77.     # str_2 = "LEADERS 丽得姿 领先润美强化补水面膜 25毫升/片 10片/盒".decode("utf-8")

  78.     # str_3 = "LEADERS 丽得姿 美帝优超强补水面膜 25毫升/片 10片装".decode("utf-8")

  79.     # str_4 = "2件装 | 丽得姿 美帝优蜗牛原液面膜 10片装+领先润美强化补水面膜 10片装".decode("utf-8")

  80.     # str_5 = "LEADERS 丽得姿 领先润美祛痘净肤修复面膜 25毫升/片 10片装".decode("utf-8")

  81.     # str_list = [str_2,str_3,str_4,str_5]

  82.     ss = StrSimilarity(query_str)

  83.     list_data = ss.Compared(str_list)

  84.     num = ss.NumChecks(list_data)

  85.     mmedian = ss.MMedian(num)

  86.     print(ss.Appear(mmedian))

  87. if __name__=="__main__":

  88.     main()

结果:
Lauríer 乐而雅 花王F系列敏感肌超量日用护翼型卫生巾 25厘米 18片

整个代码可能会有bug,因为没有时间测试而且没有任何异常捕捉(这个习惯很差,所以我一直是个渣渣),从构思到写好博客花了我两个多小时,已经快三点了,不想测试,不想测试,不想测试

如果使用以上代码碰到bug请告诉我,互相进步,如果觉得我的瞎想的求相似度方法有问题,不合理,请一定要告诉我,因为我真的不知道相似度的算法原理,更加需要相互学习

今天换了一个思路写了一个,也改用了Levenshtein库,不过效果和上面的差不多

代码:

 
  1. # -* coding:utf-8 -*-

  2. import jieba

  3. import Levenshtein

  4. import re

  5. import difflib

  6. import numpy as np

  7. jieba.load_userdict("dict.txt")

  8. class StrSimilarity():

  9.     def __init__(self,word):

  10.         # word = word.replace("/", " ").replace("*".decode("utf-8"), " ")

  11.         # word = word.replace("(".decode("utf-8"), " ").replace(")".decode("utf-8"), " ").replace("、".decode("utf-8")," ")

  12.         # word = word.replace("cm", " ").replace("ml", " ").replace("毫升".decode("utf-8"), " ").replace("片".decode("utf-8"), " ")

  13.         # word = word.replace("克".decode("utf-8"), "").replace("杯".decode("utf-8"), "").replace("袋".decode("utf-8"), "").replace("g", "")

  14.         self.word = word

  15.     #Compared函数,参数str_list是对比字符串列表

  16.     #返回原始字符串分词后和对比字符串的匹配次数,返回一个字典

  17.     def Compared(self,str_list):

  18.         dict_data={}

  19.         sarticiple =list(jieba.cut(self.word.strip()))

  20.         for strs in str_list:

  21.             num=0

  22.             for sart in sarticiple:

  23.                 if sart.strip():

  24.                     # print(sart)

  25.                     if sart in strs:

  26.                         if re.match('^[0-9a-zA-Z]+.*', sart):

  27.                             num = num+1

  28.                         else:

  29.                             num+num

  30.                         num = num+1

  31.                     else:

  32.                         num = num

  33.                 else:

  34.                     num = num

  35.             dict_data[strs]=num

  36.         return dict_data

  37.     #NumChecks函数,参数dict_data是原始字符串分词后和对比字符串的匹配次数的字典,也就是Compared函数的返回值

  38.     #返回出现次数最高的两个并给一个调节值,匹配度越高分数越低(为了之后相似度减去用),返回一个字典

  39.     def NumChecks(self,dict_data):

  40.         list_data = sorted(dict_data.iteritems(), key=lambda asd:asd[1], reverse=True)

  41.         length = len(list_data)

  42.         json_data = {}

  43.         if length>=2:

  44.             datas = list_data[:2]

  45.         else:

  46.             datas = list_data[:length]

  47.         for data in datas:

  48.             if data[1] != 0:

  49.                 json_data[data[0]]=(1.0/(data[1]))*0.01

  50.             else:

  51.                 json_data[data[0]] =0

  52.         return json_data

  53.     #MMedian函数,参数dict_data是出现次数最高的两个对比字符串的字典,也就是NumChecks函数的返回值

  54.     #返回对比字符串和调节值的字典,用原始字符串长度减去两个对比字符串长度的中位数相减

  55.     def MMedian(self,dict_data):

  56.         median_list={}

  57.         length = len(self.word)

  58.         for k,v in dict_data.items():

  59.             num = np.median([len(k),length])

  60.             if abs(length-num) !=0 :

  61.                 # xx = (1.0/(abs(length-num)))*0.1

  62.                 xx = (abs(length - num)) * 0.017

  63.             else:

  64.                 xx = 0

  65.             median_list[k] = xx

  66.         return median_list

  67.     #Appear函数,参数dict_data是对比字符串和调节值的字典,也就是MMedian函数的返回值

  68.     #返回最相似的字符串

  69.     def Appear(self,dict_data):

  70.         json_data={}

  71.         for k,v in dict_data.items():

  72.             # fraction = difflib.SequenceMatcher(None, self.word, k).quick_ratio()-v

  73.             fraction = Levenshtein.ratio( self.word,k) - v

  74.             # print(v)

  75.             # print(fraction)

  76.             # print(difflib.SequenceMatcher(None, self.word, k).quick_ratio())

  77.             # print("++++")

  78.             json_data[k]=fraction

  79.         tulp_data = sorted(json_data.iteritems(), key=lambda asd:asd[1], reverse=True)

  80.         return tulp_data[0][0]

  81. def main():

  82.     query_str = "美妆 日本 Laurier花王乐而雅F系列日用护翼卫生巾(25cm*17片)瞬吸干爽超薄棉柔".decode("utf-8")

  83.     str_2 = "Lauríer 乐而雅 F系列敏感肌超长夜用护翼型卫生巾 40厘米 7片".decode("utf-8")#8

  84.     str_3 = "Lauríer 乐而雅 花王S系列超薄日用护翼卫生巾 25厘米 19片".decode("utf-8")#10

  85.     str_4 = "Lauríer 乐而雅 S系列 超薄瞬吸量多夜用卫生巾 30厘米 15片/包".decode("utf-8")#8

  86.     str_5 = "Lauríer 乐而雅 花王F系列敏感肌超量日用护翼型卫生巾 25厘米 18片".decode("utf-8")#10

  87.     str_list=[str_2,str_3,str_4,str_5]

  88.     # query_str = "美妆 韩国 SNP燕窝面膜 深层补水保湿提亮美白水库 25ml*10 包邮".decode("utf-8")

  89.     # str_6 = "LEADERS 丽得姿 领先润美强化补水面膜 25毫升/片 10片/盒".decode("utf-8")  #

  90.     # str_7 = "SNP 海洋燕窝高倍补水美白面膜 25毫升/片10片装".decode("utf-8")  #

  91.     # str_8 = "SNP 钻石美白提亮安瓶精华面膜 25毫升/片 10片装".decode("utf-8")  #

  92.     # str_list = [str_6, str_7, str_8]

  93.     ss = StrSimilarity(query_str)

  94.     list_data = ss.Compared(str_list)

  95.     num = ss.NumChecks(list_data)

  96.     mmedian = ss.MMedian(num)

  97.     print(ss.Appear(mmedian))

  98. if __name__=="__main__":

  99.     main()

结果:

Lauríer 乐而雅 花王F系列敏感肌超量日用护翼型卫生巾 25厘米 18片

不管我怎么改,其实正确率只能提高很小的一点,很大的权重还在于两个字符串相似度库的分数

为了避免错误相似度问题,有些公司还会采用人工审核的方式,这样就不能只返回一个程序认为最相似的字符串而是要返回一个相似度降序排列的列表,这样方便人工审核

 
  1. # -* coding:utf-8 -*-

  2. import jieba

  3. # import Levenshtein

  4. import difflib

  5. import numpy as np

  6. from collections import Counter

  7. #jieba.load_userdict("dict.txt")

  8. class StrSimilarity():

  9. def __init__(self,word):

  10. self.word = word

  11. #Compared函数,参数str_list是对比字符串列表

  12. #返回原始字符串分词后和对比字符串的匹配次数,返回一个字典

  13. def Compared(self,str_list):

  14. dict_data={}

  15. sarticiple =list(jieba.cut(self.word.strip()))

  16. for strs in str_list:

  17. num=0

  18. for sart in sarticiple:

  19. if sart in strs:

  20. num = num+1

  21. else:

  22. num = num

  23. dict_data[strs]=num

  24. return dict_data

  25. #NumChecks函数,参数dict_data是原始字符串分词后和对比字符串的匹配次数的字典,也就是Compared函数的返回值

  26. #返回出现次数最高的两个,返回一个字典

  27. def NumChecks(self,dict_data):

  28. list_data = sorted(dict_data.iteritems(), key=lambda asd:asd[1], reverse=True)

  29. # length = len(list_data)

  30. json_data = {}

  31. # if length>=2:

  32. # datas = list_data[:2]

  33. # else:

  34. # datas = list_data[:length]

  35. for data in list_data:

  36. json_data[data[0]]=data[1]

  37. return json_data

  38. #MMedian函数,参数dict_data是出现次数最高的两个对比字符串的字典,也就是NumChecks函数的返回值

  39. #返回对比字符串和调节值的字典

  40. def MMedian(self,dict_data):

  41. median_list={}

  42. length = len(self.word)

  43. for k,v in dict_data.items():

  44. num = np.median([len(k),length])

  45. if abs(length-num) !=0 :

  46. # xx = (1.0/(abs(length-num)))*0.1

  47. xx = (abs(length - num)) * 0.017

  48. else:

  49. xx = 0

  50. median_list[k] = xx

  51. return median_list

  52. #Appear函数,参数dict_data是对比字符串和调节值的字典,也就是MMedian函数的返回值

  53. #返回一个相似度降序列表

  54. def Appear(self,dict_data):

  55. sum_data = []

  56. json_data={}

  57. for k,v in dict_data.items():

  58. fraction = difflib.SequenceMatcher(None, self.word, k).quick_ratio()-v

  59. # fraction = difflib.SequenceMatcher(None, self.word, k).quick_ratio() + v

  60. # print(fraction)

  61. # print(difflib.SequenceMatcher(None, self.word, k).quick_ratio())

  62. # print("++++")

  63. json_data[k]=fraction

  64. tulp_data = sorted(json_data.iteritems(), key=lambda asd:asd[1], reverse=True)

  65. for data in tulp_data:

  66. sum_data.append(data[0])

  67. return tulp_data

  68. def main():

  69. # query_str = "美妆 日本 Laurier花王乐而雅F系列日用护翼卫生巾(25cm*17片)瞬吸干爽超薄棉柔".decode("utf-8")

  70. # str_2 = "Lauríer 乐而雅 F系列敏感肌超长夜用护翼型卫生巾 40厘米 7片".decode("utf-8")#8

  71. # str_3 = "Lauríer 乐而雅 花王S系列超薄日用护翼卫生巾 25厘米 19片".decode("utf-8")#10

  72. # str_4 = "Lauríer 乐而雅 S系列 超薄瞬吸量多夜用卫生巾 30厘米 15片/包".decode("utf-8")#8

  73. # str_5 = "Lauríer 乐而雅 花王F系列敏感肌超量日用护翼型卫生巾 25厘米 18片".decode("utf-8")#10

  74. # str_list=[str_2,str_3,str_4,str_5]

  75. query_str = "美妆 韩国 SNP燕窝面膜 深层补水保湿提亮美白水库 25ml*10".decode("utf-8")

  76. str_6 = "LEADERS 丽得姿 领先润美强化补水面膜 25毫升/片 10片/盒".decode("utf-8") #

  77. str_7 = "SNP 海洋燕窝高倍补水美白面膜 25毫升/片10片装".decode("utf-8") #

  78. str_8 = "SNP 钻石美白提亮安瓶精华面膜 25毫升/片 10片装".decode("utf-8") #

  79. str_list = [str_6, str_7, str_8]

  80. # query_str = "美妆 丽得姿(Leaders)水库面膜超强补水 25ml*10片".decode("utf-8")

  81. # str_2 = "LEADERS 丽得姿 领先润美强化补水面膜 25毫升/片 10片/盒".decode("utf-8")

  82. # str_3 = "LEADERS 丽得姿 美帝优超强补水面膜 25毫升/片 10片装".decode("utf-8")

  83. # str_4 = "2件装 | 丽得姿 美帝优蜗牛原液面膜 10片装+领先润美强化补水面膜 10片装".decode("utf-8")

  84. # str_5 = "LEADERS 丽得姿 领先润美祛痘净肤修复面膜 25毫升/片 10片装".decode("utf-8")

  85. # str_list = [str_2,str_3,str_4,str_5]

  86. # query_str = "科沃斯(Ecovacs) CEN540 扫地机器人 地宝魔镜S".decode("utf-8")

  87. # str2 = "(Ecovacs)科沃斯 CEN540 扫地机器人 地宝魔镜S".decode("utf-8")

  88. # str_list = [str2]

  89. # query_str = "母婴 韩国本土好奇(HUGGIES)纸尿裤NATURE MADE 3段M,男,52片/包 *3".decode("utf-8")

  90. # str1 = "韩国金装好奇huggies超柔透气纸尿裤XXL码6段28片拉拉裤16魔术版".decode("utf-8")

  91. # str2 = "HUGGIES好奇金装纸尿裤宝宝尿不湿婴儿彩箱L104片比L129L72L40L36".decode("utf-8")

  92. # str3 = "Huggies好奇金装超柔贴身婴儿纸尿裤 宝宝尿不湿 小号S120片箱装".decode("utf-8")

  93. # str4 = "特!好奇Huggies 银装 婴儿纸尿裤 中号M160片7 - 11kg【京东送货】".decode("utf-8")

  94. # str5 = "现货德国进口欧版Huggies好奇婴儿宝宝防水游泳纸尿裤中码单片M号".decode("utf-8")

  95. # str6 = "韩国本土huggies好奇纯净版纸尿裤L码4段42片男宝原装进口尿不湿".decode("utf-8")

  96. # str7 = "好奇(Huggies) 银装 加大号XL104片(12 - 16kg) 干爽舒适 婴儿纸尿裤".decode("utf-8")

  97. # str8 = "现货 美国Huggies好奇婴儿宝宝游泳裤 防水纸尿裤 L码 大号 整包".decode("utf-8")

  98. # str9 = "HUGGIES / 好奇铂金装倍柔亲肤纸尿裤初生号NB66 + 10片 / NB76新生儿".decode("utf-8")

  99. # str10 = "【进口正品】好奇铂金装婴儿纸尿裤大号L58片 * 2包 透气干爽尿不湿".decode("utf-8")

  100. # str11 = "【进口正品】好奇铂金装婴儿纸尿裤XL44片 * 2包 透气干爽尿不湿".decode("utf-8")

  101. # str12 = "HUGGIES / 好奇金装超柔贴身纸尿裤中号M50 + 4片 好奇M号M54".decode("utf-8")

  102. # str13 = "Huggies好奇铂金装倍柔亲肤纸尿裤大号尿不湿L36 + 16 片 / L52片".decode("utf-8")

  103. # str14 = "现货欧洲Huggies好奇婴儿宝宝游泳裤防水纸尿裤L大码单片12 - 18kg".decode("utf-8")

  104. # str15 = "现货美国Huggies好奇婴儿宝宝游泳裤防水纸尿裤大L码单片14kg + ".decode("utf-8")

  105. # str16 = "好奇(Huggies) 铂金装倍柔亲肤纸尿裤中号M72原装进口".decode("utf-8")

  106. # str17 = "好奇S号 Huggies金装超柔纸尿裤新生儿小号S60 + 12片 / S72片 尿不湿".decode("utf-8")

  107. # str18 = "Huggies / 好奇纸尿裤L好奇金装超柔透气纸尿裤L72片 大码尿不湿".decode("utf-8")

  108. # str19 = "huggies好奇l铂金装纸尿裤l尿不湿l号铂金宝宝婴儿韩国原装进口l".decode("utf-8")

  109. # str20 = "Huggies好奇铂金装纸尿裤S58 + 12 片婴儿宝宝纸尿裤新生儿尿不湿".decode("utf-8")

  110. # str21 = "韩国本土Huggies好奇l纸尿裤l码尿不湿l50包邮清仓批发超薄韩版".decode("utf-8")

  111. # str22 = "美国Huggies好奇婴儿宝宝游泳裤防水纸尿裤尿不湿M码单片11 - 15kg".decode("utf-8")

  112. # str_list = [str1, str2, str3, str4, str5, str6, str7, str8, str9, str10, str11, str12, str13, str14, str15, str16,

  113. # str17, str18, str19, str20, str21, str22]

  114. ss = StrSimilarity(query_str)

  115. list_data = ss.Compared(str_list)

  116. num = ss.NumChecks(list_data)

  117. mmedian = ss.MMedian(num)

  118. print(ss.Appear(mmedian))

  119. if __name__=="__main__":

  120. main()

结果:

对于上面的算法其实还有很多问题,比如商品名中干扰项太多,打开淘宝搜索一件商品,你会发现商家为了让商品更多的被搜索到会加上很多词语,而这些词本身和商品无关的,亦或者是规格词语的中英文问题,有的是“毫升”,有的是“ml”,有的是“ML”,诸如此类,所以为了更准确的匹配到最相似的字符串需要过滤掉这些词,在TF-IDF中有一个停用词的概念,这里也拿来用一下,增加停用词过滤

 
  1. # -* coding:utf-8 -*-

  2. import jieba

  3. # import Levenshtein

  4. import difflib

  5. import numpy as np

  6. #jieba.load_userdict("dict.txt")

  7. #过滤词,这里只是针对不同网站标题的过滤词,如果数量很大可以保存在一个文件中

  8. stopwords = ["【","】","[","]","直邮","包邮","保税","全球购","包税","(",")","原装","京东超市","马尾保税仓","发货","进口","+","/","-","亏本","特价","现货","天天特价","专柜","代购","预定","正品","旗舰店","#",

  9. "转卖","国内","柜台","无盒","保税仓","官方","店铺","爆款","、"]

  10. #停用词,这里只是针对例子增加的停用词,如果数量很大可以保存在一个文件中

  11. conversions = ["克","毫升"]

  12. class StrSimilarity():

  13. def __init__(self,word):

  14. self.word = word

  15. #Compared函数,参数str_list是对比字符串列表

  16. #返回原始字符串分词后和对比字符串的匹配次数,返回一个字典

  17. def Compared(self,str_list):

  18. dict_data={}

  19. # sarticiple =list(jieba.cut(self.word.strip()))

  20. for cons in conversions:

  21. self.word[4] = self.word[4].replace(cons, "")

  22. # print(self.word[4])

  23. sarticiple = [self.word[0],self.word[2],self.word[3],self.word[4],self.word[5],self.word[6],self.word[7]]

  24. for strs in str_list:

  25. for sws in stopwords:

  26. strs_1 = strs.replace(sws.decode("utf-8")," ")

  27. num=0

  28. for sart in sarticiple:

  29. # print("qqqqqqqqqqqqqqq",sart.decode("utf-8"))

  30. sart = sart.decode("utf-8")

  31. counts = strs_1.count(sart)

  32. # print("zzzzzzzzzzzzzzzzzzz",strs_1)

  33. if counts!=0:

  34. # print("=========",sart)

  35. num = num+1

  36. else:

  37. # print("..............", sart)

  38. num = num-100

  39. if num>0:

  40. dict_data[strs]=num

  41. return dict_data

  42. #NumChecks函数,参数dict_data是原始字符串分词后和对比字符串的匹配次数的字典,也就是Compared函数的返回值

  43. #返回出现次数最高的两个,返回一个字典

  44. def NumChecks(self,dict_data):

  45. list_data = sorted(dict_data.iteritems(), key=lambda asd:asd[1], reverse=True)

  46. # length = len(list_data)

  47. json_data = {}

  48. # if length>=2:

  49. # datas = list_data[:2]

  50. # else:

  51. # datas = list_data[:length]

  52. for data in list_data:

  53. json_data[data[0]]=data[1]

  54. return json_data

  55. #MMedian函数,参数dict_data是出现次数最高的两个对比字符串的字典,也就是NumChecks函数的返回值

  56. #返回对比字符串和调节值的字典

  57. def MMedian(self,dict_data):

  58. median_list={}

  59. length = len(self.word)

  60. for k,v in dict_data.items():

  61. num = np.median([len(k),length])

  62. if abs(length-num) !=0 :

  63. # xx = (1.0/(abs(length-num)))*0.1

  64. xx = (abs(length - num)) * 0.017

  65. else:

  66. xx = 0

  67. median_list[k] = xx

  68. return median_list

  69. #Appear函数,参数dict_data是对比字符串和调节值的字典,也就是MMedian函数的返回值

  70. #返回最相似的字符串

  71. def Appear(self,dict_data):

  72. sum_data = []

  73. json_data={}

  74. for k,v in dict_data.items():

  75. word = " ".join(self.word)

  76. fraction = difflib.SequenceMatcher(None, word, k).quick_ratio()

  77. # print("++++++++++",difflib.SequenceMatcher(None, word, k).quick_ratio())

  78. # print("----------",v)

  79. # fraction = difflib.SequenceMatcher(None, self.word, k).quick_ratio() + v

  80. # print(fraction)

  81. # print(difflib.SequenceMatcher(None, self.word, k).quick_ratio())

  82. # print("++++")

  83. json_data[k]=fraction

  84. tulp_data = sorted(json_data.iteritems(), key=lambda asd:asd[1], reverse=True)

  85. for data in tulp_data:

  86. sum_data.append(data[0])

  87. return tulp_data

  88. def main():

  89. # query_str = "美妆 日本 Laurier花王乐而雅F系列日用护翼卫生巾(25cm*17片)瞬吸干爽超薄棉柔".decode("utf-8")

  90. # str_2 = "Lauríer 乐而雅 F系列敏感肌超长夜用护翼型卫生巾 40厘米 7片".decode("utf-8")#8

  91. # str_3 = "Lauríer 乐而雅 花王S系列超薄日用护翼卫生巾 25厘米 19片".decode("utf-8")#10

  92. # str_4 = "Lauríer 乐而雅 S系列 超薄瞬吸量多夜用卫生巾 30厘米 15片/包".decode("utf-8")#8

  93. # str_5 = "Lauríer 乐而雅 花王F系列敏感肌超量日用护翼型卫生巾 25厘米 18片".decode("utf-8")#10

  94. # str_list=[str_2,str_3,str_4,str_5]

  95. # query_str = "美妆 韩国 SNP燕窝面膜 深层补水保湿提亮美白水库 25ml*10".decode("utf-8")

  96. # str_6 = "LEADERS 丽得姿 领先润美强化补水面膜 25毫升/片 10片/盒".decode("utf-8") #

  97. # str_7 = "SNP 海洋燕窝高倍补水美白面膜 25毫升/片10片装".decode("utf-8") #

  98. # str_8 = "SNP 钻石美白提亮安瓶精华面膜 25毫升/片 10片装".decode("utf-8") #

  99. # str_list = [str_6, str_7, str_8]

  100. # query_str = "美妆 丽得姿(Leaders)水库面膜超强补水 25ml*10片".decode("utf-8")

  101. # str_2 = "LEADERS 丽得姿 领先润美强化补水面膜 25毫升/片 10片/盒".decode("utf-8")

  102. # str_3 = "LEADERS 丽得姿 美帝优超强补水面膜 25毫升/片 10片装".decode("utf-8")

  103. # str_4 = "2件装 | 丽得姿 美帝优蜗牛原液面膜 10片装+领先润美强化补水面膜 10片装".decode("utf-8")

  104. # str_5 = "LEADERS 丽得姿 领先润美祛痘净肤修复面膜 25毫升/片 10片装".decode("utf-8")

  105. # str_list = [str_2,str_3,str_4,str_5]

  106. # query_str = ["科沃斯","Ecovacs", "CEN540", "扫地机器人", "魔镜","S"]#.decode("utf-8")

  107. # str2 = "(Ecovacs)科沃斯 CEN540 扫地机器人 地宝魔镜N".decode("utf-8")

  108. # str3 = "(Ecovacs)科沃斯 CEN540 扫地机器人 地宝 S".decode("utf-8")

  109. # str4 = "科沃斯地宝灵犀扫地机器人家用智能吸尘器魔镜S升级版CEN540/546".decode("utf-8")#1299

  110. # str5 = "科沃斯地宝魔镜S扫地机器人吸尘器智能家用超薄全自动擦地机拖地".decode("utf-8")#1099

  111. # str6 = "科沃斯/Ecovacs 地宝魔戒 CEN550、魔镜S CEN540-LG扫地机器人".decode("utf-8")#868

  112. # str7 = "ECOVACS科沃斯/魔镜S 地宝灵犀 智能湿拖扫地机器人CEN540吸尘器".decode("utf-8")#849

  113. # str8 = "科沃斯/Ecovacs 地宝魔戒 CEN550 扫地机器人 魔镜S(CEN540-LG)".decode("utf-8")#888

  114. # str9 = "科沃斯(Ecovacs) CEN540 扫地机器人 地宝魔镜S 全自动充电".decode("utf-8")#959

  115. # str10 = "科沃斯(Ecovacs)地宝魔镜S(CEN540-LG)扫地机器人智能拖地".decode("utf-8")#1000

  116. # str_list = [str2,str3,str4,str5,str6,str7,str8,str9,str10]

  117. # query_str = ["花王","Merries", "纸尿裤", "妙而舒","L", "54片","",""]#.decode("utf-8")

  118. # str2 = "[店铺爆款]Kao/Merries 日本花王妙而舒新版纸尿裤大号(L)54 官方".decode("utf-8")

  119. # str3 = "【红孩子母婴】花王(Merries)妙而舒纸尿裤大号尿不湿L54片纸尿裤".decode("utf-8")

  120. # str4 = "日本 花王KAO 妙而舒 merries纸尿裤尿不湿 L码54片 保税发".decode("utf-8")#1299

  121. # str5 = "正品行货日本花王 Merries 妙而舒 纸尿裤 (L)54片".decode("utf-8")#1099

  122. # str6 = "日本本土正品花王 Merries 妙而舒 尿不湿纸尿裤 大号(L)54片".decode("utf-8")#868

  123. # str7 = "日本原装进口花王纸尿裤Merries妙而舒宝宝尿不湿 L码54片".decode("utf-8")#849

  124. # str8 = "香港代购 正品日本花王 Merries 妙而舒 纸尿裤 大号(L)54片".decode("utf-8")#888

  125. # str9 = "2包包邮 Merries 妙而舒 日本本土花王 尿不湿/纸尿裤 L码 54片".decode("utf-8")#959

  126. # str10 = "日本花王 Merries 妙而舒纸尿裤 尿布尿片 大号L 54 片".decode("utf-8")#1000

  127. # str_list = [str2,str3,str4,str5,str6,str7,str8,str9,str10]

  128. # query_str = ["伊思","It's skin", "韩国", "晶钻红参蜗牛面膜","25ml", "5片","",""]#.decode("utf-8")

  129. # str2 = "韩国its skin伊思晶钻蜗牛原液面膜贴 胶原蛋白祛痘净化修复面膜".decode("utf-8")

  130. # str3 = "韩国its skin伊思晶钻蜗牛原液面膜贴 胶原蛋白祛痘净化修复面膜".decode("utf-8")

  131. # str4 = "格润丝韩国蜗牛面膜原液多补水去皱嫩肤滋润保湿20片正品包邮".decode("utf-8")#1299

  132. # str5 = "韩国伊思(It's skin)晶钻红参蜗牛面膜(25ml*5片)".decode("utf-8")#1099

  133. # str6 = "韩国专柜正品 伊思it's skin晶钻红参蜗牛精华面膜贴25ml 5片/盒".decode("utf-8")#868

  134. query_str = ["诗留美屋", "Rosette", "海泥洁面乳洗面奶", "粉色白泥", "120克", "", "", ""] # .decode("utf-8")

  135. str2 = "日本代购Rosette 露姬婷海泥洗面奶去角质黑头控油 祛痘 保湿洁净".decode("utf-8")

  136. str3 = "日本Rosette蓝色海泥洁面膏洗面奶 清洁毛孔痘痘肌克星祛痘控油".decode("utf-8")

  137. str4 = "日本rosette|露姬婷 海泥洁面膏洗面奶女深层清洁绿色120g 去角质".decode("utf-8")#1299

  138. str5 = "日本诗留美屋Rosette 无添加海泥洁面乳洗面奶(粉色白泥)120克".decode("utf-8")#1099

  139. str6 = "诗留美屋(Rosette)无添加海泥洁面乳洗面奶(粉色白泥)120克".decode("utf-8")#868

  140. str7 = "日本诗留美屋Rosette海泥洁面乳洗面奶 粉色白泥 120g".decode("utf-8") # 868

  141. str_list = [str2,str3,str4,str5,str6,str7]

  142. # http://m.xiaohongshu.com/search/keyword?q=诗留美屋 Rosette 海泥洁面乳洗面奶 粉色白泥 120克

  143. # query_str = ["自然晨露", "DEWYTREE", "蛇毒嫩肤竹炭黑面膜", "10片盒装", "", "", "", ""] # .decode("utf-8")

  144. # str2 = "日本代购Rosette 露姬婷海泥洗面奶去角质黑头控油 祛痘 保湿洁净".decode("utf-8")

  145. # str3 = "日本Rosette蓝色海泥洁面膏洗面奶 清洁毛孔痘痘肌克星祛痘控油".decode("utf-8")

  146. # str4 = "日本rosette|露姬婷 海泥洁面膏洗面奶女深层清洁绿色120g 去角质".decode("utf-8") # 1299

  147. # str5 = "日本诗留美屋Rosette 无添加海泥洁面乳洗面奶(粉色白泥)120克".decode("utf-8") # 1099

  148. # str6 = "诗留美屋(Rosette)无添加海泥洁面乳洗面奶(粉色白泥)120克".decode("utf-8") # 868

  149. # str7 = "日本诗留美屋Rosette海泥洁面乳洗面奶 粉色白泥 120g".decode("utf-8") # 868

  150. #

  151. # str_list = [str2, str3, str4, str5, str6, str7]

  152. # "自然晨露 DEWYTREE 蛇毒嫩肤竹炭黑面膜 10片盒装"

  153. ss = StrSimilarity(query_str)

  154. list_data = ss.Compared(str_list)

  155. # print(list_data)

  156. num = ss.NumChecks(list_data)

  157. mmedian = ss.MMedian(num)

  158. print(ss.Appear(mmedian))

  159. if __name__=="__main__":

  160. main()

结果:

python 商品名称相似度查找(difflib库和结巴分词的运用)相关推荐

  1. Python中相似度对比-difflib模块

    计算两个字符串的相似度 应用场景:拼写纠错.文本去重.上下文相似性.不同来源数据对比 python中有比较相似度的模块 difflib,相关函数为difflib.SequenceMatcher().q ...

  2. python文本相似度分析_文本相似度分析(基于jieba和gensim)

    ##基础概念 本文在进行文本相似度分析过程分为以下几个部分进行, 文本分词 语料库制作 算法训练 结果预测 分析过程主要用两个包来实现jieba,gensim jieba:主要实现分词过程 gensi ...

  3. python使用heapq快速查找最大或最小的 N 个元素

    python使用heapq快速查找最大或最小的 N 个元素 heapq实现了一个适合与Python的列表一起使用的最小堆排序算法. 堆是非线性的树形的数据结构,有两种堆,最大堆与最小堆.( heapq ...

  4. python计算两张图片相似度,python 图片相似度匹配

    如何使用python来判断图片相似度 . fromPILimportImageimportos#importhashlibdefgetGray(image_file):tmpls=[]forhinra ...

  5. 学习Python要知道哪些重要的库和工具

    本文转自:https://github.com/jobbole/awesome-python-cn 环境管理 管理 Python 版本和环境的工具 p:非常简单的交互式 python 版本管理工具. ...

  6. python中文相似度_python文本相似度计算

    步骤分词.去停用词 词袋模型向量化文本 TF-IDF模型向量化文本 LSI模型向量化文本 计算相似度 理论知识 两篇中文文本,如何计算相似度?相似度是数学上的概念,自然语言肯定无法完成,所有要把文本转 ...

  7. python画罗小黑_Python3+requests库爬取豆瓣《罗小黑战记》评论

    贴一下抓到的评论,最后几条的 本渣是在校学生(非计算机相关),今年上半年接触Python,然后暑假开始学着写爬虫. 新手,本文如有错误,谢谢指正. 这个爬虫开始思路有点乱,现在比较清晰了 思路:req ...

  8. python 拼音相似度_Python实现简单的文本相似度分析操作详解

    本文实例讲述了Python实现简单的文本相似度分析操作.分享给大家供大家参考,具体如下: 学习目标: 1.利用gensim包分析文档相似度 2.使用jieba进行中文分词 3.了解TF-IDF模型 环 ...

  9. Python+审计实务与案例分析库 毕业设计-附源码211526

    Python审计实务与案例分析库 摘 要 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识 ...

最新文章

  1. SanDisk闪迪推面向VMware Virtual SAN 6的增强型闪存
  2. LeetCode Count Numbers with Unique Digits(计数问题)
  3. [笔记].在Quartus II下载时,找不到USB-Blaster的一个可能原因
  4. 互联网巨头们的「中台战事」
  5. Scrapy框架的学习(7. 了解Scrapy中的debug信息以及Scrapy shell的使用)
  6. android 如何使用LaunchMode
  7. 一种全新的点击率建模方案
  8. JS实现图片循环滚动
  9. centos7.2编译php,CentOS7.2编译安装PHP7.2.3之史上最详细步骤。
  10. Script to Setup NTP/DNS/Powerpolicy for new server
  11. linux之压缩文件,查看压缩文件,解压文件的操作命令
  12. 测试人,测试魂,3年测遍32个城,主管的一句话给予了他源源不断的动力
  13. 密码找回、带星号密码查看解决方案
  14. 4——Hive数仓项目完整流程(在线教育)
  15. CF1400:1490E、448B、1462FD、650A、1380B、1451C
  16. 数据库常用命令及关键字
  17. 查找并下载开放的音乐数据(.mp3)
  18. GraphicsLab Project之HDR渲染
  19. 推荐有关微信开发的十个开源项目
  20. Smartbi解读最严《数据安全法》,打开数据安全保护“新思路”!

热门文章

  1. dell电脑外星人电脑没开启什么程序风扇就高速转
  2. VS通过自定义宏设置环境变量
  3. MFC最简易7音符的电子琴
  4. “神仙打架”的预制菜赛道,鲜美来能靠水产品突围吗?
  5. java编程软件手机版_Java编程软件(Alice 3)
  6. 《寒战》看完整部电影的最大感觉竟然是没看懂
  7. python爬取7w+『赘婿』弹幕,发现弹幕比剧还精彩!
  8. WIN10 修改Edge浏览器图标
  9. poi 信息点 概念
  10. 现代机械设计理论与方法杨义勇pdf_【专业介绍| 高起本】机械设计制造及其自动化...