当前位置:科学 > 正文

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

2023-05-16 15:02:34  来源:初始安全

前言

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

介绍

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


(资料图片)

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

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

安装:

pip3 install docxtpl

基础使用

from docxtpl import DocxTemplatedoc = DocxTemplate("test.docx")context = {"whoami": "d4m1ts"}doc.render(context)doc.save("generated_doc.docx")

其中,test.docx内容如下:

生成后的结果如下:

案例介绍

需求假设

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

模板文档准备

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

template


数据结构分析

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

梳理好的数据结构如下:

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

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

from docxtpl import DocxTemplatedoc = 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

加入图表

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

相关代码如下:

import plotly.graph_objects as gofrom io import BytesIOdef 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_iodef 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

最终结果

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

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

完整代码如下:

from docxtpl import DocxTemplate, InlineImagefrom docx.shared import Mmimport plotly.graph_objects as gofrom io import BytesIOdef 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_iodef 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_iodoc = 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


- END -

关键词:

推荐阅读

世界最贵房车有哪些 福特F550房车怎么样?

世界最贵房车有哪些1 凯迪拉克凯雷德ESV XXXL超级加长房车如果你是那种需要一架空中喷气式飞机和一艘水上游艇的24 × 7大型忙碌者 【详细】

DART小行星任务已开始 有6次自我毁灭航天器介绍

DART小行星任务已开始斯科特·博尔顿曾与两艘飞船合作,这两艘飞船以确保陆地微生物永远无法在太阳系外站稳脚跟的名义自我毁灭。冒着最恶劣 【详细】

十大日系车排名 日系车有怎样的优缺点?

十大日系车排名雷克萨斯UX雷克萨斯UX,官方宣称为紧凑型SUV,但实际上它只是一款小型SUV。UX和C-HR都采用TNGA架构,因此具有很好的可操作性 【详细】

非晶硅薄膜电池的起源 非晶硅薄膜电池优点有哪些?

非晶硅薄膜电池的起源非晶硅薄膜太阳能电池由Carlson和Wronski于20世纪70年代中期成功开发,80年代生产达到高潮,约占全球太阳能电池总量的 【详细】

苹果官网回收旧手机 苹果手机回收注意事项

苹果官网回收旧手机现在很多地方都能回收手机,再生资源回收利用是可以的。苹果是一家非常强大的公司,苹果的手机在国内用户中非常受欢迎。 【详细】

关于我们  |  联系方式  |  免责条款  |  招聘信息  |  广告服务  |  帮助中心

联系我们:85 572 98@qq.com备案号:粤ICP备18023326号-40

科技资讯网 版权所有