使用Python为PDF文件批量添加水印的方法及进一步思考

感谢中国传媒大学胡凤国老师的分享!

============

问题描述:

想用Python把WORD文件转成PDF文件并加上水印。网上搜了一下资料,没发现有现成的解决方案。于是决定自己写一个Python程序。思路是分两步:第一步,将WORD文件转成PDF,第二步将生成的PDF文件添加水印。但是做的过程中出现了一些问题,解决的过程对我来说又十分困难,这里把我的思路、方法和经验教训总结一下,分享给需要的朋友。

系统环境:

32位Win7 + Python 3.6.4 + Office2010。

材料准备:

1、网上下载《千字文》全文,放入WORD文件中,每页25行,每行5列,每列4字,设定大小合适以填满两页,保存为“test.docx”。

2、另准备一个用来充当水印的图片“water.jpg”,用其他方法把它变成一个图案半透明的PDF文件“water.pdf”。

3、用WPS加载“test.docx”导出的PDF文件“testwps.pdf”。

4、用Acrobat加载WORD2010做成的“testword2010.pdf”导出的图片,保存目录是“testacrobat”。


第一步:将“test.docx”变成“testword2010.pdf”。

为适应批处理需要,这里不考虑手动用WORD2010另存为的办法得到PDF文件。

这一步,参考网上资料,直接写出Python程序word2pdf.py:

640?wx_fmt=png

第二步:为PDF文件加水印

将“testword2010.pdf”变成“rword2010.pdf”。网上资料也很多,思路是使用PyPDF2扩展包,参考网址http://www.blog.pythonlibrary.org/2018/06/07/an-intro-to-pypdf2/给出的代码,写出Python程序addwatermark1.py:

640?wx_fmt=png

运行程序发现出错。出错信息如下:
Traceback (most recent call last):
  File "C:\Python364\lib\site-packages\PyPDF2\generic.py", line 484, in readFromStream
    return NameObject(name.decode('utf-8'))
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xcb in position 8: invalid continuation byte

During handling of the above exception, another exception occurred:

这后面还跟着数十行出错信息。生成的PDF文件“rword2010.pdf”自然是打不开的。网上搜一圈,发现没有相关帖子。看来我这是小众问题,小概率事件发生在我身上,我怎么这么幸运呢?强忍住到世界杯去赌球的冲动,继续思考我的问题的解决办法。

第三步:寻求问题的原因

首先,我看出错信息有“decode('utf-8')”之类的字样,难道是PyPDF2不支持中文?

于是我又做了一个纯英文的WORD文件,用WORD2010手动导出成PDF,加水印也是失败的。这就排除了编码的问题,看来这个问题PDF文件是不是中文内容关系不是太大。

仍然是上网狂搜,变换各种关键词狂搜。终于搜到一篇相关的
https://blog.csdn.net/Li_Jiaqian/article/details/80299026
该帖子想用程序合并PDF文件,遇到跟本文一样的错误,贴文的作者说原来的pdf是1.5版本,合并出错。他将pdf转化为word,再在wps中将word输出为pdf,这时的pdf是1.7版本,合并就不再报错。
于是用WPS文字打开“test.docx”,用菜单“输出为PDF”生成PDF文件“testwps.pdf”,用上面的代码(当然得改一下文件名)加水印,成功。
用的WPS文字的版本是“WPS 文字 10.1.0.7400”,20180629官网下载。

到目前为止,我也怀疑这事儿跟所谓的PDF版本有关,但查不到相关资料,不知道word2010和wps文字导出的PDF到底是哪个版本的PDF。或许从这里突破还真有希望找到为PDF加水印的简单办法,但目前没太多精力,无奈放下,继续寻找为PDF加水印的成功办法。

于是继续上网搜,另外一个网友在贴子https://blog.csdn.net/Leafage_M/article/details/79705731里面提到一个奇怪的思路:

pdf = PdfFileReader(input_pdf)

改为

pdf = PdfFileReader(input_pdf, strict=False)

我按照这个思路去修改代码,程序运行不报错了,会在输出警告信息后生成“rword2010.pdf”,警告信息如下:

