如何清理NLTK提取的重复及近似重复标题?求最优处理方案
处理提取标题中的重复与近似重复问题
问题场景
提取的标题存在完全重复、冗余前缀(RE:/FW:等)、拼写错误、附加无关后缀等近似重复问题,示例如下:
Daily Update (6/20) REDACTED.,
Daily Update (9/9).,
Daily Update (10/10).,
RE: General/ABC Update.
RE: General/ABC Update RELEASE IN PART BS.
General/ABC Update.
RE: General/ABC Article.
RE: General/ABC Articie.
Wrap Up for Friday, September 2017.,
Wrap Up for Monday, January 2018.,
Wrap Up for Monday, January 2018.
期望输出:
Daily Update (6/20) REDACTED.,
Daily Update (9/9).,
Daily Update (10/10).
General/ABC Article.
Wrap Up for Friday, September 2017.,
Wrap Up for Monday, January 2018.
解决方案
1. 预处理优化(减少后续匹配压力)
在提取阶段先清理冗余内容:
- 统一移除所有回复/转发前缀(RE:/FW:/Fwd:等,支持大小写及变体)
- 清理标题末尾多余标点
- 移除无关后缀标注(如
RELEASE IN PART BS这类附加内容)
2. 模糊匹配去重(解决近似重复)
用rapidfuzz(性能优于fuzzywuzzy)计算标题相似度,设定阈值(如85%),只保留首次出现的相似标题。
3. 精确去重(保留首条)
若仅需处理完全重复,直接遍历列表,保留首次出现的标题即可。
完整实现代码
from itertools import chain from nltk import sent_tokenize, word_tokenize from nltk.tokenize.treebank import TreebankWordDetokenizer import re from rapidfuzz import fuzz word_detokenize = TreebankWordDetokenizer().detokenize def preprocess_title(title): # 移除回复/转发前缀(支持大小写、变体) title = re.sub(r'^\s*(RE:|FW:|Fwd:|Re:|R\.E:)\s*', '', title, flags=re.IGNORECASE) # 清理末尾多余标点,统一为单个句号 title = re.sub(r'\.*$', '.', title.strip()) # 移除无关后缀标注(可根据实际情况调整正则) title = re.sub(r'\s+RELEASE IN PART.*$', '', title, flags=re.IGNORECASE) return title def fuzzy_deduplicate(titles, threshold=85): unique_titles = [] for title in titles: # 与已保留标题比对相似度,低于阈值则加入 is_duplicate = any(fuzz.ratio(title, existing) >= threshold for existing in unique_titles) if not is_duplicate: unique_titles.append(title) return unique_titles # 原标题提取逻辑 tokenized_text = [word_tokenize(sent) for sent in sent_tokenize(data1)] sent_idx_with_event = [idx for idx, sent in enumerate(tokenized_text) if 'Event' in sent or 'Subject' in sent] window = 1 list1 = [] for idx in sent_idx_with_event: start = max(idx - window, 1) end = min(idx+window, len(tokenized_text)) result = ' '.join(word_detokenize(sent) for sent in tokenized_text[start:end]) result = re.split("Subject:|Event:", result)[-1] # 加入预处理步骤 result = preprocess_title(result) list1.append(result) # 先模糊去重,若需完全去重可追加精确去重 unique_list = fuzzy_deduplicate(list1) # 精确去重(保留首条):unique_list = list(dict.fromkeys(unique_list)) # 输出处理后的标题 for title in unique_list: print(title)
说明
- 预处理正则可根据实际标题的冗余类型调整,适配更多场景。
- 模糊匹配阈值
threshold可灵活调整:阈值越高,去重越严格;越低,越容易合并近似标题。 - 若无需模糊匹配,仅做精确去重,直接用
list(dict.fromkeys(list1))即可保留首条完全重复的标题。
内容的提问来源于stack exchange,提问作者Aaron
相关产品推荐
相关产品推荐

