Python 方便快捷给 PDF 加水印

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: Python 方便快捷给 PDF 加水印

方便快捷给 PDF 加水印


有文字创作需求的同学有时候会需要将自己的作品集结为 PDF 进行分发,一方面帮助自己整理归档,另一方面也有利于作品传播。类似的需求我们已经讲过《用 Python 抓取公号文章保存成 PDF》。


出于对盗版的担忧以及对自身权益的维护,很多人都会选择给自己的 PDF 加上专属的水印以标识出处。但各种 PDF 编辑器中加水印的逻辑不同,使用方式也大相径庭,有没有一种方式可以简单快捷地对 PDF 加上水印,同时保持逻辑的一致性呢?


显然此时我们又想到了我们的老朋友:Python。使用 Python 通过编程的方式来对 PDF 加水印还有一个显而易见的好处是:在操作过程中我们会拥有更大的自由度。我们可以根据自己的特殊要求任意定制加水印的逻辑。


我们就以《用 Python 抓取公号文章保存成 PDF》一文中得到的 PDF 为例进行演示。下图所示即为该 PDF 文档的一部分。


image.png


1. 相应库


首先,要对 PDF 进行操作,只靠 Python 自带的库肯定是不够的,还需要求助于第三方库。这里我们用到的是PyPDF2这个库(好消息是,这个库不需要额外安装其他应用,开箱即可使用)。


安装方式大家已经很熟悉了,输入命令:


pip install PyPDF2

即可。


2. 测试库的功能


首先我们尝试从现有 PDF 文件中提取出第一页保存为新的 PDF 文件:


import PyPDF2
inputName = "input.pdf"pdf = PyPDF2.PdfFileReader(inputName)page = pdf.getPage(0)
outputObj = PyPDF2.PdfFileWriter()outputObj.addPage(page)
with open("test.pdf", "wb") as f:    outputObj.write(f)


PyPDF2 中有两个最常用的类:PdfFileReaderPdfFileWriter。顾名思义,这两个类分别用于读取 PDF 和写入 PDF。其中PdfFileReader传入参数可以是一个打开的文件对象,也可以是表示文件路径的字符串。而PdfFileWriter则必须传入一个以写方式打开的文件对象。


尤其要注意的是,不同于我们常见的代码、markdown 等文本格式,PDF 是二进制数据类型,因此在打开一个 PDF 格式的文件时,需要显式指定“以二进制格式写入文件内容”,即”wb"


运行程序,打开test.pdf查看结果。可以看到效果与预期一致:


image.png


3. 加水印

要加水印首先要制作水印,出于演示目的我们也制作了本公众号对应的水印,用到了公众号的二维码和一句友好的提示语。如下图所示:


image.png


本文用到的水印、源 PDF 等文件均随示例代码一起发布,读者可以在之后自行尝试。

出于美观和尽量不影响阅读 PDF 内容的考虑,二维码和提示语的位置较偏且尺寸并不大,并且提示语的字体和颜色也不算醒目——如果是读者自用的话,就可以尽情挥洒创作激情,爱什么狂拽酷炫尽管往上堆也没人能反对哈哈。


首先,同时打开源 PDF 和作为水印的 PDF 文件。其中,水印 PDF 文件有且仅有一页,因此我们直接使用链式操作取出watermark.pdf文件的第一页作为变量watermark的值:


import PyPDF2
inputName = "input.pdf"watermarkName = "watermark.pdf"outputName = "output.pdf"
pdfInput = PyPDF2.PdfFileReader(inputName)watermark = PyPDF2.PdfFileReader(watermarkName).getPage(0)

按照上一节复制 PDF 内容的套路,还需要再创建一个PyPDF2.PdfFileWriter对象:


pdfWriter = PyPDF2.PdfFileWriter()

然后很自然地,我们需要对源 PDF 文件的内容按页遍历,将每一页的内容逐页与水印内容合并。但应该如何来对 PDF 文件进行遍历呢?


我们现在只知道对于PyPDF2.PdfFileReader对象,有方法getPage可以以索引的方式取出对应页码的内容,该如何获得相应索引呢?


好在,PyPDF2.PdfFileReader还提供了一个属性字段numPages来表示该 PDF 文件的总页数——调用方法getNumPages可以得到同样的结果。


对于上面的代码,源 PDF 文件实际应为 10 页,我们输出相应值可以看到与实际一致:


print(pdfInput.numPages)  # 10print(pdfInput.getNumPages()) # 10

这样我们就可以利用for循环和range来提供一个递增的索引,用以逐页取出 PDF 的内容了:


for i in range(pdfInput.numPages):    page = pdfInput.getPage(i)