PdfReadWarning: Illegal character in Name Object [generic.py:489]

随后查看这个加水印后的PDF文件,发现只能看见水印,完全看不到中文内容。又做了一下英文PDF的实验,发现水印有,看不到英文内容。

现在,问题原因找到了:我们用PyPDF2扩展包为PDF文件添加水印之所以失败,是因为PDF是通过WORD2010将WORD文件转换来的。

那么,问题似乎解决了,用WPS文字把WORD文件做成PDF文件似乎是个好办法,然后再用我们第二步的代码就能为WPS生成的PDF文件加水印。但为现存的PDF文件加水印的问题还没有解决,因为我们的现存PDF文件总有很多是用WORD2010做成的。所以,还得继续寻找为PDF文件加水印的办法。

第四步:探求PDF加水印的通用办法

看来Python的扩展包PyPDF2的添加水印功能还是有很大缺点的,在它自身的版本升级之前,是不能考虑它了。本着吃不成鱼肉吃猪肉也行的原则,我们坚决抛开PyPDF2,另觅它途。既然一步到位不了,我们可以继续把整个任务分成两个子任务:

任务一:将PDF文件拆成图片,一页PDF文件变成一张图片。

任务二:将一张张的图片加上水印合并成PDF。

这两步似乎都不难。现分别实现之。


任务一:将PDF文件拆成图片

这个任务需要用到PyPDF2、PythonMagick和ghostscript三个扩展包,这里使用PyPDF2的其它功能。参考资料是

https://blog.csdn.net/sqlserverdiscovery/article/details/51425543

废话少说,直接上代码,函数如下:

640?wx_fmt=png

任务二:将图片加上水印合并成PDF

这一个任务主要是用扩展包reportlab。代码也很简单,直接给出函数:

640?wx_fmt=png

有了这两个函数,我们就好办了。将源PDF文件转成图片保存到中间目录,然后将中间目录的图片加上水印合并成目标PDF文件,最后删掉中间目录。调用函数的代码如下:

640?wx_fmt=png

运行一下,一切OK。

结语

虽然实现了为PDF文件添加水印的通用算法,为批量将WORD文件直接转换为带水印的PDF文件扫清了障碍。但是,还存在着如下的问题

第一、用本文的办法生成的图片质量不是太高,如果不删除中间结果目录的话,我们会看到,程序自动生成的图片远不如用Acrobat手动打开“testword2010.pdf”用菜单导出的图片清楚。所以,如何自动从PDF文件导出质量更高的图片,值得进一步研究。为了对比,本文在研究过程中将Acrobat导出的图片保存在“testacrobat”目录,用如下语句生成加水印的PDF文件:my_create_pdf_from_pictures_and_add_watermark("testacrobat", "r.pdf", waterfn)

第二、不相信PyPDF2的开发者比我们笨,所以说不定PyPDF2还有一些隐藏功能我们没发掘出来,因此寻求PyPDF2为PDF文件添加水印的完美解决办法还是有希望的。

第三、本文的思路和算法可能存在缺点和不足,请广大朋友批评指正。希望抛砖引玉,能找到更好的PDF添加水印的办法。

致谢

特别感谢Python界的大咖董付国老师,作为Python的小白,我在用Python处理WORD、PDF和图片的过程中得到董老师很多帮助。
也感谢我参考资料里面列出网址的帖子的楼主,他们给了我启发。

测试文件与代码下载地址:

链接: https://pan.baidu.com/s/1967jzOb3hFi-e5zSoboQwQ 密码: c8hw


中国传媒大学,胡凤国,2018年6月30日




---------董付国老师Python系列教材--------

1)《Python程序设计(第2版)》(2018年5月第6次印刷)

出版社官方链接(亚马逊、京东、当当均有销售):https://detail.tmall.com/item.htm?spm=a1z10.3-b-s.w4011-16232114860.18.24a52226hIi8Bj&id=534581929248&rn=9311dcbc68fffcf57b7ae352800e485d&abbucket=6

