文本关键字替换:Python 中的 re 与 flashtext (I)
最编程
2024-10-15 14:26:34
...
一、背景
在处理文本数据时,替换关键词是一个常见的需求。Python中我们通常使用re模块中的正则表达式来实现这一功能。然而,最近我注意到一个名为flashtext的库,据其官方文档介绍,它同样可以实现文本关键词的高效替换。那么,这两种方法究竟有何不同呢?接下来,我们将通过实际操作来探索并简要对比re和flashtext在关键词替换方面的表现。
二、准备
首先我们需要准备测试用文本内容和需要替换的关键词。
为了更好地对比re和flashtext,这里准备了两类关键词:中文关键词和英文关键词,其中英文关键词区分了大小写
同样准备了目标关键词tg_en="nymph"(英文目标关键词),tg_ch="女神"(中文目标关键词)
也就是说需要把文本中所有的关键词替换为“nymph”或者“女神”
import random
def generate_test_data(filename, range_num):
"""
生成测试txt文档和关键词列表
"""
fruit_dict = {'apple': "苹果", 'banana': "香蕉", 'pear': "梨", 'grape': "葡萄", 'mango': "芒果", 'orange': "橘子",
'pineapple': "凤梨", 'peach': "桃子", 'cherry': "樱桃", 'loquat': "枇杷", 'watermelon': "西瓜",
'blueberry': "蓝莓", 'pomegranate': "石榴", 'litchi': "荔枝"} # 水果字典
k_list = [] # 关键词列表
num = 1 # 水果名称后缀初始值
with open(filename, 'w+', encoding='utf-8') as f: # 打开文件
for i in range(range_num): # 循环次数--生成len(fruit_dict)*循环次数条文本;关键词数量=len(fruit_dict)*循环次数*2
for k in fruit_dict: # 遍历水果字典
fruit_en = f"{random.choice([k, k.upper()])}{num}" # 英文水果名称
fruit_ch = f"{fruit_dict[k]}{num}" # 中文水果名称
s = f"Don't lose hope.You never know what tomorrow brings.Maybe it's your favorite {fruit_en}.\n" \
f"别灰心,谁又知道明天会有怎样的惊喜。也许会是你最喜欢的{fruit_ch}。\n" # 文本模板
f.writelines(s) # 写入文件
k_list.append(f"{k}{num}") # 添加英文关键词
k_list.append(fruit_ch) # 添加中文关键词
num += 1 # 名称后缀自加1
return k_list
if __name__ == "__main__":
file_path = 'test_content.txt' # 文件名称
kw = generate_test_data(file_path, 2) # 生成测试txt文档和关键词列表
print(kw)
生成的文本内容和关键词如下图所示:
三、对比
re方法
import re
def is_chinese_start_and_number_end(s):
"""
判断字符串是否以中文开头并且数字结尾
"""
return re.compile(r'^[\u4e00-\u9fa5]+\d+$').match(s) is not None
def multi_replace(text, keywords, target_en, target_ch):
"""
正则表达式替换多个关键字
"""
kw_dict = {i: target_ch if is_chinese_start_and_number_end(i) else target_en for i in keywords} # 组装为关键词字典
ptn = '|'.join(map(re.escape, kw_dict.keys())) # 拼接转义后的关键字,生成正则表达式
return re.sub(ptn, lambda m: kw_dict[m.group(0)], text) # 通过正则表达式替换
def re_replace(file, keywords, target_en, target_ch):
"""使用re替换"""
with open(file, 'r', encoding='utf-8') as f: # 打开文件,读取内容
content = f.read()
new_content = multi_replace(content, keywords, target_en, target_ch) # 替换关键字
with open('replaced_re.txt', 'w', encoding='utf-8') as f: # 将替换后的内容写入新文件
f.write(new_content)
if __name__ == "__main__":
file_path = 'test_content.txt' # 文件名称
kw = generate_test_data(file_path, 2) # 生成测试txt文档和关键词列表
tg_en = "nymph" # 英文目标关键词
tg_ch = "女神" # 中文目标关键词
re_replace(file_path, kw, tg_en, tg_ch) # 使用正则表达式替换
替换效果:
可以看到,re方法并未替换英文大写关键词,因为我们在生成正则表达式时只转义了小写的英文关键词
flashtext方法
import re
import flashtext as flashtext
def is_chinese_start_and_number_end(s):
"""
判断字符串是否以中文开头并且数字结尾
"""
return re.compile(r'^[\u4e00-\u9fa5]+\d+$').match(s) is not None
def flash_replace(file, keywords, target_en, target_ch):
"""
使用flash_text替换
"""
kp = flashtext.KeywordProcessor() # 创建KeywordProcessor对象
for v in keywords: # 添加关键词到KeywordProcessor对象中
if is_chinese_start_and_number_end(v): # 若关键字以中文开头并且数字结尾
kp.add_keyword(v, target_ch) # 添加中文关键词
else:
kp.add_keyword(v, target_en) # 添加英文关键词
with open(file, 'r', encoding='utf-8') as f: # 打开文件,读取内容
content = f.read()
new_content = kp.replace_keywords(content) # 替换关键词
with open('replaced_flash.txt', 'w', encoding='utf-8') as f: # 将替换后的内容写入新文件
f.write(new_content)
if __name__ == "__main__":
file_path = 'test_content.txt' # 文件名称
kw = generate_test_data(file_path, 2) # 生成测试txt文档和关键词列表
tg_en = "nymph" # 英文目标关键词
tg_ch = "女神" # 中文目标关键词
flash_replace(file_path, kw, tg_en, tg_ch) # 使用flashtext替换
替换效果:
flashtext在替换关键词时方法更加简单明了,并且成功替换了英文大小写关键词
四、结语
上面的对比只测试了关键词数量较少(56个)的情况,在准备测试文本和关键词时,定义了range_num(循环次数),是为了测试不同关键词数量对两种方法替换耗时的影响。那么在下一篇文章中,我们就来尝试绘制关键词数量-耗时的对比图。