修改 PDF 及其元数据

修改 PDF 及其元数据

RayAlto OP

老早买了一本码奴相关的实体书,以为支持一波正版能激起我当牛做马的欲望。但后来发现一边低头看书,一边抬头看屏幕实在是太蠢了,我可是有三个显示器的人,腾出一个屏幕看电子书还是轻而易举的。

所以老老实实去网上找了一个 PDF ,是某位网友从某个出版社网站上买的正版 PDF ,但是这个 PDF 先是有一个数字版权声明,然后每一页的页脚都被这个出版社标注了网友的用户名和邮箱,看着实在是难受,所以研究了一下怎么去掉这些东西。

1. 编辑 PDF 内容

Adobe 的软件基本都是 Windows 下的,所以这一节的操作都是在 Windows KVM 下完成的

一开始我就知道 Adobe Acrobat Pro DC 可以编辑 PDF ,但我买不起正版,而且之前一直在用的 AMTEmu 早就不能用了。

花两分钟咕噜咕噜之后,找到了 mokrus 这个毛子网站,里面都是 Adobe 的 patched 包,恰好有 Adobe Acrobat Pro DC ,装好了以后就可以随便编辑 PDF 页面的内容:

这个 PDF 是开源的,只是演示一下,实际上编辑的不是这个 PDF

Acrobat 编辑 PDF 的截图

阻止 Adobe Acrobat 对右键菜单的污染

打开 regedit ,打开 HKEY_CLASSES_ROOT ,把里面 *folder 下的 shellex\ContextMenuHandlers\Adobe.Acrobat.ContextMenu 里面的 default 的值前面加上 -- 就可以了,如果不考虑哪一天后悔想要恢复右键菜单可以直接把 Adobe.Acrobat.ContextMenu 删了。

2. 编辑 PDF 元数据

现在可以回到 Linux 了

直接说结论的话 PDF 有两套元数据机制,一个是 PDF 标准下的元数据、一个是 XMP 。这些数据都可以使用 PyMuPDF 来修改, PyMuPDF 是 MuPDF 的 Python 绑定,在 ArchLinux 下有打好的软件包:

1
pacman -S python-pymupdf

和 MuPDF 的 C 接口使用 fitz.h 头文件类似, PyMuPDF 包名为 fitz

1
import fitz

最基本的操作为 opensave ,两个函数的参数都是文件名:

1
2
3
doc = fitz.open('doc.pdf')
# 做了一些修改
doc.save('doc.modified.pdf')

2.1. PDF 标准元数据

可以通过 pdfinfo 来查看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
rayalto@RayAltoNUC ~$ pdfinfo ProGit.pdf
Creator: LaTeX with hyperref package
Producer: xdvipdfmx (0.7.8)
CreationDate: Thu Mar 4 20:51:26 2010 CST
ModDate: Fri Apr 6 23:05:39 2012 CST
Custom Metadata: no
Metadata Stream: no
Tagged: no
UserProperties: no
Suspects: no
Form: none
JavaScript: no
Pages: 236
Encrypted: no
Page size: 595.28 x 841.89 pts (A4)
Page rot: 0
File size: 4764239 bytes
Optimized: no
PDF version: 1.4

使用 PyMuPDF 可以轻松地读取这些数据:

1
2
3
4
5
import fitz # PyMuPDF

doc = fitz.open('ProGit.pdf')
for k, v in doc.metadata.items():
print(f'{k}: {v}')

输出:

1
2
3
4
5
6
7
8
9
10
11
format: PDF 1.4
title:
author:
subject:
keywords:
creator: LaTeX with hyperref package
producer: xdvipdfmx (0.7.8)
creationDate: D:20100304215126+09'00'
modDate: D:20120406230539+08'00'
trapped:
encryption: None

修改时需要复制一份,修改好再覆盖上去:

1
2
3
pdfmeta = doc.metadata
pdfmeta['creator'] = 'PyMuPDF'
doc.set_metadata(pdfmeta)

2.2. XMP

是 Adobe 的一个标准,大概是在媒体文件里塞 XML ,可能在被发明的 2001 年是先进的,但现在看来就是一坨。这个元数据也可以通过 pdfinfo 查看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
rayalto@RayAltoNUC ~$ pdfinfo -meta Algorithms.4th.pdf
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.1.0-jc003">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
xmlns:pdf="http://ns.adobe.com/pdf/1.3/"
xmp:ModifyDate="2018-11-28T17:51:45+08:00"
xmp:CreateDate="2018-11-28T17:51:45+08:00"
xmp:MetadataDate="2018-11-28T17:51:45+08:00"
dc:format="application/pdf"
xmpMM:DocumentID="uuid:178f2fd1-da33-420f-8ec2-6d65ab4d1f32"
xmpMM:InstanceID="uuid:1bf8c27c-a796-41a5-815c-dce5ff62aeb5"
pdf:Producer="xdvipdfmx (0.7.8)"/>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

使用 PyMuPDF 也可以轻松地读取这些数据,但只能拿到 XML 字符串:

1
print(doc.get_xml_metadata())

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.1.0-jc003">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
xmlns:pdf="http://ns.adobe.com/pdf/1.3/"
xmp:ModifyDate="2018-11-28T17:51:45+08:00"
xmp:CreateDate="2018-11-28T17:51:45+08:00"
xmp:MetadataDate="2018-11-28T17:51:45+08:00"
dc:format="application/pdf"
xmpMM:DocumentID="uuid:178f2fd1-da33-420f-8ec2-6d65ab4d1f32"
xmpMM:InstanceID="uuid:1bf8c27c-a796-41a5-815c-dce5ff62aeb5"
pdf:Producer="xdvipdfmx (0.7.8)"/>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

修改也是需要复制一份,修改好再覆盖:

1
2
3
xmlmeta = doc.get_xml_metadata()
# 做了一些修改
doc.set_xml_metadata(xmlmeta)

总结

虽然理论上 PDF 内容也可以通过 PyMuPDF 来编程修改,但体验下来还是可视化的 Acrobat Pro DC 操作起来方便一点,但 Acrobat 好像并不能修改 PDF 的元数据(而且还会私自修改 XMP 的格式),所以用 PyMuPDF ,实际用起来比 exiftool, pdftk, gs 之类的工具好一些。