2021-06-23

Python 操作 PDF

相关介绍

1)Python 操作 PDF 会用到两个库,分别是:PyPDF2 和 pdfplumber
其中 PyPDF2 可以更好的读取、写入、分割、合并PDF文件,而 pdfplumber 可以更好的读取 PDF 文件中内容和提取 PDF 中的表格
由于这两个库都不是 Python 的标准库,所以在使用之前都需要单独安装
安装命令如下:

pip install PyPDF
pip install pdfplumber

批量拆分

1)PDF 拆分成几个小的 PDF
大致思路:读取 PDF ,以每个 step 为间隔将 PDF 存成每一个小的文件块,
将小的文件块重新保存为新的 PDF 文件
示例代码:

import  PyPDF2
from PyPDF2 import PdfFileReader, PdfFileWriter
import os
def split_pdf(filename, filepath, save_dirpath, step):
    """
    拆分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)
filename = 'Python.pdf'
filepath = "D:\\Python操作PDF\\Python.pdf"
save_dirpath= 'D:\\Python操作PDF\\Python'
step=60
split_pdf(filename, filepath, save_dirpath, step)

结果:
D:\Python操作PDF\Python\Python.pdf1.pdf
D:\Python操作PDF\Python\Python.pdf2.pdf
D:\Python操作PDF\Python\Python.pdf3.pdf
D:\Python操作PDF\Python\Python.pdf4.pdf
D:\Python操作PDF\Python\Python.pdf5.pdf
D:\Python操作PDF\Python\Python.pdf6.pdf
文件已成功拆分,保存路径为:D:\Python操作PDF\Python
Process finished with exit code 0


image.png
image.png

批量合并

1)大致思路:
确定要合并的 文件顺序
循环追加到一个文件块中
保存成一个新的文件

def concat_pdf(filename, read_dirpath, save_filepath):
    """
    合并多个PDF文件
    @param filename:文件名
    @param read_dirpath:要合并的PDF目录
    @param save_filepath:合并后的PDF文件路径
    @return:
    """
    pdf_writer = PdfFileWriter()
    # 对文件名进行排序
    list_filename = os.listdir(read_dirpath)
    list_filename.sort(key=lambda x: int(x[:-4].replace(filename, "")))
    for filename in list_filename:
        print(filename)
        filepath = os.path.join(read_dirpath, filename)
        # 读取文件并获取文件的页数
        pdf_reader = PdfFileReader(filepath)
        pages = pdf_reader.getNumPages()
        # 逐页添加
        for page in range(pages):
            pdf_writer.addPage(pdf_reader.getPage(page))
    # 保存合并后的文件
    with open(save_filepath, "wb") as out:
        pdf_writer.write(out)
    print("文件已成功合并,保存路径为:"+save_filepath)

提取文字内容

1)提取指定页内容
示例代码:

def extract_text_info(filepath):
    """
    提取PDF中的文字
    @param filepath:文件路径
    @return:
    """
    with pdfplumber.open(filepath) as pdf:
        # 获取第2页数据
        page = pdf.pages[1]
        print(page.extract_text())

2)获取整个文件

ef extract_text_info(filepath):
    """
    提取PDF中的文字
    @param filepath:文件路径
    @return:
    """
    with pdfplumber.open(filepath) as pdf:
        # 获取全部数据
        for page in pdf.pages
            print(page.extract_text())

提取表格内容

1)提取一个表格

def extract_table_info(filepath):
    """
    提取PDF中的图表数据
    @param filepath:
    @return:
    """
    with pdfplumber.open(filepath) as pdf:
        # 获取第18页数据
        page = pdf.pages[17]
        # 如果一页有一个表格,设置表格的第一行为表头,其余为数据
        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')

2)提取多个表格

def extract_table_info(filepath):
    """
    提取PDF中的图表数据
    @param filepath:
    @return:
    """
    # 如果一页有多个表格,对应的数据是一个三维数组
    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])
        print(df_table)
        # df_table.to_csv('dmeo.csv', index=False, encoding='gbk')

提取图片内容

1)安装 PyMuPDF 模块

pip install PyMuPDF

大致·思路:打开文档>遍历元素>正则匹配>生成图片>过滤图片
示例:


"""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)

转换为图片

1)安装 pdf2image模块
2)安装组件
windows 用户需要安装 poppler for Windows,安装链接是:http://blog.alivate.com.au/poppler-windows/
mac 用户,需要安装 poppler for Mac,具体可以参考这个链接:http://macappstore.org/poppler/
示例:

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')

添加水印

主要代码:

watermark = PdfFileReader(watermark_filepath)
watermark_page = watermark.getPage(0)

pdf_reader = PdfFileReader(filepath)
pdf_writer = PdfFileWriter()

for page_index in range(pdf_reader.getNumPages()):
    current_page = pdf_reader.getPage(page_index)
    # 封面页不添加水印
    if page_index == 0:
        new_page = current_page
    else:
        new_page = copy(watermark_page)
        new_page.mergePage(current_page)
    pdf_writer.addPage(new_page)
# 保存水印后的文件
with open(save_filepath, "wb") as out:
    pdf_writer.write(out)

文档加密与解密

1)加密操作

pdf_reader = PdfFileReader(filepath)
pdf_writer = PdfFileWriter()

for page_index in range(pdf_reader.getNumPages()):
    pdf_writer.addPage(pdf_reader.getPage(page_index))

# 添加密码
pdf_writer.encrypt(passwd)
with open(save_filepath, "wb") as out:
    pdf_writer.write(out)

2)解密操作

pdf_reader = PdfFileReader(filepath)
# PDF文档解密
pdf_reader.decrypt('python')

pdf_writer = PdfFileWriter()
for page_index in range(pdf_reader.getNumPages()):
    pdf_writer.addPage(pdf_reader.getPage(page_index))

with open(save_filepath, "wb") as out:
    pdf_writer.write(out)

你可能感兴趣的:(2021-06-23)