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

