快速生成定制化的Word文档:Python实践指南

简介: 1.1. 前言 众所周知, 安服工程师 又叫做 Word工程师 ,在打工或者批量SRC的时候,如果产出很多,又需要一个一个的写报告的情况下会非常的折磨人,因此查了一些相关的资料,发现使用python的 docxtpl 库批量写报告效果很不错,记录一下。 1.2. 介绍 docxtpl 是一个用于生成 Microsoft Word 文档的模板引擎库,它结合了 docx

1.1. 前言

众所周知,安服工程师又叫做Word工程师,在打工或者批量SRC的时候,如果产出很多,又需要一个一个的写报告的情况下会非常的折磨人,因此查了一些相关的资料,发现使用python的docxtpl库批量写报告效果很不错,记录一下。

1.2. 介绍

docxtpl 是一个用于生成 Microsoft Word 文档的模板引擎库,它结合了 docx 模块和 Jinja2 模板引擎,使用户能够使用 Microsoft Word 模板文件并在其中填充动态数据。它提供了一种方便的方式来生成个性化的 Word 文档,并支持条件语句、循环语句和变量等控制结构,以满足不同的文档生成需求。

官方GitHub地址:https://github.com/elapouya/python-docx-template

官方文档地址:https://docxtpl.readthedocs.io/en/latest/

简单来说:就是创建一个类似Jinja2语法的模板文档,然后往里面动态填充内容就可以了

安装:

pip3 install docxtpl

1.3. 基础使用

from docxtpl import DocxTemplate

doc = DocxTemplate("test.docx")
context = {'whoami': "d4m1ts"}
doc.render(context)
doc.save("generated_doc.docx")

其中,test.docx内容如下:

test.docx

生成后的结果如下:

gen

1.4. 案例介绍

1.4.1. 需求假设

写一份不考虑美观的漏扫报告,需要有统计结果图和漏洞详情,每个漏洞包括漏洞名、漏洞地址、漏洞等级、漏洞危害、复现过程、修复建议六个部分。

1.4.2. 模板文档准备

编写的模板文档如下,使用到了常见的iffor赋值等,保存为template.docx,后续只需要向里面填充数据即可。

template

1.4.3. 数据结构分析

传入数据需要一串json字符串,因此我们根据模板文档梳理好json结构,然后传入即可。

梳理好的数据结构如下:

{
  "饼图": "111",
  "柱状图": "222",
  "漏洞简报": [
    {
      "漏洞名": "测试漏洞名1",
      "漏洞等级": "高危"
    }
  ],
  "漏洞详情": [
    {
      "漏洞名": "测试漏洞名1",
      "漏洞地址": "http://blog.gm7.org/",
      "漏洞等级": "高危",
      "漏洞危害": "危害XXX",
      "复现过程": "先xxx,再xxx,最后xxx",
      "修复建议": "更新到最新版本即可"
    }
  ]
}

编写代码测试一下可行性:

from docxtpl import DocxTemplate

doc = DocxTemplate("template.docx")
context = {
      "饼图": "111",
      "柱状图": "222",
      "漏洞简报": [
        {
          "漏洞名": "测试漏洞名1",
          "漏洞等级": "高危"
        },
        {
          "漏洞名": "测试漏洞名2",
          "漏洞等级": "严重"
        },
        {
          "漏洞名": "测试漏洞名2",
          "漏洞等级": "中危"
        }
      ],
      "漏洞详情": [
        {
          "漏洞名": "测试漏洞名1",
          "漏洞地址": "http://blog.gm7.org/",
          "漏洞等级": "高危",
          "漏洞危害": "危害XXX",
          "复现过程": "先xxx,再xxx,最后xxx",
          "修复建议": "更新到最新版本即可"
        },
        {
          "漏洞名": "测试漏洞名2",
          "漏洞地址": "http://bblog.gm7.org/",
          "漏洞等级": "严重",
          "漏洞危害": "危害XXX",
          "复现过程": "先xxx,再xxx,最后xxx",
          "修复建议": "更新到最新版本即可"
        },
        {
          "漏洞名": "测试漏洞名3",
          "漏洞地址": "http://cblog.gm7.org/",
          "漏洞等级": "中危",
          "漏洞危害": "危害XXX",
          "复现过程": "先xxx,再xxx,最后xxx",
          "修复建议": "更新到最新版本即可"
        }
      ]
    }

