PDF(Portable Document Format)是一种便携文档格式,它基于PostScripty这种脚本语言。
PDF文档操作
PDF(Portable Document Format)是一种便携文档格式,它基于PostScripty这种脚本语言,它是第一个独立于设备的页面描述语言。pdf格式是与平台无关,独立于底层操作系统和渲染引擎。由于PDF文档遵循标准格式,相关生态建设完善,应用广泛,非常值得花费时间讨论使用python进行操作。
python中能够操作pdf格式文档的库有:
◆PyMuPDF
◆pikepdf
◆pdfplumber
◆ReportLab
◆borb
主攻方向稍有不同,大致分类是:
◆pikepdf专注对已经存在的PDF的操作,例如分割、合并、旋转等
◆pdfplumber专注PDF内容提取,例如文本(位置、字体及颜色等)和形状(矩形、直线、曲线),此外还能够解析表格
◆ReportLab专注PDF页面内容(文本、图、表等)的创建
◆PyMuPDF和borb同时支持读、写及PDF页面操作,功能最为全面
◆borb是较新的库,功能也较为完善,但经过笔者试用,对于中文的支持不好
PyMuPDF的基本功能全面,非常适应用于批处理PDF。使用python来操作PDF/WORD/EXCEL/PPT等类文档,应该有如下的期望:
◆进行创作是非常不称手的。为何不用Office提供的工具软件进行编辑创作呢。因此,不能够指望这类库以及python提供非常全面完善的能力
◆能够在原来文档的基础上,进行批量化的一些操作。例如,可以基于某个模板,批量得制作邀请函,只要简单得修改姓名即可。或者根据数据库中的内容,在模板的基础上,定期形成周报、月报类固定格式的文档
◆能够在原来文档的基础上,增加、删除以及调整图片、文字与页面布局
所以,下述代码均从已经存在的内容入手进行演示:
01.
图片处理
timport os
import fitzprint(fitz.__doc__)def export2png(filename,pageno):"""将pdf文件指定页(从0开始算)导出为PNG图片文件Args:filename (string): PDF文件名pageno (int): 页号(从0开始)"""with fitz.open(filename) as doc:page = doc[pageno]pix = page.get_pixmap() pix.save("page-%i.png" % pageno)def export2svg(filename,pageno):"""将pdf文件指定页(从0开始算)导出为SVG矢量图Args:filename (string): PDF文件名pageno (int): 页号(从0开始)"""with fitz.open(filename) as doc:page = doc[pageno]svg = page.get_svg_image(matrix=fitz.Identity)output = open("page-%i.svg" % pageno,'w')output.write(svg)output.close()def figs2pdf(filename,startdir):"""将指定目录下的所有图片文件合并成为PDF文件Args:filename (string): 未来要生成的PDF文件名称startdir (string): 图片所在目录"""doc = fitz.open()# 列出目录下所有文件imglist = os.listdir(startdir) imglist.sort() for _, f in enumerate(imglist):# 遍历并且打开每个图片文件img = fitz.open(os.path.join(startdir, f))# 计算图片大小rect = img[0].rectpdfbytes = img.convert_to_pdf()img.close()# 将图片文件贴合到PDF页上imgPDF = fitz.open("pdf", pdfbytes) page = doc.new_page(width = rect.width,height = rect.height) page.show_pdf_page(rect, imgPDF, 0)# 保存到目标PDF中doc.save(filename) def convert(inputfile,outputfile):"""对图片格式进行转换Args:inputfile (string): 源图片outputfile (string): 目标图片"""pix = fitz.Pixmap(inputfile)pix.save(outputfile) pdfname = r'd:\test\sed.pdf'figs2pdf(r'd:\test\demo.pdf',r'D:\test\all\figures')export2png(pdfname,10)
export2svg(pdfname,10)convert(r"D:\test\all\serial1\000000.gif",r'd:\test\0.psd')
convert(r"D:\test\all\serial1\000000.jpg",r'd:\est\1.png')
上述代码演示了合并图片与分解PDF到图片,转换图片格式等功能。
•其中figs2pdf函数完成了从指定目录的多个图片合成一个PDF文件的常用功能。相对复杂一些。
•pymupdf也提供了逆向生成图片的方法。
•export2png将指定PDF文件的指定页转换成为PNG文件,效果比截图好
•export2svg将指定PDF文件的指定页转换成为svg文件,而SVG文件是矢量图、能够编辑,这个功能更是强大
•convert函数能够将多种图片格式进行转换。代码演示了转换成为psd与png格式。当然这些功能是pymupdf赠送的功能,不能够与pillow等专业库相比
下面的代码演示如何从pdf中提取文字,以及获得PDF文档中的各类链接。
import fitzdef showmeta(filename):"""显示PDF的基本信息Args:filename (string): 要打开的PDF文件名称"""print(fitz.__doc__)doc = fitz.open(filename)print(doc.page_count)print(doc.metadata)def showlinks(filename):"""显示PDF中的所有超链Args:filename (string): 要打开的PDF文件名称"""with fitz.open(filename) as doc:for page in doc:for link in page.links():# 显示一个列表if link["kind"] == fitz.LINK_GOTO:print("Jump to page", link["page"] + 1)elif link["kind"] in (fitz.LINK_GOTOR, fitz.LINK_LAUNCH):print("Open or launch file", link["file"])elif link["kind"] == fitz.LINK_URI:print("Open URI", link["uri"])def showtext(filename, pageno, option='text'):"""显示pdf中的文字Args:filename (string): 要打开的PDF文件名称pageno (int): 页号option (选项): 可能是'text','block'等Returns:list: 所有的文字列表"""with fitz.open(filename) as doc:page = doc[pageno]return page.get_text(option)def searchtext(filename, pageno, searchstr):"""在pdf中搜寻文字Args:filename (string): 要打开的PDF文件名称pageno (int): 页号searchstr (string): 要搜索的内容Returns:list: 匹配文字所在的区域列表。"""with fitz.open(filename) as doc:page = doc[pageno]areas = page.search_for(searchstr)return areaspdfname = r'd:\test\阿里技术地图.pdf'print(showtext(pdfname, 9))
areas = searchtext(pdfname, 1, '数据挖掘')
for rect in areas:print(rect)
showlinks(pdfname)
以上代码中:
•showtext需要传递相关的选项。pymupdf可以提取多种类型的文字。具体可以参考
•searchtext函数的返回与通常的预期不同,返回的是多个区域所形成的列表。主要用途是为了相关的工具软件显示用,例如可以高亮等。如果用这个函数只是期待返回具体的文字内容的话,不妨直接获得文字,然后再使用字符串的搜索功能。
•showlinks函数直接获得了所有页上所有的链接。大部分链接是内部的跳转,也有使用编辑软件加入的外部超链。文字内的包含的URL使用pymupdf是找不到的,必须自己写函数对字符串进行语议分析才能够获得,这个也是pymupdf不完善的地方。
除了上述对PDF本身的操作外,还有从PDF到DOCX文档的双向转换需要。由DOCX文档转PDF文档非常容易,直接在WORD中选择打印或者导出即可,没有什么可以讨论的。但是反过来稍微困难些,可以考虑以下方法:
•直接用WORD打开PDF,然后另存为DOCX文档。
•使用pdf2docx转化
•使用python-office转化
pdf2docx是一个轻量级的第三方库,对中文的支持不错,本身是基于pymupdf库发展起来的,它的安装过程如下。
pip install pdf2docx
# upgrade
pip install --upgrade pdf2docx
《阿里的技术地图》这个PDF可以从网上下载到,内容比较丰富,值得一看。如果想要转换成为WORD文档,示例代码如下。
from pdf2docx import Converterinputfilename = r'd:\test\阿里技术地图.pdf'
outputfilename = r'd:\test\demo.docx'cv = Converter(inputfilename)
# 将PDF全部内容转换成为DOCX
cv.convert(outputfilename)
cv.close()cv = Converter(inputfilename)
# 将PDF部分页转换为DOCX
cv.convert(outputfilename,start=3,end=5)
cv.close()cv = Converter(inputfilename)
# 将PDF个别页转换为DOCX
cv.convert(outputfilename,pages=[10,16,8])
cv.close()
这个库转换速度不是太快,还提供了多进程的功能,但实际使用时会有BUG出现,不建议使用。
END