pdf压缩脚本

通过Python压缩pdf

pdf如果直接经过编辑,可能会有多图层叠加的问题;多次编辑后pdf文件可能会变得非常大,所以提供一种压缩pdf的方式,并且pdf压缩后,仍然可以选定文本和编辑文本。

PS:市面上的在线压缩软件要么收费,要么压缩效果不好,压缩以后可能有乱码

通过PyPDF2实现压缩

建议使用anaconda安装python的pypdf2包

笔者用的python版本是3.10,可能会出现pypdf2版本不兼容的问题

提供一个命令,直接输入conda命令行,即可让conda推荐合适的插件版本

conda install -c conda-forge PyPDF2

实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import PyPDF2


def compress_pdf(input_path, output_path):
with open(input_path, 'rb') as file:
pdf = PyPDF2.PdfFileReader(file)
writer = PyPDF2.PdfFileWriter()

for page_num in range(pdf.getNumPages()):
page = pdf.getPage(page_num)
# 对页面内容进行压缩
page.compressContentStreams()
writer.addPage(page)

with open(output_path, 'wb') as output_file:
writer.write(output_file)


if __name__ == "__main__":
# 可以用相对路径或者绝对路径
input_pdf = "input.pdf"
output_pdf = "output_compressed.pdf"
compress_pdf(input_pdf, output_pdf)

经过测试,成功将46.2 MB的PDF压缩到了4.29 MB,并且保留了原有格式和字体,不会有乱码的情况

压缩原理

  1. 首先,我们使用Python的open()函数以二进制读取模式打开输入的PDF文件。这样我们就可以读取PDF文件的内容。
  2. 接下来,我们使用PyPDF2的PdfFileReader()函数创建一个PDF文件阅读器对象,以便读取输入PDF文件的内容。通过这个阅读器对象,我们可以获取PDF文件的总页数和访问每一页的内容。
  3. 接着,我们创建一个新的PDF文件写入器对象,使用PdfFileWriter()函数。
  4. 然后,我们使用一个循环遍历输入PDF文件的每一页。在循环中,我们使用pdf.getPage(page_num)来获取当前页的内容。
  5. 对于每一页,我们调用page.compressContentStreams()函数,这是PyPDF2库中的一个方法,用于对页面内容进行压缩。
  6. 压缩完成后,我们将当前页添加到新的PDF文件写入器对象中,使用writer.addPage(page)
  7. 在遍历所有页面后,我们使用open()函数以二进制写入模式打开输出的PDF文件。
  8. 最后,我们使用新的PDF文件写入器对象的write()函数将压缩后的内容写入输出PDF文件。

这样,通过循环遍历所有页面,对每一页的内容进行压缩,并将压缩后的内容写入新的PDF文件,我们就完成了PDF文件的压缩过程。值得注意的是,这个压缩过程主要针对内容的压缩,而不是对文件结构进行重组。压缩的效果取决于PDF文件的内容和结构,对于不同类型的PDF文件可能会产生不同的结果。

那么page.compressContentStreams()的原理是什么呢?

page.compressContentStreams()方法是PyPDF2库中用于压缩PDF页面内容流(Content Stream)的函数。PDF页面的内容流是一系列操作指令,用于描述页面上的文本、图像和其他元素的位置、样式和绘制方式。通过压缩内容流,可以减小PDF文件的大小,节省存储空间和传输时间。

compressContentStreams()方法的原理如下:

  1. 遍历内容流:首先,PyPDF2库会遍历页面的内容流,解析其中的操作指令和参数。
  2. 优化操作:在遍历过程中,PyPDF2会尝试对内容流中的操作进行优化,例如合并相邻的相同操作、删除冗余的操作、简化操作参数等。
  3. 压缩操作:PyPDF2会对内容流中的文本和图像数据进行压缩,以减小数据的大小。例如,它可能会压缩文本字符串、使用更高压缩率的图像格式等。
  4. 重新生成内容流:在优化和压缩操作完成后,PyPDF2会重新生成经过优化和压缩的内容流。
  5. 更新页面内容:最后,PyPDF2会将经过优化和压缩的内容流替换原始页面的内容流,从而实现对页面内容的压缩。

值得注意的是,compressContentStreams()方法主要针对页面的内容流进行压缩,而不会对PDF文件的结构进行重组。压缩的效果取决于页面内容的复杂性和特点,对于包含大量文本和图像的页面,压缩效果可能会更明显。但对于一些特殊类型的PDF文件或已经进行过压缩处理的PDF文件,压缩的效果可能较小。在实际使用中,建议检查压缩后的PDF文件,以确保满足预期的压缩效果。

直接可运行的exe

分享一个我封装好的可执行文件,可以直接用来压缩pdf

https://github.com/guolinac/CompressPDF

-------------本文结束感谢您的阅读-------------