2)《Python可以这样学》(2018年2月第5次印刷)(本书已发行繁体版)

出版社官方链接(亚马逊、京东、当当均有销售):https://detail.tmall.com/item.htm?spm=a1z10.3-b-s.w4011-16232114860.16.24a52226hIi8Bj&id=544817105410&rn=9311dcbc68fffcf57b7ae352800e485d&abbucket=6

3)《Python程序设计基础(第2版)(2018年5月第2次印刷)

出版社官方链接(亚马逊、京东、当当均有销售):https://detail.tmall.com/item.htm?spm=a1z10.3-b-s.w4011-16232114860.24.24a52226hIi8Bj&id=565581275846&rn=9311dcbc68fffcf57b7ae352800e485d&abbucket=6

4)《中学生可以这样学Python》2018年5月第2次印刷)

出版社官方链接(亚马逊、京东、当当均有销售):https://detail.tmall.com/item.htm?spm=a1z10.3-b-s.w4011-16232114860.20.24a52226hIi8Bj&id=560808221053&rn=9311dcbc68fffcf57b7ae352800e485d&abbucket=6

5)《Python程序设计开发宝典》(2018年2月第3次印刷)

出版社官方链接(亚马逊、京东、当当均有销售):https://detail.tmall.com/item.htm?spm=a1z10.3-b-s.w4011-16232114860.52.24a52226hIi8Bj&id=556093887133&rn=9311dcbc68fffcf57b7ae352800e485d&abbucket=6

6)《玩转Python轻松过二级》(2018年5月隆重上架)

出版社官方链接(亚马逊、京东、当当均有销售):https://detail.tmall.com/item.htm?spm=a1z10.3-b-s.w4011-16232114860.84.24a52226hIi8Bj&id=569250004069&rn=9311dcbc68fffcf57b7ae352800e485d&abbucket=6


董付国老师6本Python系列图书阅读指南

董付国老师6本Python系列教材被北大、复旦等近百所高校选作教材

热烈庆祝《Python可以这样学》在台湾发行繁体版


董老师127课免费视频地址: https://pan.baidu.com/s/1jJeAs8Q 密码: px59


----------相关阅读----------

教学课件

1900页Python系列PPT分享一:基础知识(106页)

1900页Python系列PPT分享二:Python序列(列表、元组、字典、集合)(154页)

1900页Python系列PPT分享三:选择与循环结构语法及案例(96页)

1900页Python系列PPT分享四:字符串与正则表达式(109页)

1900页Python系列PPT分享五:函数设计与应用(134页)

1900页Python系列PPT分享六:面向对象程序设计(86页)

1900页Python系列PPT分享七:文件操作(132页)

1900页Python系列PPT分享八:异常处理结构与程序调试、测试(70页)

报告PPT(163页):基于Python语言的课程群建设探讨与实践

非计算机专业《Python程序设计基础》教学参考大纲

计算机相关专业“Python程序设计”教学大纲(参考)

报告PPT(123页):Python编程基础精要

《Python程序设计》实验指导书(30个实验)


系列题库分享

1000道Python题库系列分享一(17道)

1000道Python题库系列分享二(48道)

1000道Python题库系列分享三(30道)

1000道Python题库系列分享四(40道)

1000道Python题库系列分享五(40道)

1000道Python题库系列分享六(40道)

1000道Python题库系列分享七(30道)

1000道Python题库系列分享八(29道)

1000道Python题库系列分享九(31道)

1000道Python题库系列分享十(37道)

1000道Python题库系列分享十一(9道)


相关阅读

Python+pywin32批量转换Word文件为PDF文件

Python批量提取PDF文件中的文本

Python查找Word文件中红色和加粗的文字(附元宵节送书活动中奖名单)

使用Python写入docx文件并控制字体颜色

Python批量提取Word文件题库中的答案

Python操作docx文档设置居中并创建表格

Python把docx文档中的题库导入SQLite数据库

Python提取docx文档中例题、插图、表格清单

猜你喜欢

转载自blog.csdn.net/oh5w6hinug43jvrhhb/article/details/80879026