Python 方便快捷给 PDF 加水印

来源:Python 技术「ID: pythonall」

方便快捷给 PDF 加水印

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

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

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

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

original_pdf

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查看结果。可以看到效果与预期一致:

copy_pdf

3. 加水印

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

watermark

本文用到的水印、源 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”

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

output_pdf

4. 番外:给 PDF 加密

一般来讲,我们在发布 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)
encrypt

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

5. 总结

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

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

(0)

相关推荐

  • 使用pdfrw库对pdf文件进行读写操作

    大家好,前几天分享了一篇读取pdf文章,但是依然无法少部分的pdf进行操作.今天看Python Weekly最新一期推送的文章中<Creating and Manipulate PDFs wit ...

  • pdf加水印怎么加?一个简单的方法共享给大家

    pdf加水印怎么加?一个简单的方法共享给大家

  • pdf加水印怎么加?给pdf添加水印的快速方法

    除了需要给PDF去除水印之外,有的时候,咱们也是需要给PDF添加上水印的.前段时间,小北向大家分享了如何给PDF文档去除水印,这不,立马就有网友发来了私信,问小北该如何给PDF文档添加水印,刚好,小北 ...

  • 免费教你用Python给PDF加版权水印

    "小李,今天需要给一批商务文件文件加水印",快下班了,小李被老板临时分配的任务惊呆了.咋办?200个PDF 啊! Python不加班:5分钟学会自动给PDF加水印 什么是水印? 水 ...

  • 100份PDF、Word、Excel文档加水印,只要1分钟,方法真的很简单!

    Hello,各位叨友们好!我是叨叨君~ 在上网查资料时,我们常常看到一些文件的文字后面印着公司的名字或者logo水印,还能在一些保密文件的正文后面看到"机密""严禁复制& ...

  • pdf怎么加水印?上班族都会的简单方法

    对于阅读的人来说,水印是一种负担,但是对于作者来说,水印就更像是一种版权的象征了,这也就是为什么那么多人喜欢在自己创作的作品中加入水印的原因了.关于水印,很多人都曾经学习过去除水印的办法,那么问题来了 ...

  • 如何在PDF文档上加水印

    当我们需要传输一些比较重要的文件时,往往会选择将文档转换为PDF文件,避免其他人复制.更改文档的内容. pdfFactory不仅可以为用户提供快速创建PDF的功能,同时还提供了添加水印的功能.有了水印 ...

  • PDF设置水印,怎样给PDF添加水印内容?

    PDF是常见的办公文档格式之一,有时候为了保护自己的文档,我们会选择给文档添加水印,那么如何给PDF添加水印内容呢?下面是详细的操作方法,有需要的小伙伴可以参考使用! 借助工具:金舟PDF转换器 操作 ...

  • 在excel中如何加水印图片

    在excel中如何加水印图片有好几种方法,可以用背景来当作水印,也可以在页脚上插入图片进行调整设置为水印,但是我觉得还是没有下面这种方法较为合适.这种方法有一个前提条件就是尽量的把图片比例做成与插入水 ...

  • 用 Python 将 html 转为 pdf、word

    来源:Python 技术「ID: pythonall」 在日常中有时需将 html 文件转换为 pdf.word 文件.网上免费的大多数不支持多个文件转换的情况,而且在转换几个后就开始收费了. 转 p ...