Python 中 fuzzywuzzy 進行字符串模糊匹配的全過程
fuzzywuzzy 是 Python中 基于 Levenshtein 距離算法的字符串模糊匹配庫,提供 fuzz.ratio 、 partial_ratio 、 token_sort_ratio 等核心函數(shù),用于高效計算字符串相似度。該庫廣泛應(yīng)用于數(shù)據(jù)清洗、拼寫糾錯、文本挖掘和用戶輸入處理等場景。比如識別相同新聞(有些新聞可能會在不同平臺進行發(fā)布,標(biāo)題和內(nèi)容基本上沒太大差異,爬取時需要把這種的識別出來,避免重復(fù)處理浪費相應(yīng)資源)。
依賴安裝
pip install fuzzywuzzy python-Levenshtein
依賴安裝可以使用清華的 pip 鏡像源,不然會很慢,甚至很可能導(dǎo)致安裝失敗:
pip install fuzzywuzzy python-Levenshtein -i https://pypi.tuna.tsinghua.edu.cn/simple some-package
編輯距離
你可以把編輯距離想象成一場“變臉游戲”:給你兩個詞,比如“kitten”和“sitting”,你要通過最少的操作次數(shù),把第一個詞變成第二個詞。允許的操作只有三種:
- 插入 (Insert):加個字母
- 刪除 (Delete):刪個字母
- 替換 (Substitute):換個字母
比如將 “kitten” 怎么變成 “sitting” ?
- k → s (替換)
- e → i (替換)
- 在末尾加個 g (插入)
總共三步完成,所以它們的編輯距離就是3。這種以“最小改動次數(shù)”來衡量相似度的方式,非常符合人類的直覺。改動越少,說明倆詞越像;改動越多,就越不像。
相似度得分
fuzzywuzzy 把編輯距離轉(zhuǎn)化成了一個 0 到 100 的直觀評分。分?jǐn)?shù)越高,越像。
相似度得分 = (1 - 編輯距離 / 最長字符串長度) × 100
匹配函數(shù)
常用的匹配函數(shù)一般是下面這些,可能還會有一些衍生出來的變體,但整體分類上沒有太大變化。下面示例中,不同依賴包版本的算法可能會稍有差異,運行的結(jié)果可能會有不同屬于正?,F(xiàn)象。
完整比對
ratio() 要求整體上盡量一致,包括順序,詞匯,長度等。它就像一把尺子,從頭到尾量一遍兩個字符串的相似度。
from fuzzywuzzy import fuzz
standard = "iPhone 15 Pro Max"
variants = [
"Iphone15ProMax",
"iphone 15 pro max (256GB)",
"IPHONE 15 PRO MAX",
]
for v in variants:
print(f"{v}: {fuzz.ratio(standard.lower(), v.lower())}")
# Iphone15ProMax: 90
# iphone 15 pro max (256GB): 81
# IPHONE 15 PRO MAX: 100局部比對
partial_ratio() 自動把短的那個字符串當(dāng)成模板,在長的那個字符串上滑動,挨個位置截取同樣長度的子串,然后調(diào)用 ratio() 去比,最后返回最高的那個得分。
from fuzzywuzzy import fuzz query = "北京路" db_entry = "廣東省廣州市越秀區(qū)北京路步行街" print(fuzz.ratio(query, db_entry)) # 只有33多分 print(fuzz.partial_ratio(query, db_entry)) # 高達100分!
排序比對
token_sort_ratio() 會先把兩個字符串按空格或其他分隔符拆分成詞(token),然后排序,最后再調(diào)用 ratio() 比對得到結(jié)果。
from fuzzywuzzy import fuzz
print(fuzz.token_sort_ratio("紅 色 跑車", "跑車 紅 色")) # 輸出: 100排序局部比對 partial_token_sort_ratio()
上面這種比對,如果有額外的干擾項的話,還是會影響最終的得分結(jié)果。
from fuzzywuzzy import fuzz
print(fuzz.token_sort_ratio("紅 色 跑車", "跑車 紅 色 這是 干擾 項")) # 輸出: 60所以還有變體 partial_token_sort_ratio(),排序后再進行局部比對,就能避免額外項的干擾了
from fuzzywuzzy import fuzz
print(fuzz.token_sort_ratio("紅 色 跑車", "跑車 紅 色 這是 干擾 項")) # 輸出: 60
print(fuzz.partial_token_sort_ratio("紅 色 跑車", "跑車 紅 色 這是 干擾 項")) # 輸出: 100核心比對
token_set_ratio() 會提取兩個字符串的所有唯一詞匯,然后分成三部分:交集(共同有的詞)、A獨有、B獨有。接著,它會組合這些部分進行多次比對,取最高分。在處理電商商品標(biāo)題、文章標(biāo)簽等富含冗余信息場景時比較有效。
from fuzzywuzzy import fuzz title1 = "【旗艦店】Apple iPhone 15 Pro Max 256G 黑色" title2 = "iPhone15 Pro Max 256GB 手機 黑色" print(fuzz.token_set_ratio(title1, title2)) # 73
核心局部比對 partial_token_set_ratio()
當(dāng)然,同排序比對一樣,如果兩者有額外的干擾項,也會影響最終的得分。
所以還有變體 partial_set_sort_ratio(),核心部分再進行局部比對,就能避免額外項的干擾了
from fuzzywuzzy import fuzz title1 = "【旗艦店】Apple iPhone 15 Pro Max 256G 黑色" title2 = "iPhone15 Pro Max 256GB 手機 黑色" print(fuzz.token_set_ratio(title1, title2)) # 73 print(fuzz.partial_token_set_ratio(title1, title2)) # 100
process
extractOne()
傳給它一個查詢詞和一個候選列表,它會默默幫你把每個候選都比一遍,然后把得分最高的那位和它的分?jǐn)?shù)打包送回來。默認(rèn)的 full_process 預(yù)處理器會幫你做小寫轉(zhuǎn)換、去標(biāo)點等清洗工作。
from fuzzywuzzy import process
choices = [
"Apple iPhone 14 Pro",
"iPhone 14 Plus",
"Samsung Galaxy S23",
"Google Pixel 7",
]
query = "iphone 14 pro"
best_match, score = process.extractOne(query, choices)
print(f"最佳匹配: {best_match}, 得分: {score}")
# 輸出: 最佳匹配: Apple iPhone 14 Pro, 得分: 95extract()
提取最好的幾個,默認(rèn)是 5 個,會將最佳匹配的幾個候選和得分返回來。
from fuzzywuzzy import process
choices = [
"Apple iPhone 14 Pro",
"iPhone 14 Plus",
"Samsung Galaxy S23",
"Google Pixel 7",
]
query = "iphone 14 pro"
bests_match = process.extract(query, choices, limit=3)
for match, score in bests_match:
print(f"匹配:'{match}',得分:{score}")
# 匹配:'Apple iPhone 14 Pro',得分:95
# 匹配:'iPhone 14 Plus',得分:81
# 匹配:'Google Pixel 7',得分:35extractBests()
目前來看和 extract() 差別不大,唯一的區(qū)別是可以設(shè)置 score_cutoff 的閾值,使得只返回得分高于閾值的選項。
from fuzzywuzzy import process
choices = [
"Apple iPhone 14 Pro",
"iPhone 14 Plus",
"Samsung Galaxy S23",
"Google Pixel 7",
]
query = "iphone 14 pro"
bests_match = process.extractBests(query, choices, limit=3, score_cutoff=80)
for match, score in bests_match:
print(f"匹配:'{match}',得分:{score}")
# 匹配:'Apple iPhone 14 Pro',得分:95
# 匹配:'iPhone 14 Plus',得分:81extractWithoutOrder
這個就是上面 extractOne()、extract()、extractBests() 內(nèi)部所調(diào)用的函數(shù),就是按照原始的輸入順序(不會按照評分進行排序)返回每個可選項及其評分。
from fuzzywuzzy import process
choices = [
"Apple iPhone 14 Pro",
"iPhone 14 Plus",
"Samsung Galaxy S23",
"Google Pixel 7",
]
query = "iphone 14 pro"
bests_match = process.extractWithoutOrder(query, choices)
for match, score in bests_match:
print(f"匹配:'{match}',得分:{score}")
# 匹配:'Apple iPhone 14 Pro',得分:95
# 匹配:'iPhone 14 Plus',得分:81
# 匹配:'Samsung Galaxy S23',得分:19
# 匹配:'Google Pixel 7',得分:35到此這篇關(guān)于Python 中 fuzzywuzzy 進行字符串模糊匹配的全過程的文章就介紹到這了,更多相關(guān)Python fuzzywuzzy 字符串模糊匹配內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
django基礎(chǔ)學(xué)習(xí)之send_mail功能
這篇文章主要給大家介紹了關(guān)于django基礎(chǔ)學(xué)習(xí)之send_mail功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用django具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
Python?內(nèi)置模塊?argparse快速入門教程
argparse模塊是Python內(nèi)置的用于命令項選項與參數(shù)解析的模塊,argparse模塊可以讓人輕松編寫用戶友好的命令行接口,能夠幫助程序員為模型定義參數(shù),這篇文章主要介紹了快速入門Python內(nèi)置模塊argparse,需要的朋友可以參考下2023-06-06
python 動態(tài)生成變量名以及動態(tài)獲取變量的變量名方法
今天小編就為大家分享一篇python 動態(tài)生成變量名以及動態(tài)獲取變量的變量名方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-01-01
Python實現(xiàn)將內(nèi)容寫入文件的五種方法總結(jié)
本篇帶你詳細(xì)看一下python將內(nèi)容寫入文件的方法以及細(xì)節(jié),主要包括write()方法、writelines()?方法、print()?函數(shù)、使用?csv?模塊、使用?json?模塊,需要的可以參考一下2023-04-04
用python實現(xiàn)的可以拷貝或剪切一個文件列表中的所有文件
python 實現(xiàn)剪切或是拷貝一個文件列表中的所有文件2009-04-04

