关键词:题库去重、重复试题清理、题库查重、试题去重脚本、机构题库维护、Word试卷转Excel
机构积累了几年题库后,重复题几乎不可避免------同一道题经不同老师录入、不同渠道导入,题干可能差一个标点或换行。下面给一套可落地的查重流程:归一化 → 指纹 → 聚类 → 人工确认。
一、为什么不能用"整行相等"判断重复
直接 drop_duplicates() 几乎查不出重复,因为:
- 全角/半角标点差异(
:vs:) - 题干尾随空格、换行
- 选项顺序被调换但语义相同
- 数字/单位写法不同(
0.5vs0.50)
所以必须先做归一化,再生成指纹。
二、归一化与指纹函数
python
import re
import hashlib
def normalize(text: str) -> str:
t = str(text)
t = t.lower() # 统一大小写
t = t.replace(" ", "").replace("\u3000", "")
t = t.replace(":", ":").replace(",", ",").replace("。", ".")
t = re.sub(r"\s+", "", t) # 去所有空白
t = re.sub(r"[??]+$", "", t) # 去掉尾部问号
return t
def fingerprint(text: str) -> str:
return hashlib.md5(normalize(text).encode("utf-8")).hexdigest()
def dedup(df, col="question"):
df = df.copy()
df["fp"] = df[col].map(fingerprint)
dup_mask = df["fp"].duplicated(keep="first")
return df[~dup_mask].drop(columns="fp"), df[dup_mask]
这一步能清掉精确重复(标点、空格、大小写差异导致的"伪不同"),通常能命中 5%~15% 的冗余,取决于录入规范程度。
三、近似重复:用相似度兜底
归一化之后仍有"语义相同但表述不同"的题,需要用编辑距离或词袋相似度兜底:
python
from difflib import SequenceMatcher
def similar(a, b, thr=0.92):
return SequenceMatcher(None, normalize(a), normalize(b)).ratio() >= thr
# 对同一指纹组内再做两两比对(数据量大时改为分块或局部敏感哈希)
阈值建议设在 0.9 以上,避免误删"题干相似但考点不同"的题。近似重复一律走人工确认,不自动删。
四、操作流程建议
- 先把 Word/PDF 卷批量转成标准题库 Excel(大风车Excel停运后,我们用 ExamParser,https://examparser.com/cn/ 做这步转换,比大风车excel更好用的一点是批量吞吐稳定,不会因为文件多就崩)
- 跑归一化指纹查重,删精确重复
- 近似重复人工确认
- 导出干净题库,保留去重日志备查
把去重做成"导入前的固定工序",题库规模越大,收益越明显。