doc.render(context)
doc.save("generated_doc.docx")

很好,达到了预期的效果。

res

1.4.4. 加入图表

在上面的过程中,内容几乎是没问题了,但是图表还是没有展示出来。生成图表我们使用plotly这个库,并将生成内容写入ByteIO

相关代码如下:

import plotly.graph_objects as go
from io import BytesIO

def generatePieChart(title: str, labels: list, values: list, colors: list):
    """
    生成饼图
    https://juejin.cn/post/6911701157647745031#heading-3
    https://juejin.cn/post/6950460207860449317#heading-5

    :param title: 饼图标题
    :param labels: 饼图标签
    :param values:  饼图数据
    :param colors:  饼图每块的颜色
    :return:
    """
    # 基础饼图
    fig = go.Figure(data=[go.Pie(
        labels=labels,
        values=values,
        hole=.4,  # 中心环大小
        insidetextorientation="horizontal"
    )])
    # 更新颜色
    fig.update_traces(
        textposition='inside',  # 文本显示位置
        hoverinfo='label+percent',  # 悬停信息
        textinfo='label+percent', # 饼图中显示的信息
        textfont_size=15,
        marker=dict(colors=colors)
    )
    # 更新标题
    fig.update_layout(
        title={   # 设置整个标题的名称和位置
            "text": title,
            "y": 0.96,  # y轴数值
            "x": 0.5,  # x轴数值
            "xanchor": "center",  # x、y轴相对位置
            "yanchor": "top"
        }
    )
    image_io = BytesIO()
    fig.write_image(image_io, format="png")
    return image_io


def generateBarChart(title: str, x: list, y: list):
    """
    生成柱状图
    https://cloud.tencent.com/developer/article/1817208
    https://blog.csdn.net/qq_25443541/article/details/115999537
    https://blog.csdn.net/weixin_45826022/article/details/122912484

    :param title: 标题
    :param x: 柱状图标签
    :param y:  柱状图数据
    :return:
    """
    # x轴长度最为18
    b = x
    x = []
    for i in b:
        if len(i) >= 18:
            x.append(f"{i[:15]}...")
        else:
            x.append(i)

    # 基础柱状图
    fig = go.Figure(data=[go.Bar(
        x=x,
        y=y,
        text=y,
        textposition="outside",
        marker=dict(color=["#3498DB"] * len(y)),
        width=0.3
    )])
    # 更新标题
    fig.update_layout(
        title={  # 设置整个标题的名称和位置
            "text": title,
            "y": 0.96,  # y轴数值
            "x": 0.5,  # x轴数值
            "xanchor": "center",  # x、y轴相对位置
            "yanchor": "top"
        },
        xaxis_tickangle=-45,  # 倾斜45度
        plot_bgcolor='rgba(0,0,0,0)'  # 背景透明
    )
    fig.update_xaxes(
        showgrid=False
    )
    fig.update_yaxes(
        zeroline=True,
        zerolinecolor="#17202A",
        zerolinewidth=1,
        showgrid=True,
        gridcolor="#17202A",
        showline=True
    )

    image_io = BytesIO()
    fig.write_image(image_io, format="png")
    return image_io

1.4.5. 最终结果

要插入图片内容,代码语法如下:

myimage = InlineImage(tpl, image_descriptor='test_files/python_logo.png', width=Mm(20), height=Mm(10))

完整代码如下:

from docxtpl import DocxTemplate, InlineImage
from docx.shared import Mm
import plotly.graph_objects as go
from io import BytesIO


def generatePieChart(title: str, labels: list, values: list, colors: list):
    """
    生成饼图
    https://juejin.cn/post/6911701157647745031#heading-3
    https://juejin.cn/post/6950460207860449317#heading-5

    :param title: 饼图标题
    :param labels: 饼图标签
    :param values:  饼图数据
    :param colors:  饼图每块的颜色
    :return:
    """
    # 基础饼图
    fig = go.Figure(data=[go.Pie(
        labels=labels,
        values=values,
        hole=.4,  # 中心环大小
        insidetextorientation="horizontal"
    )])
    # 更新颜色
    fig.update_traces(
        textposition='inside',  # 文本显示位置
        hoverinfo='label+percent',  # 悬停信息
        textinfo='label+percent',  # 饼图中显示的信息
        textfont_size=15,
        marker=dict(colors=colors)
    )
    # 更新标题
    fig.update_layout(
        title={  # 设置整个标题的名称和位置
            "text": title,
            "y": 0.96,  # y轴数值
            "x": 0.5,  # x轴数值
            "xanchor": "center",  # x、y轴相对位置
            "yanchor": "top"
        }
    )
    image_io = BytesIO()
    fig.write_image(image_io, format="png")
    return image_io


