标书商务卷文件中会包含大量的图片,例如人员资料、资质信息等敏感材料,这些图片通常是由多方来源集成到一个word文件中,所以无法在生成word前对图片统一进行批量水印,幸运的是通过对docx文件解析再配合python的Pillow组件,可以实现对word内图片进行批量水印,下面记录实现过程

思路

在开始之前做过以下尝试:

  • 使用word内置页面水印功能,word只能对页面加水印而无法覆盖图片,而且原图可以直接拷贝出来,效果不理想

  • 使用WPS自带图片水印功能,这个功能很接近需求,但水印后的图片分辨率会被压缩,而且处理速度很慢,效率不理想

最终采用了下面的思路:

  • 将docx文件解包,获取文档内所有图片附件

  • 使用python脚本对目录图片进行水印

  • 替换原图,重新打包docx文件

实现步骤

  • 将docx文件更改后缀为zip或rar,然后解压至本地目录

  • 解压后进入图片路径合同案例\word\media

  • 将media目录拷贝到python项目目录,然后开始创建脚本文件

  • 在开始之前需要安装一下Pillow组件,版本要求不得大于10.0

    pip install Pillow==9.5.0
  • 脚本内容如下:

    from PIL import Image, ImageDraw, ImageFont
    import os
    def add_watermark(input_dir, output_dir, watermark_text):
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
    ​
        # 加载字体
        font_path = "C:/Windows/Fonts/simsun.ttc"
        font_size = 36
        font = ImageFont.truetype(font_path, font_size)
    ​
        for filename in os.listdir(input_dir):
            if filename.endswith(('.png', '.jpg', '.jpeg')):
                input_image_path = os.path.join(input_dir, filename)
                output_image_path = os.path.join(output_dir, filename)
    ​
                image = Image.open(input_image_path)
                draw = ImageDraw.Draw(image)
    ​
                # 计算水印大小和位置
                text_width, text_height = draw.textsize(watermark_text, font=font)
                width, height = image.size
                x = (width - text_width) / 2
                # 高度根据水印长度适当调整
                y = (width - text_width) / 4
    ​
                # 添加水印
                rotated_text = Image.new('RGBA', (text_width, text_height), (255, 255, 255, 0))
                rotated_draw = ImageDraw.Draw(rotated_text)
                # 水印颜色
                rotated_draw.text((0, 0), watermark_text, fill=(60, 60, 60, 128), font=font)
                rotated_text = rotated_text.rotate(45, expand=True)
                image.paste(rotated_text, (int(x), int(y)), rotated_text)
    ​
                # 保存图片
                image.save(output_image_path)
    ​
    ​
    if __name__ == "__main__":
        input_dir = "media"  # 输入图片目录
        output_dir = "marked"  # 输出图片目录
        watermark_text = "我是水印文本"
    ​
        add_watermark(input_dir, output_dir, watermark_text)
  • 确保media目录和脚本处在同级目录即可执行脚本,脚本执行完毕后,会在当前路径生成marked目录,里面存放已加水印的同名图片文件,可打开图片查看效果

  • 水印添加完成后,将水印图片覆盖至合同案例\word\media目录

  • 然后进入合同案例,全选目录下所有文件进行打包,打包格式选择zip,压缩方式选择存储,开始打包

  • 打包完成后,将zip包后缀改回docx,然后使用word打开即可。