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

阻止 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 :
最基本的操作为 open 和 save ,两个函数的参数都是文件名:
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
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 之类的工具好一些。