同时,对于单个的page对象,还存在一个名为mergePage的方法,接受另一个同为 PDF 中单个页面的对象,原地修改自身为两个页面合并之后的结果。


PyPDF2.PdfFileWriter()则提供方法addPage,用以新增 PDF 页面:


for i in range(pdfInput.numPages):    page = pdfInput.getPage(i)    page.mergePage(watermark)    pdfWriter.addPage(page)

循环结束之后,实际上我们加水印的工作已经基本完成。


之所以说是“基本”,是因为这个时候得到的“PDF 文件”实际上依然还只是存在于内存中的一个对象,虽然保存了我们想要的内容,但尚未保存到硬盘上,一旦程序执行结束就再也找不回来了。


因此我们还需要新建一个文件用以保存最终结果:


with open(outputName, "wb") as f:    pdfWriter.write(f)

注意文件的打开方式为“wb”


到这一步,我们加水印的工作已经全部完成,效果如下:


image.png


4. 番外:给 PDF 加密

image.png




一般来讲,我们在发布 PDF 的同时,可能需要对文件的权限进行一定的限制,比如阻止用户直接提取 PDF 内容,因此我们可以考虑对 PDF 进行加密。


在 PyPDF2 中,PyPDF2.PdfFileWriter()对象提供方法encrypt来对 PDF 文件加密,可以同时进行用户级和拥有者级加密。


默认情况下传入一个字符串作为密码,以该字符串作为密码同时进行两种加密;也可分别指定相应密码。


第三个参数接受一个布尔值,用以指示加密类型,默认为True,使用 128 位加密;为False时使用 40 位加密。视情况决定。不过对一般 PDF 而言,40 位加密已然足够,还能提升加密效率。


注意,在内容写入硬盘时可能需要耗时较长,因此若程序“假死”,需要耐心等待一段时间。


import PyPDF2
inputPDF = PyPDF2.PdfFileReader("output.pdf")pdfWriter = PyPDF2.PdfFileWriter()
for i in range(inputPDF.numPages):    page = inputPDF.getPage(i)    pdfWriter.addPage(page)
pdfWriter.encrypt("user", "justdopython", False)# pdfWriter.encrypt("justdopython")
with open("encrypted.pdf", "wb") as f:    pdfWriter.write(f)


image.png


这种情况下,为保证用户体验,建议将第一个参数,即用户级密码,设置为空字符串(“”)。这样一般用户打开 PDF 文件时就不必进行输入。如需特别操作时在阅读器中用拥有者口令重新打开即可。


5. 总结


本文介绍了一种给 PDF 加水印的自动化方法。实际上 PyPDF2 模块的功能还不止于此,合并多个 PDF 文件、筛选 PDF 文件的特定页面等等重复性的工作同样可以使用该模块代劳。


更多用法就留待读者探索了。


目录
相关文章
|
2月前
|
Python
Python对PDF文件页面的旋转和切割
Python对PDF文件页面的旋转和切割
49 3
|
2月前
|
计算机视觉 Python
Python操作PDF文件
Python操作PDF文件
38 1
|
2月前
|
存储 安全 网络安全
Python编程--使用PyPDF解析PDF文件中的元数据
Python编程--使用PyPDF解析PDF文件中的元数据
66 1
|
2月前
|
算法 Java 程序员
【福利😍】2024年最新103本互联网大厂程序员编程书合集【高清文字版无水印pdf】
推荐优质编程电子书资源,涵盖Python入门、算法设计、Java高并发、Docker、机器学习等领域,适合从小白到高级开发者。书籍包括《编程小白的第一本Python入门书》、《编程珠玑》等,助你提升技能,紧跟技术前沿,在职场中脱颖而出。下载地址含国内外网盘链接,更多资源可访问资料吧网站获取。
200 0
|
2月前
|
IDE 开发工具 数据安全/隐私保护
Python编程实现批量md5加密pdf文件
Python编程实现批量md5加密pdf文件
42 0
|
3月前
|
数据安全/隐私保护 Python
Python办公自动化:给pdf加水印
Python办公自动化:给pdf加水印
46 0
|
3月前
|
Python
Python办公自动化:提取pdf文件中的图片
Python办公自动化:提取pdf文件中的图片
34 0
|
数据安全/隐私保护 Python
python-批量添加图片水印
前言: 最近总是被无良公众号和培训机构拷贝文章,他们根本不会给你备注原文出处,这种行为真的让人不高兴,所以计划以后的文章都添加上自己的水印。 话不多说,直接上代码。 一、单张图片添加文字水印 # -*- coding: utf-8 -*- # @Time : 2018/5/9 上午11:31 # @Author : xiaoxi # @File : watermark.
1844 0
|
16天前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!
|
15天前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
下一篇
DataWorks