def generateBarChart(title: str, x: list, y: list):
    """
    生成柱状图
    https://cloud.tencent.com/developer/article/1817208
    https://blog.csdn.net/qq_25443541/article/details/115999537
    https://blog.csdn.net/weixin_45826022/article/details/122912484

    :param title: 标题
    :param x: 柱状图标签
    :param y:  柱状图数据
    :return:
    """
    # x轴长度最为18
    b = x
    x = []
    for i in b:
        if len(i) >= 18:
            x.append(f"{i[:15]}...")
        else:
            x.append(i)

    # 基础柱状图
    fig = go.Figure(data=[go.Bar(
        x=x,
        y=y,
        text=y,
        textposition="outside",
        marker=dict(color=["#3498DB"] * len(y)),
        width=0.3
    )])
    # 更新标题
    fig.update_layout(
        title={  # 设置整个标题的名称和位置
            "text": title,
            "y": 0.96,  # y轴数值
            "x": 0.5,  # x轴数值
            "xanchor": "center",  # x、y轴相对位置
            "yanchor": "top"
        },
        xaxis_tickangle=-45,  # 倾斜45度
        plot_bgcolor='rgba(0,0,0,0)'  # 背景透明
    )
    fig.update_xaxes(
        showgrid=False
    )
    fig.update_yaxes(
        zeroline=True,
        zerolinecolor="#17202A",
        zerolinewidth=1,
        showgrid=True,
        gridcolor="#17202A",
        showline=True
    )

    image_io = BytesIO()
    fig.write_image(image_io, format="png")
    return image_io


doc = DocxTemplate("template.docx")
context = {
    "饼图": InlineImage(doc, image_descriptor=generatePieChart(
        title="漏洞数量",
        labels=["严重", "高危", "中危", "低危"],
        values=[1, 1, 1, 0],
        colors=["#8B0000", "red", "orange", "aqua"]
    ), width=Mm(130)),
    "柱状图": InlineImage(doc, image_descriptor=generateBarChart(
        title="漏洞类型",
        x=["测试漏洞名1", "测试漏洞名2", "测试漏洞名3"],
        y=[1, 1, 1]
    ), width=Mm(130)),
    "漏洞简报": [
        {
            "漏洞名": "测试漏洞名1",
            "漏洞等级": "高危"
        },
        {
            "漏洞名": "测试漏洞名2",
            "漏洞等级": "严重"
        },
        {
            "漏洞名": "测试漏洞名2",
            "漏洞等级": "中危"
        }
    ],
    "漏洞详情": [
        {
            "漏洞名": "测试漏洞名1",
            "漏洞地址": "http://blog.gm7.org/",
            "漏洞等级": "高危",
            "漏洞危害": "危害XXX",
            "复现过程": "先xxx,再xxx,最后xxx",
            "修复建议": "更新到最新版本即可"
        },
        {
            "漏洞名": "测试漏洞名2",
            "漏洞地址": "http://bblog.gm7.org/",
            "漏洞等级": "严重",
            "漏洞危害": "危害XXX",
            "复现过程": "先xxx,再xxx,最后xxx",
            "修复建议": "更新到最新版本即可"
        },
        {
            "漏洞名": "测试漏洞名3",
            "漏洞地址": "http://cblog.gm7.org/",
            "漏洞等级": "中危",
            "漏洞危害": "危害XXX",
            "复现过程": "先xxx,再xxx,最后xxx",
            "修复建议": "更新到最新版本即可"
        }
    ]
}

doc.render(context)
doc.save("generated_doc.docx")

结果如下:

result

