Python PDF转image方法小结

昨天有一个突发的需求,要求尽快的把一个一百多页的pdf按照页码每页转换成一个jpg文件后打包传回。正好最近一直在学习Python就打算写一个这样的脚本(结果发现踩了坑)

Wand

【pypi - Wand】【Wand官网】【Github - Wand】pip install wand

在百度上找解决方案的时候,第一条用的就是wand. 后来去stackoverflow上看也有用wand来操作的,看起来也挺简单,代码如下:

from wand.image import Image

filename="somefile.pdf"

with(Image(filename=filename, resolution=120)) as source: 
    images = source.sequence
    pages = len(images)
    for i in range(pages):
        n = i + 1
        newfilename = filename[:-4] + str(n) + '.jpeg'
        Image(images[i]).save(filename=newfilename)

上述代码把somefile.pdf转换成一张张图片,并分为存为somefile1.jpeg这样的图片。
但问题是,我在windows下运行的时候出现了这样的错误:

Traceback (most recent call last):
  File "test.py", line 1, in 
    from wand.image import Image
  File "C:\Program Files\Python\lib\site-packages\wand\image.py", line 18, in 
    from . import compat
  File "C:\Program Files\Python\lib\site-packages\wand\compat.py", line 25, in 
    abc = collections.abc if PY3 else collections
  File "C:\Program Files\Python\lib\collections\__init__.py", line 55, in __getattr__
    raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
AttributeError: module 'collections' has no attribute 'abc'

翻看wand官网可以看到,wand和其他大部分类似库一样,都是包装接口(bindings),而实际进行转换的工具是ImageMagick. 【ImageMagick官网】【Github - ImageMagick】

在我写这篇文章的时候,我只打开过ImageMagick官网一次,剩下大部分时候都会超时。除了在ImageMagick官网上下载windows版本,Wand官网说在这里也能下载到windows版的ImageMagick。但实际上这个网站还是超时。

从ImageMagick仓库来看,官方在releases里没有提供windows版的build。但是从其CI日志看其实是在win平台上也测试并打包了。ImageMagick倒是支持在windows下编译,不过看了一下说明文档之后发现不仅不支持cmake,还需要先build一个configure程序然后再用configure生成sln编译库本体。

在Linux下,安装wand的时候会提示需要安装libmagickwand-dev。

如果脚本启动的时候报这样的错:wand.exceptions.PolicyError: not authorized somefile.pdf,这不是wand的锅,这是ImageMagick默认配置的锅。解决方案是sudo vim /etc/ImageMagick-6/policy.xml然后找到这一行,将right="none"修改为right="all"即可。

pdf2image

【pypi - pdf2image 】【Github - pdf2image】pip install pdf2image

pdf2image也是个包装器,真正的转换工具是poppler。从这里下载poppler-utils的windows版. 右键另存为或者迅雷下载可能会出现一些问题,这里我只能用curl下载了(windows版本的curl去libcurl官网上就能下载到,虽然我是自己编译的)curl -O http://blog.alivate.com.au/wp-content/uploads/2018/10/poppler-0.68.0_x86.7z 解压之后把bin目录加载到PATH环境变量里(或者直接把bin目录下的文件都拖到当前文件夹里,用完再删了)

pdf2image用法如下:

from pdf2image import convert_from_path
convert_from_path('a.pdf', 500, "output",fmt="JPEG",output_file="ok",thread_count=4)

这会将a.pdf转换成在output文件夹下形如ok_线程id-页码.jpg的一些文件。若不指定thread_count则默认为1,并且在文件名中显示id. 这种转换是直接写入到磁盘上的,因此不会占用太多内存。

还有一种写法是:

from pdf2image import convert_from_path
pages = convert_from_path('pdf_file', 500)
for page in pages:
    page.save('out.jpg', 'JPEG')

但这种写法会占用大量内存,因为convert_from_path的默认格式是ppm,其次若不指定输出则默认是写入到内存中的。

在Linux下使用sudo apt install poppler-utils来安装poppler,可能还需要安装pillow,使用pip install pillow安装即可。

其他

除了使用现成的package,也可以通过“野路子”。比如选好一个工具,拼凑cmd命令,然后通过subprocess模块启动子进程进行转换,也是可以的。
目前除了wand和pdf2image还没发现比较好的包,以后如果发现更好的工具可能会更新。
最后推荐一个在线pdf转图片的网站:【PDF to JPG online converter - Convert PDF to JPG for FREE】如果pdf内容不要紧的话可以试试这个在线转换器,完全免费,对于多页结果还提供在线打包下载服务。

你可能感兴趣的:(Python PDF转image方法小结)