在处理文本匹配时,正则表达式这类 “硬匹配” 方式,面对拼写错误、细微差异容易失效。而 Python 中的 difflib 库,能很好地弥补这一短板,实现更贴合实际场景的模糊查询,比如处理用户输入难免出错的搜索需求。
正则表达式(Regex)在文本匹配中常用,但面对拼写错误时很 “脆弱”。例如想匹配 “iPhone 16 Pro Max”,若查询词是 “iphone 16 prro max”(“max” 错写为 “mmax” ),正则因严格字符匹配,无法识别,最终无结果返回,如下代码示例:
import re
products = ["iPhone 16 Pro Max", "vivo", "xaiomi"]
query = "iphone 16 pro mmax" # 存在拼写错误
pattern = re.compile(query, re.IGNORECASE)
matches = [p for p in products if pattern.search(p)]
print(matches) # 输出 []difflib 里的 SequenceMatcher 是关键工具,通过计算序列相似度,判断文本间的相似程度示例:
from difflib import SequenceMatcher
def fuzzy_match(query, products, threshold=0.6):
matches = []
for product in products:
# 统一转小写,避免大小写干扰匹配
ratio = SequenceMatcher(None, query.lower(), product.lower()).ratio()
if ratio >= threshold: # 设定阈值,过滤相似度低的结果
matches.append((product, f"{ratio:.2f}"))
return matches
query = "iphone 16 pro mmax"
products = ["iPhone 16 Pro Max", "vivo", "xaiomi"]
print(fuzzy_match(query, products))
# 输出 [('iPhone 16 Pro Max', '0.88')],匹配成功 ratio() 返回 0 - 1 的值,值越接近 1 代表越相似
SequenceMatcher 还有 quick_ratio() 方法,计算速度更快(精度稍降)。若处理几万条商品名等大数据量场景,用 quick_ratio 可提升效率,示例:
ratio = SequenceMatcher(None, query.lower(), product.lower()).quick_ratio()商品名里的品牌、型号(如 iPhone 14 )比后缀(Pro Max )更重要。可拆分字符串关键部分,给不同部分设权重,再结合 difflib 得分,让匹配更贴合业务,比如:
def weighted_fuzzy_match(query, products, threshold=0.6):
matches = []
for product in products:
# 拆分关键部分,假设按空格拆分,品牌、型号为前几个元素
query_parts = query.lower().split()
product_parts = product.lower().split()
# 给品牌、型号部分更高权重(这里简单示例,实际可更复杂)
weight = 1
iflen(query_parts) >= 2andlen(product_parts) >= 2:
if query_parts[0] == product_parts[0] and query_parts[1] == product_parts[1]:
weight = 2
ratio = SequenceMatcher(None, query.lower(), product.lower()).ratio() * weight
if ratio >= threshold * weight:
matches.append((product, f"{ratio:.2f}"))
return matches若文本含 emoji、外语字符(如 Samsung Galaxy S23 里的 Galaxy ),可先简单清洗(保留核心字符,去掉无意义符号),再用 difflib 匹配,避免特殊字符干扰,示例(简单清洗特殊字符):
import re
defclean_text(text):
# 保留字母、数字、空格,去掉其他特殊字符
return re.sub(r'[^\w\s]', '', text)
deffuzzy_match_with_clean(query, products, threshold=0.6):
cleaned_query = clean_text(query)
matches = []
for product in products:
cleaned_product = clean_text(product)
ratio = SequenceMatcher(None, cleaned_query.lower(), cleaned_product.lower()).ratio()
if ratio >= threshold:
matches.append((product, f"{ratio:.2f}"))
return matchesdifflib 无需额外安装,轻量够用,日常简单模糊匹配需求,用它就很合适。
#Python #Python模糊匹配