目录
相关文章
|
2月前
|
XML 数据格式 Python
从手动编辑到代码生成:Python 助你高效创建 Word 文档
本文介绍如何用Python实现Word文档自动化生成,结合python-docx、openpyxl和matplotlib库,高效完成报告撰写、数据插入与图表生成,大幅提升办公效率,降低格式错误,实现数据驱动的文档管理。
481 2
|
5月前
|
设计模式 SQL 人工智能
Python设计模式:从代码复用到系统架构的实践指南
本文以Python为实现语言,深入解析23种经典设计模式的核心思想与实战技巧。通过真实项目案例,展示设计模式在软件开发中的结构化思维价值,涵盖创建型、结构型、行为型三大类别,并结合Python动态语言特性,探讨模式的最佳应用场景与实现方式,帮助开发者写出更清晰、易维护的高质量代码。
234 1
|
4月前
|
安全 JavaScript 开发者
Python 自动化办公神器|一键转换所有文档为 PDF
本文介绍一个自动化批量将 Word、Excel、PPT、TXT、HTML 及图片转换为 PDF 的 Python 脚本。支持多格式识别、错误处理与日志记录,适用于文档归档、报告整理等场景,大幅提升办公效率。仅限 Windows 平台,需安装 Office 及相关依赖。
229 0
|
5月前
|
设计模式 人工智能 算法
Python设计模式:从代码复用到系统架构的实践指南
本文探讨了电商系统中因支付方式扩展导致代码臃肿的问题,引出设计模式作为解决方案。通过工厂模式、策略模式、单例模式等经典设计,实现代码解耦与系统扩展性提升。结合Python语言特性,展示了模块化、装饰器、适配器等模式的实战应用,并延伸至AI时代的设计创新,帮助开发者构建高内聚、低耦合、易维护的软件系统。
337 0
|
6月前
|
监控 大数据 API
Python 技术员实践指南:从项目落地到技术优化
本内容涵盖Python开发的实战项目、技术攻关与工程化实践,包括自动化脚本(日志分析系统)和Web后端(轻量化API服务)两大项目类型。通过使用正则表达式、Flask框架等技术,解决日志分析效率低与API服务性能优化等问题。同时深入探讨内存泄漏排查、CPU瓶颈优化,并提供团队协作规范与代码审查流程。延伸至AI、大数据及DevOps领域,如商品推荐系统、PySpark数据处理和Airflow任务编排,助力开发者全面提升从编码到架构的能力,积累高并发与大数据场景下的实战经验。
Python 技术员实践指南:从项目落地到技术优化
|
5月前
|
XML Linux 区块链
Python提取Word表格数据教程(含.doc/.docx)
本文介绍了使用LibreOffice和python-docx库处理DOC文档表格的方法。首先需安装LibreOffice进行DOC到DOCX的格式转换,然后通过python-docx读取和修改表格数据。文中提供了详细的代码示例,包括格式转换函数、表格读取函数以及修改保存功能。该方法适用于Windows和Linux系统,解决了老旧DOC格式文档的处理难题,为需要处理历史文档的用户提供了实用解决方案。
503 1
|
4月前
|
监控 Linux 数据安全/隐私保护
Python实现Word转PDF全攻略:从入门到实战
在数字化办公中,Python实现Word转PDF自动化,可大幅提升处理效率,解决格式兼容问题。本文详解五种主流方案,包括跨平台的docx2pdf、Windows原生的pywin32、服务器部署首选的LibreOffice命令行、企业级的Aspose.Words,以及轻量级的python-docx+pdfkit组合。每种方案均提供核心代码与适用场景,并涵盖中文字体处理、表格优化、批量进度监控等实用技巧,助力高效办公自动化。
1113 0
|
5月前
|
Python
Python 办公实战:用 python-docx 自动生成 Word 文档
本文详解如何使用 python-docx 库实现 Word 文档自动化生成,涵盖环境搭建、文档创建、格式设置、表格与图片处理、模板填充、批量生成及性能优化等实战技巧,助你高效完成办公场景中的文档自动化任务。
1409 1
|
3月前
|
数据采集 机器学习/深度学习 人工智能
Python:现代编程的首选语言
Python:现代编程的首选语言
309 102
|
3月前
|
数据采集 机器学习/深度学习 算法框架/工具
Python:现代编程的瑞士军刀
Python:现代编程的瑞士军刀
338 104

推荐镜像

更多