Python如何统计列表中关键词在多个文本文件的出现次数及总频次
最优实现方案
核心思路
针对2万+关键词的多文本匹配统计场景,最优方案选择Aho-Corasick(AC)自动机作为多模式匹配核心,相比逐关键词遍历文本的方案,时间复杂度从O(关键词数量 * 所有文本总长度)降到O(关键词总长度 + 所有文本总长度 + 命中次数),效率提升可达几个数量级。
你需要统计两个核心结果:一是出现在≥2个不同文件中的关键词总数,二是这类关键词的全局总出现频次,整个流程无冗余计算。
具体实现步骤
- 第一步:预处理关键词与初始化统计容器
- 先对
KeywordList去重,避免重复关键词导致的统计误差 - 用去重后的关键词构建AC自动机,每个自动机节点关联对应的关键词,匹配命中时可直接定位
- 初始化两个统计字典:
file_hit_count记录每个关键词出现在多少个不同文件中,total_freq记录每个关键词的全局总出现次数
- 先对
- 第二步:逐文件处理统计
- 读取单个文本文件内容,做和关键词规则一致的标准化处理(比如统一转小写、去除特殊符号等)
- 用AC自动机扫描当前文本,统计该文件内每个关键词的命中次数
- 对当前文件命中的关键词,
file_hit_count对应值+1(同一文件内多次命中仅加1次);同时将该文件内的命中次数累加到total_freq对应字段 - 遍历完所有文本文件后进入结果汇总
- 第三步:结果汇总
- 统计
file_hit_count中值≥2的键的数量,即“在多个独立文本中出现的关键词总数” - 对所有
file_hit_count≥2的关键词,求和其对应的total_freq值,即这类关键词的全局总出现频次
- 统计
不同场景的简化实现
如果你的文本总大小≤1GB,不需要极致性能,可以用现有工具快速落地:
Python 快速实现
直接调用第三方库pyahocorasick,10行左右代码即可完成,示例代码:
import ahocorasick # 构建AC自动机 automaton = ahocorasick.Automaton() unique_kw = set(KeywordList) for idx, kw in enumerate(unique_kw): automaton.add_word(kw, (idx, kw)) automaton.make_automaton() file_hit_count = {} total_freq = {} # 遍历所有文本文件 for file_path in your_file_path_list: with open(file_path, 'r', encoding='utf-8') as f: # 按需修改标准化规则,这里以统一转小写为例 content = f.read().lower() current_file_hit = {} # 扫描文本获取所有命中结果 for end_pos, (idx, kw) in automaton.iter(content): current_file_hit[kw] = current_file_hit.get(kw, 0) + 1 # 更新全局统计 for kw, cnt in current_file_hit.items(): file_hit_count[kw] = file_hit_count.get(kw, 0) + 1 total_freq[kw] = total_freq.get(kw, 0) + cnt # 计算最终结果 multi_file_kw_num = sum(1 for v in file_hit_count.values() if v >= 2) multi_file_total_freq = sum(v for k, v in total_freq.items() if file_hit_count[k] >= 2)
命令行快速实现(Linux环境)
临时处理不需要写代码的场景,可直接用grep+awk组合实现:
- 把去重后的关键词每行一个存为
pattern.txt - 执行命令输出所有命中结果再做统计:
grep -r -o -f pattern.txt 你的文本目录路径 | awk -F: '{print $1"\t"$2}' | awk '{a[$2]++;b[$2]++}END{for(k in a)if(a[k]>=2)print k,b[k]}'
性能优化注意点
- 大小写不敏感的需求统一在预处理阶段完成,不要在匹配过程中做大小写判断,会大幅降低性能
- 单文本文件过大时不要一次性读入内存,按块/按行读入即可,AC自动机支持流式匹配
- 关键词存在包含关系(比如“北京”和“北京海淀”)时,提前明确匹配规则是最长匹配还是全匹配,避免统计误差
内容的提问来源于stack exchange,提问作者goonercoder
相关产品推荐
相关产品推荐

