欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

文本关键字替换: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)

生成的文本内容和关键词如下图所示:

文本关键词替换:Python中re与flashtext的对比(一)_flashtext

文本关键词替换:Python中re与flashtext的对比(一)_文本关键词替换_02

三、对比

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)  # 使用正则表达式替换

替换效果:

文本关键词替换:Python中re与flashtext的对比(一)_文本关键词替换_03

可以看到,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替换

替换效果:

文本关键词替换:Python中re与flashtext的对比(一)_re_04

flashtext在替换关键词时方法更加简单明了,并且成功替换了英文大小写关键词

四、结语

上面的对比只测试了关键词数量较少(56个)的情况,在准备测试文本和关键词时,定义了range_num(循环次数),是为了测试不同关键词数量对两种方法替换耗时的影响。那么在下一篇文章中,我们就来尝试绘制关键词数量-耗时的对比图。