如何识别招聘场景近重复文本?有哪些适用的NLP去重方法?
招聘启事近重复文本去重方案与相关NLP技术
原有方案的核心缺陷
你当前使用的固定片段匹配方案准确率不足的核心原因如下:
- 固定截取350-550字符的逻辑鲁棒性极差:如果相似文本的前缀长度不同(比如你给出的示例2开头多了空行、少了「完整职位描述」字样),截取的片段会完全不匹配,导致漏判
- 完全匹配片段的规则容错率为0:哪怕相似文本里多了个标点、改了个别词汇(比如示例里的
Recycling改成Recyclage、句号改成分号)就会匹配失败 - 循环检索的时间复杂度极高:O(n²)的复杂度,数据量超过1万条就会出现明显卡顿
可用于近重复文本识别的NLP技术
目前工业界常用的近重复文本检测技术主要有以下几类:
- MinHash+LSH(局部敏感哈希):专门针对大规模文本近重复检测的经典方案,通过将文本转化为特征签名,仅需一次遍历就能把相似文本分到同一个桶里,时间复杂度接近O(n),是海量文本场景下的首选方案
- 语义向量相似度匹配:用轻量级预训练模型把文本转成固定长度的语义向量,计算余弦相似度,阈值超过0.85~0.9即可判定为近重复,对语序调整、局部增删内容的容错率极高,适合对准确率要求高的场景
- SimHash:谷歌用来检测网页近重复的经典算法,把文本的哈希值海明距离控制在3以内即可判定为重复,计算速度快,适合长文本场景
- 编辑距离/杰卡德相似度:针对短文本或差异极小的文本,计算两个文本的字符编辑距离或者分词后词集合的杰卡德相似度,超过阈值即判定为重复,缺点是长文本计算效率低,不适合大规模数据
更优的落地方案
你可以根据自己的数据量选择对应方案:
方案1:语义向量匹配(适合数据量<1万条,准确率最高)
先安装依赖:pip install text2vec pandas numpy
参考实现代码:
import pandas as pd import numpy as np from text2vec import SentenceModel, cos_sim # 加载轻量级中文语义模型 model = SentenceModel('shibing624/text2vec-base-chinese') data = pd.read_csv('你的招聘数据文件路径.csv') # 统一预处理文本:去掉多余空白、冗余的网页残留内容 def clean_text(text): text = str(text).strip().replace('\n', ' ').replace('\t', ' ') text = text.replace('展开更多', '').replace('收起更多', '') return text data['clean_text'] = data['originalText'].apply(clean_text) # 批量生成所有文本的语义向量 vecs = model.encode(data['clean_text'].tolist(), show_progress_bar=True) # 去重逻辑:保留每个相似簇的第一条数据 keep_idx = [] used = np.zeros(len(data), dtype=bool) similarity_threshold = 0.9 # 可根据实际效果调整,数值越高去重越宽松 for i in range(len(data)): if not used[i]: keep_idx.append(i) # 标记所有和当前文本相似度超过阈值的为重复项 sims = cos_sim(vecs[i], vecs).flatten().numpy() used[sims >= similarity_threshold] = True # 得到最终去重后的数据集 dedup_data = data.iloc[keep_idx].reset_index(drop=True)
方案2:MinHash+LSH(适合数据量>1万条,速度最快)
先安装依赖:pip install datasketch pandas jieba
参考实现代码:
import pandas as pd from datasketch import MinHash, MinHashLSH import jieba # 预处理文本并分词 def clean_and_tokenize(text): text = str(text).strip().replace('\n', ' ').replace('\t', ' ') text = text.replace('展开更多', '').replace('收起更多', '') return [w for w in jieba.lcut(text) if w.strip()] data['tokens'] = data['originalText'].apply(clean_and_tokenize) # 构建LSH索引 lsh = MinHashLSH(threshold=0.8, num_perm=128) minhashes = [] for idx, tokens in enumerate(data['tokens']): m = MinHash(num_perm=128) for t in tokens: m.update(t.encode('utf-8')) minhashes.append(m) lsh.insert(idx, m) # 去重逻辑 used = set() keep_idx = [] for i in range(len(data)): if i not in used: keep_idx.append(i) # 检索所有和当前文本相似的样本 duplicates = lsh.query(minhashes[i]) used.update(duplicates) dedup_data = data.iloc[keep_idx].reset_index(drop=True)
调优建议
- 相似度阈值可以根据业务需求调整:如果要严格去重就把阈值下调到0.85,要保留更多差异内容就把阈值上调到0.9以上
- 如果招聘文本里有大量通用的公司介绍、招聘声明等内容,可以在计算相似度前提前去掉这类通用段落,进一步提升识别准确率
- 你给出的两个示例文本,用上述两个方案计算的相似度都会超过0.9,会被判定为近重复,符合你的业务需求
内容的提问来源于stack exchange,提问作者user15649753
相关产品推荐
相关产品推荐

