1. 相关介绍
PyPDF2 读取、写入、分割、合并PDF文件
pdfplumber 读取 PDF 文件中内容和提取 PDF 中的表格
- pip install PyPDF2
- pip install pdfplumber
2. 批量拆分
将一个完整的 PDF 拆分成几个小的 PDF
- 读取 PDF 的整体信息、总页数等
- 遍历每一页内容,以每个 step 为间隔将 PDF 存成每一个小的文件块
- 将小的文件块重新保存为新的 PDF 文件
在拆分的过程中,可以手动设置间隔,例如:每5页保存成一个小的 PDF 文件。
from PyPDF2 import PdfFileWriter, PdfFileReader
import os
def split_pdf(filename, filepath, save_dirpath, step=5):
"""
拆分PDF为多个小的PDF文件,
@param filename:文件名
@param filepath:文件路径
@param save_dirpath:保存小的PDF的文件路径
@param step: 每step间隔的页面生成一个文件,例如step=5,表示0-4页、5-9页...为一个文件
@return:
"""
if not os.path.exists(save_dirpath):
os.mkdir(save_dirpath)
pdf_reader = PdfFileReader(filepath)
# 读取每一页的数据
pages = pdf_reader.getNumPages()
for page in range(0, pages, step):
pdf_writer = PdfFileWriter()
# 拆分pdf,每 step 页的拆分为一个文件
for index in range(page, page+step):
if index < pages:
pdf_writer.addPage(pdf_reader.getPage(index))
# 保存拆分后的小文件
save_path = os.path.join(save_dirpath, filename+str(int(page/step)+1)+'.pdf')
print(save_path)
with open(save_path, "wb") as out:
pdf_writer.write(out)
print("文件已成功拆分,保存路径为:"+save_dirpath)
# 调用对应的方法即可
split_pdf('top1',r'C:\Users\Administrator\Desktop\top1.pdf',r'D:\study\Datawhale\自动化办公-OfficeAutomation\1')
D:\study\Datawhale\自动化办公-OfficeAutomation\1\top11.pdf
D:\study\Datawhale\自动化办公-OfficeAutomation\1\top12.pdf
文件已成功拆分,保存路径为:D:\study\Datawhale\自动化办公-OfficeAutomation\1
3. 批量合并
- 1 确定要合并的 文件顺序
- 2 循环追加到一个文件块中
- 3 保存成一个新的文件
from PyPDF2 import PdfFileMerger
import os
path = r'D:\study\Datawhale\自动化办公-OfficeAutomation\1/'
files = os.listdir(path)#列出目录中的所有文件
merger = PdfFileMerger()
for file in files: #从所有文件中选出pdf文件合并
if file[-4:] == ".pdf":
merger.append(open(path+file, 'rb'))
with open('newfile.pdf', 'wb') as fout: #输出文件为newfile.pdf
merger.write(fout)
4. 提取文字内容
pdfplumber库
extract_text函数
import pdfplumber
def extract_text_info(filepath):
"""
提取PDF中的文字
@param filepath:文件路径
@return:
"""
with pdfplumber.open(filepath) as pdf:
# 获取第2页数据
page = pdf.pages[1]
print(page.extract_text())
extract_text_info(r'C:\Users\Administrator\Desktop\top1.pdf')
目录
Œ
一、医疗类资源方进入门槛和评价标准
二、医疗Query边界和问答类Query示例
Ž
三、医疗类资源类型、展现要求和质量要求
2
直接通过下标即可定位到相应的页码,从而通过 extract_text 函数提取该也的所有文字
如果想要提取所有页的文字,只需要改成:
def extract_text_info(filepath):
"""
提取PDF中的文字
@param filepath:文件路径
@return:
"""
with pdfplumber.open(filepath) as pdf:
# 获取全部数据
for page in pdf.pages:
print(page.extract_text())
extract_text_info(r'C:\Users\Administrator\Desktop\top1.pdf')
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210622155800789.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1Mzk2NTc3,size_16,color_FFFFFF,t_70#pic_center)
拓展一下:此处可以结合前面 word 小节,将内容写入 word 文件中
5. 提取表格内容
pdfplumber库
extract_text 函数→extract_table 函数
import pandas as pd
import pdfplumber
def extract_table_info(filepath):
"""
提取PDF中的图表数据
@param filepath:
@return:
"""
with pdfplumber.open(filepath) as pdf:
# 获取第8页数据
page = pdf.pages[7]
# 如果一页有一个表格,设置表格的第一行为表头,其余为数据
table_info = page.extract_table()
df_table = pd.DataFrame(table_info[1:], columns=table_info[0])
df_table.to_csv('dmeo.csv', index=False, encoding='gbk')
extract_table_info(r'C:\Users\Administrator\Desktop\top1.pdf')
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210622155816511.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1Mzk2NTc3,size_16,color_FFFFFF,t_70#pic_center)
如果当页不止一个表格,extract_table 函数 → extract_tables 即可。
# 如果一页有多个表格,对应的数据是一个三维数组
def extract_table_info(filepath):
"""
提取PDF中的图表数据
@param filepath:
@return:
"""
with pdfplumber.open(filepath) as pdf:
page = pdf.pages
tables_info = page.extract_tables()
for index in range(len(tables_info)):
# 设置表格的第一行为表头,其余为数据
df_table = pd.DataFrame(tables_info[index][1:], columns=tables_info[index][0])
df_table.to_csv('dmeo1.csv', index=False, encoding='gbk')
extract_table_info(r'C:\Users\Administrator\Desktop\top1.pdf')
6. 提取图片内容
提取图片:将内容中的图片都提取出来;
转存为图片:将每一页的 PDF 内容存成一页一页的图片,需要用到一个模块叫 fitz,fitz 的最新版 1.18.13,非最新版的在部分函数名称上存在差异,代码中会标记出来。
使用 fitz 需要先安装 PyMuPDF 模块,安装方式如下:
pip install PyMuPDF
提取图片的整体逻辑如下:
- 使用 fitz 打开文档,获取文档详细数据
- 遍历每一个元素,通过正则找到图片的索引位置
- 使用 Pixmap 将索引对应的元素生成图片
- 通过 size 函数过滤较小的图片
实现的具体代码如下:
if not os.path.exists(pic_dirpath):
os.makedirs(pic_dirpath)
# 使用正则表达式来查找图片
check_XObject = r"/Type(?= */XObject)"
check_Image = r"/Subtype(?= */Image)"
img_count = 0
"""1. 打开pdf,打印相关信息"""
pdf_info = fitz.open(filepath)
# 1.16.8版本用法 xref_len = doc._getXrefLength()
# 最新版本写法
xref_len = pdf_info.xref_length()
# 打印PDF的信息
print("文件名:{}, 页数: {}, 对象: {}".format(filepath, len(pdf_info), xref_len-1))
"""2. 遍历PDF中的对象,遇到是图像才进行下一步,不然就continue"""
for index in range(1, xref_len):
# 1.16.8版本用法 text = doc._getXrefString(index)
# 最新版本
text = pdf_info.xref_object(index)
is_XObject = re.search(check_XObject, text)
is_Image = re.search(check_Image, text)
# 如果不是对象也不是图片,则不操作
if is_XObject or is_Image:
img_count += 1
# 根据索引生成图像
pix = fitz.Pixmap(pdf_info, index)
pic_filepath = os.path.join(pic_dirpath, 'img_' + str(img_count) + '.png')
"""pix.size 可以反映像素多少,简单的色素块该值较低,可以通过设置一个阈值过滤。以阈值 10000 为例过滤"""
# if pix.size < 10000:
# continue
"""三、 将图像存为png格式"""
if pix.n >= 5:
# 先转换CMYK
pix = fitz.Pixmap(fitz.csRGB, pix)
# 存为PNG
pix.writePNG(pic_filepath)
7. 转换为图片
转换为照片比较简单,就是将一页页的 PDF 转换为一张张的图片。大致过程如下:
7.1 安装 pdf2image
首先需要安装对应的库,最新的 pdf2image 库版本应该是 1.14.0
它的 github地址 为:https://github.com/Belval/pdf2image ,感兴趣的可以自行了解
安装方式如下:
pip install pdf2image
7.2 安装组件
Windows 平台
对于 windows 用户需要安装 poppler for Windows,安装链接是:http://blog.alivate.com.au/poppler-windows/
另外,还需要添加环境变量, 将 bin 文件夹的路径添加到环境变量 PATH 中
注意这里配置之后需要重启一下电脑才会生效,不然会报如下错误:
if not os.path.exists(pic_dirpath):
os.makedirs(pic_dirpath)
images = convert_from_bytes(open(filepath, 'rb').read())
# images = convert_from_path(filepath, dpi=200)
for image in images:
# 保存图片
pic_filepath = os.path.join(pic_dirpath, 'img_'+str(images.index(image))+'.png')
image.save(pic_filepath, 'PNG')
8. 添加水印
首先需要一个水印PDF文件(可以自己生成一个水印pdf文件),再mergePage
from PyPDF2 import PdfFileReader, PdfFileWriter
from copy import copy
water = PdfFileReader(r'D:\study\Datawhale\自动化办公-OfficeAutomation\水印.pdf')
water_page = water.getPage(0)
pdf_reader = PdfFileReader(r'D:\study\Datawhale\自动化办公-OfficeAutomation\top1.pdf')
pdf_writer = PdfFileWriter()
for page in range(pdf_reader.getNumPages()):
current_page = pdf_reader.getPage(page)
# 封面页不添加水印
if page == 0:
new_page = current_page
else:
new_page = copy(water_page)
new_page.mergePage(current_page)
pdf_writer.addPage(new_page)
# 保存水印后的文件
with open(r'D:\study\Datawhale\自动化办公-OfficeAutomation\添加水印的top1.pdf', "wb") as out:
pdf_writer.write(out)
这里有一点需要注意:进行pdf合并的时候,“水印”在下面,文字在上面,因此是“水印”.mergePage(“图片页”)
其他解法:
# 导入库
from PyPDF2 import PdfFileWriter, PdfFileReader
import os
# 将水印页面读出来
water_page = PdfFileReader(r'D:\study\Datawhale\自动化办公-OfficeAutomation\水印.pdf').getPage(0)
# 遍历文件夹里的文件
all_files = os.listdir(r'D:\study\Datawhale\自动化办公-OfficeAutomation\1/')
# 返回在files/inputs下的所有文件
for file_name in all_files: # 遍历all_files的所有文件
pash = r'D:\study\Datawhale\自动化办公-OfficeAutomation\1/'+file_name
# 通过file_name和files/inputs/ 拼接出文件完整路径
#print(pash)
reader = PdfFileReader(pash)
# reader保存读出需要添加水印的页面 PdfFileReader()
number = reader.getNumPages()
# 获取pdf文件的页数
writer = PdfFileWriter()
# 创建writer对象
for x in range(number):
# for in 遍历每个页面
page = reader.getPage(x)
# page保存读出的每个页面
page.mergePage(water_page)
# 对读出的每个页面粘贴水印
writer.write(open('D:\study\Datawhale\自动化办公-OfficeAutomation/'+file_name,'wb'))
# 保存批量添加水印的pdf文件
9. 文档加密与解密
加密需使用 encrypt 函数
# 加密PDF
from PyPDF2 import PdfFileReader, PdfFileWriter
pdf_reader = PdfFileReader(r'D:\study\Datawhale\自动化办公-OfficeAutomation\top1.pdf')
pdf_writer = PdfFileWriter()
for page in range(pdf_reader.getNumPages()):
pdf_writer.addPage(pdf_reader.getPage(page))
# 添加密码
pdf_writer.encrypt("123123")
with open(r'D:\study\Datawhale\自动化办公-OfficeAutomation\密码.pdf', "wb") as out:
pdf_writer.write(out)
打开“密码”pdf,需要输入密码才能打开。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210622155843890.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1Mzk2NTc3,size_16,color_FFFFFF,t_70#pic_center)
那么如何解密呢,使用 decrypt 函数
# 解密pdf(是在已知密码的情况下)
from PyPDF2 import PdfFileReader, PdfFileWriter
pdf_reader = PdfFileReader(r'D:\study\Datawhale\自动化办公-OfficeAutomation\密码.pdf')
pdf_reader.decrypt('123123')
pdf_writer = PdfFileWriter()
for page in range(pdf_reader.getNumPages()):
pdf_writer.addPage(pdf_reader.getPage(page))
with open(r'D:\study\Datawhale\自动化办公-OfficeAutomation\已经解密.pdf', "wb") as out:
pdf_writer.write(out)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210622155851146.png#pic_center)
解密完成后打开PDF不再需要输入密码,就成功了。