python-docx批量插入图片——优化版

1、图片插入位置判断优化

写了图片插入脚本后,想着每个图片都遍历一次word,有的项目测试场景多,那插入对比会变很慢。
自动化报告神器:python-docx批量插入图片,性能测试报告秒成

1.1、原始方案

  在原始方案中:每一张图片,都去遍历word段落。先文本对比场景描述,找到了为True,开始对比并发数,为True后开始对比性能指标,最后插入图片。
  问题是,如果段落过多,图片过多。后面的图片,对比次数越来越多,对比时间就会越来越长。
在这里插入图片描述

def insert_image(image_paths, doc, count):
    """
    遍历图片路径列表,根据图片信息,判断插入位置,插入图片到文档
    :param image_paths: 图片路径
    :param doc: 打开的word文档
    :param count: 成功图片数
    :return count: 成功图片数
    """
    for image_path in image_paths:
        scene_description, concurrency, metric = get_image_info(image_path)
        scene_description_flag = False  # 关键词标记,辅助定位图片插入位置
        concurrency_flag = False
        # 遍历文档中的所有段落
        for paragraph in doc.paragraphs[100:]:  # 切片,去除目录等
            # p = paragraph.text
            if scene_description in paragraph.text:
                scene_description_flag = True
            elif scene_description_flag and concurrency in paragraph.text:
                concurrency_flag = True
            elif concurrency_flag and metric in paragraph.text:
                run = paragraph.add_run()  # 创建一个新的Run对象并添加到当前段落
                run.add_break()  # 添加一个换行符
                run.add_picture(image_path, width=Inches(5.5))  # 在当前Run中插入图, 设置宽高, height=Inches(3.0)3.0英寸
                # print(f"{image_path}插入成功")
                count += 1
                scene_description_flag = False  # 关键词标记,辅助定位图片插入位置
                concurrency_flag = False
    return count

1.2、优化想法

  先处理图片路径列表,转换成路径字典:{场景描述:{并发数:{性能指标:路径}}}

def get_image_keys(image_paths):
    """
    预处理图片路径信息,列表转换字典
    :param image_paths: 图片路径列表
    :return: 路径字典:{场景描述:{并发数:{性能指标:路径}}}
    """
    image_keys = {}
    for image_path in image_paths:
        scene_description, concurrency, metric = get_image_info(image_path)
        # 检查是否需要创建新的字典层级
        if scene_description not in image_keys:
            image_keys[scene_description] = {}
        if concurrency not in image_keys[scene_description]:
            image_keys[scene_description][concurrency] = {}
        image_keys[scene_description][concurrency][metric] = image_path         # 保存文件路径到对应的位置
    return image_keys

示例如下:

scene_description = {
    "场景描述": {
        "50并发": {
            "事务响应时间": "交易处理模块/场景描述-50并发-事务响应时间.png",
            "每秒点击数": "交易处理模块/场景描述-50并发-每秒点击数.png",
            "TPS": "交易处理模块/场景描述-50并发-TPS.png"},
        "100并发": {
            "事务响应时间": "交易处理模块/场景描述-100并发-事务响应时间.png",
            "每秒点击数": "交易处理模块/场景描述-100并发-每秒点击数.png",
            "TPS": "交易处理模块/场景描述-100并发-TPS.png"}
    }
}

  遍历段落时,先将段落对比每一个‘场景描述’,为True后开始对比场景下的“并发数”,最后对比并发下的指标。插入图片,之后删除对应字典,减少后续判断次数。
在这里插入图片描述
  这样先通过字典,只需要遍历一次word段落,段落文本对比所有图片的‘场景描述’,再对比其下的并发,层层递减,对比数据会越来越少。而且成功插入会删除字典数据,也可以减少后面的对比次数。

def insert_image_two(image_paths, doc, count):
    """
    向已打开word,插入图片。优化版:通过预处理图片字典,遍历一次word段落,对比每个图片关键信息。减少了word遍历次数
    :param image_paths: 图片路径
    :param doc: 打开的word文档
    :param count: 成功图片数
    :return count: 成功图片数
    """
    image_keys = get_image_keys(image_paths)
    scene_description_flag = False  # 关键词标记,辅助定位图片插入位置
    concurrency_flag = False

    for paragraph in doc.paragraphs[100:]:  # 切片,去除目录等。遍历word's段落
        if not scene_description_flag:          # 场景描述
            for scene_description in image_keys.keys():
                if scene_description in paragraph.text:
                    scene_description_flag = True
                    break
        elif scene_description_flag and not concurrency_flag:   # 并发数
            for concurrency in image_keys[scene_description].keys():
                if concurrency in paragraph.text:
                    concurrency_flag = True
                    break
        elif concurrency_flag:                                  # 性能指标
            for metric in image_keys[scene_description][concurrency].keys():
                if metric in paragraph.text:
                    run = paragraph.add_run()  # 创建一个新的Run对象并添加到当前段落
                    run.add_break()  # 添加一个换行符
                    run.add_picture(image_keys[scene_description][concurrency][metric], width=Inches(5.5))  # 在当前
                    count += 1

                    del image_keys[scene_description][concurrency][metric]  # 删除已插入图片字典
                    if not image_keys[scene_description][concurrency]:
                        del image_keys[scene_description][concurrency]
                        concurrency_flag = False
                    if not image_keys[scene_description]:
                        del image_keys[scene_description]
                        scene_description_flag = False  # 关键词标记,辅助定位图片插入位置
                    break
    if count > 0 and image_keys:    # 输出未插入图片信息
        print("以下图片未插入:")
        for scene_description in image_keys.keys():
            for concurrency in image_keys[scene_description].keys():
                for metric in image_keys[scene_description][concurrency].keys():
                    print(f"\t{scene_description} {concurrency} {metric}")
    return count

2、优化结果

  1. 原始方案
    在这里插入图片描述

  2. 优化方案
    在这里插入图片描述

  两次图片插入都是已经改名后的图片,报告、图片等因素均一致。包含:5个场景 X 每场景4个并发 X 4个性能指标,共80张图片。时间减少一倍左右,优化方案是有效的。随着图片数增长,两个方案差距可能会进一步增大。完整代码看gitee

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

觅梦_feng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值