PDF 文件处理
参加高阶培训的时候讲过 pdf 数据内容的获取,当时使用的是 pdfplumber 这个第三方库。
不过在那之前我一直使用的是 pymupdf 这个库进行 pdf 文件的处理。官方文档看得很心烦,索性写了一些代码将其封装,现在分享给大家。
# -*- coding: utf-8 -*-
"""
@author: yanglei
对pdf进行操作
需要先安装pymupdf库
安装方法为pip insatll --upgrade -i https://pypi.tuna.tsinghua.edu.cn/simple PyMuPDF
"""
try:
import fitz
except:
print(__file__, "needs PyMuPDF (fitz).")
raise SystemExit
def convert_obj_to_pdf(obj_path, pdf_path):
'''
功能:将文件(XPS, EPUB, CBZ,图片等)转为pdf
参数:文件路径,pdf存放路径
'''
if not (list(map(int, fitz.VersionBind.split('.'))) >= [1, 13, 3]):
raise SystemExit('insufficient PyMuPDF version')
doc = fitz.open(obj_path)
if doc.isPDF:
raise SystemExit('document is PDF already')
print('Converting {} to pdf'.format(obj_path))
b = doc.convertToPDF() # convert to pdf
pdf = fitz.open("pdf", b) # open as pdf
toc = doc.getToC() # 获取书签
pdf.setToC(toc) # 设置输出的书签
meta = doc.metadata # 获取详细信息
# if not meta.get('producer'):
# meta['producer'] = 'PyMuPDF v' + fitz.VersionBind
# if not meta.get('creater'):
# meta['creater'] = "PyMuPDF PDF converter"
pdf.setMetadata(meta)
# 设置超链接
link_cnti = 0
link_skip = 0
for pinput in doc:
links = pinput.getLinks()
link_cnti += len(links)
pout = pdf[pinput.number]
for l in links:
if l['kind'] == fitz.LINK_NAMED:
link_skip += 1
continue
pout.insertLink(l)
pdf.save(pdf_path + '.pdf', garbage=4, deflate=True)
print("Skipped %i named links of a total of %i in input." % (link_skip, link_cnti))
return True
class Pdf(object):
def __init__(self, path):
self.pdf_path = path
def get_doc_pagecount(self):
'''
功能:获取pdf文档的页数
返回值:pdf文档的页数
返回值类型:int
'''
doc = fitz.open(self.pdf_path)
return doc.pageCount
def get_doc_metadata(self):
'''
功能:获取pdf文档的详细信息,包括创建日期、修改日期、创建者等等
返回值:pdf文档的详细信息
返回值类型:dict
'''
doc = fitz.open(self.pdf_path)
return doc.metadata
def get_doc_bookmarks(self):
'''
功能:获取pdf文档的书签信息
返回值:pdf文档的书签信息
返回值类型:list
'''
doc = fitz.open(self.pdf_path)
if doc.getToC():
return doc.getToC()
else:
return None
def get_page_links(self, pagenum=0):
'''
功能:获取pdf文档某个页面的超链接
参数:页码
参数类型:int
返回值:pdf文档某个页面的超链接信息
返回值类型:list
'''
doc = fitz.open(self.pdf_path)
if pagenum > self.get_doc_pagecount() - 1:
return 'Invalid page number,please try again!'
else:
page = doc[pagenum]
links = page.getLinks()
if links:
return links
else:
return None
def page_to_img(self, pagenum=0, img_path='yanglei.png', zoom=3, rotate=0): # zoom为放大倍数,rotate为旋转角度
'''
功能:将pdf文档某个页面转换为图片
参数:页码,图片存储路径,放大倍数,旋转角度
返回值:True代表图片已经生成
返回值类型:bool
'''
doc = fitz.open(self.pdf_path)
if pagenum > self.get_doc_pagecount() - 1:
return 'Invalid page number,please try again!'
else:
page = doc[pagenum]
zoom = zoom
rotate = rotate
trans = fitz.Matrix(zoom, zoom).preRotate(rotate)
pix = page.getPixmap(matrix=trans, alpha=False)
pix.writePNG(img_path)
return True
def get_page_text(self, pagenum=0, type='text'):
'''
功能:将pdf文档某个页面转换为文本
参数:页码,获取数据的类型(可填写的类型有text/html/dict/rawdict/xhtml/xml)
返回值:转换为文本之后的内容
返回值类型:str
'''
doc = fitz.open(self.pdf_path)
if pagenum > self.get_doc_pagecount() - 1:
return 'Invalid page number,please try again!'
else:
page = doc[pagenum]
text = page.getText(type)
return text
def search_page_for_text(self, pagenum=0, text='', hit_max=16):
'''
功能:搜索pdf文档某个页面中是否存在待搜索文本
参数:页码,待搜索文本的内容,允许匹配的最多个数
返回值:待搜索文本的位置信息
返回值类型:list
'''
doc = fitz.open(self.pdf_path)
if pagenum > self.get_doc_pagecount() - 1:
return 'Invalid page number,please try again!'
else:
page = doc[pagenum]
areas = page.searchFor(text, hit_max=hit_max)
return areas
pdf = Pdf('I:/艺赛旗iS-RPA V7.0高阶培训.pdf')
pdf.page_to_img(50, r'C:\Users\yuryq\Desktop\1.png')
顺带一提,看代码的最后两行可以知道本文的图片就是用其中的代码生成的。
先挖个坑,代码还远不止这些,感兴趣的可以持续关注,之后有空还会更新。
来来来,今天好好聊聊,哈哈