首页 > 其他分享 >修改、编辑pdf

修改、编辑pdf

时间:2023-03-03 09:00:09浏览次数:28  
标签:filepath PDF 修改 编辑 dirpath pdf save page

Python 操作 PDF 会用到两个库,分别是:PyPDF2 和 pdfplumber
其中 PyPDF2 可以更好的读取、写入、分割、合并PDF文件,而 pdfplumber 可以更好的读取 PDF 文件中内容和提取 PDF 中的表格
pip install PyPDF2
pip install pdfplumber

1、批量拆分
import os
from PyPDF2 import PdfFileWriter, PdfFileReader

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(filename, filepath, save_dirpath, step=5)

以“易方达中小盘混合型证券投资基金2020年中期报告”为例,整个 PDF 文件一共 46 页,每5页为间隔,最终生成了10个小的 PDF 文件

2、 批量合并
mport os
from PyPDF2 import PdfFileReader, PdfFileWriter

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)
    
concat_pdf(filename, read_dirpath, save_filepath)

3、提取文字内容
import os
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(filepath)



而如果想要提取所有页的文字,只需要改成:
with pdfplumber.open(filepath) as pdf:
 # 获取全部数据
 for page in pdf.pages
     print(page.extract_text())

4、提取表格内容
import os
import pandas as pd
import pdfplumber

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')
        
# 提取表格内容
extract_table_info(filepath)


但是,如果说第 18 页有多个表格内容呢?
因为读取的表格会被存成二维数组,而多个二维数组就组成一个三维数组
遍历这个三位数组,就可以得到该页的每一个表格数据,对应的将 extract_table 函数 改成 extract_tables 即可
# 如果一页有多个表格,对应的数据是一个三维数组
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')

5、提取图片内容
import os
import re
import fitz

def extract_pic_info(filepath, pic_dirpath):
    """
    提取PDF中的图片
    @param filepath:pdf文件路径
    @param pic_dirpath:要保存的图片目录路径
    @return:
    """
    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)
            
# 提取图片内容
extract_pic_info(filepath, pic_dirpath)

6、转换为图片

pip install pdf2image
import os
from pdf2image import convert_from_path, convert_from_bytes

def convert_to_pic(filepath, pic_dirpath):
    """
    每一页的PDF转换成图片
    @param filepath:pdf文件路径
    @param pic_dirpath:图片目录路径
    @return:
    """
    print(filepath)
    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')
        
# PDF转换为图片
convert_to_pic(filepath, pic_dirpath)

7、添加水印
pip install PyPDF2

import os
from copy import copy
from PyPDF2 import PdfFileReader, PdfFileWriter

if __name__ == '__main__':
    dirpath = 'pdf_file'
    filename = '易方达中小盘混合型证券投资基金2020年中期报告'
    filepath = os.path.join(dirpath, filename+'.pdf')
    """添加水印"""
    watermark_filepath = os.path.join(dirpath, 'watermark.pdf')
    save_filepath = os.path.join(dirpath, filename+'【带水印】.pdf')
    """读取PDF水印文件"""
    # 可以先生成一个空白A4大小的png图片,通过 https://mp.weixin.qq.com/s/_oJA6lbsdMlRRsBf6DPxsg 教程的方式给图片加水印,将图片插入到word中并最终生成一个水印PDF文档
    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)

8、文档加密与解密
import os
from PyPDF2 import PdfFileReader, PdfFileWriter

def encrypt_pdf(filepath, save_filepath, passwd='xiaoyi'):
    """
    PDF文档加密
    @param filepath:PDF文件路径
    @param save_filepath:加密后的文件保存路径
    @param passwd:密码
    @return:
    """
    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)
        
# 文档加密
encrypt_pdf(filepath, save_filepath, passwd='xiaoyi')

----------------------------------------------------------------------------
def decrypt_pdf(filepath, save_filepath, passwd='xiaoyi'):
    """
    解密 PDF 文档并且保存为未加密的 PDF
    @param filepath:PDF文件路径
    @param save_filepath:解密后的文件保存路径
    @param passwd:密码
    @return:
    """
    pdf_reader = PdfFileReader(filepath)
    # PDF文档解密
    pdf_reader.decrypt('xiaoyi')

    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)
        
# 文档解密
decrypt_pdf(filepath, save_filepath, passwd='xiaoyi')

 

标签:filepath,PDF,修改,编辑,dirpath,pdf,save,page
From: https://www.cnblogs.com/ht-privete-logs/p/17174347.html

相关文章

  • ArcGIS Pro代码修改布局方向
    privatevoidSwitchPageOrientation(){if(LayoutView.Active==null)return;varlayout=LayoutView.Active.Layout;QueuedTask.Run(()=>{va......
  • 大型网站架构可修改性阅读笔记
    当今互联网时代,大型网站架构的可修改性是至关重要的,因为网站需要不断地更新和改进以适应不断变化的市场和用户需求。在这种背景下,实现可修改性需要考虑多个因素,如架构设计......
  • 完全相同的两条数据如何进行修改
    1.背景​ 前几日打工的时候发现的一个神奇的bug当我在NAVCATE(sqlserver)中用鼠标修改一条数据时会同时修改另一条数据,当时瞬间懵逼,然后定睛一看妈的这个表建表的时候没给i......
  • DDL语言——库和表的创建、修改、删除
    DDL语言DDL:DataDefinitionLanguageDDL允许用户定义数据,也就是创建表、删除表、修改表结构这些操作。通常,DDL由数据库管理员执行。下面的中括号【】内的内容是可选的。......
  • 软件质量之可修改性
    软件的可修改性:软件质量属性中的可修改性是指容易修改的能力,其包括修正,改进和用户需求的变化。今天阅读了《大型网站技术架构:核心原理与案例分析》,里面没有明确的......
  • Ubuntu20.04修改环境变量失误导致开机循环——解决方法以及保存profile
    gedit/etc/profile配置Ubuntu环境变量时出现失误导致开机时输入密码后重复开机无法进入图画界面解决方法:ctrl+alt+(F1~F6),我的是ctrl+alt+F2进入界面输入login(用户名)和......
  • GitLab修改群组报错“路径已经被使用”
    GitLab修改群组报错“路径已经被使用” 1、问题背景在GitLab修改群组时,遇到如下报错“路径已经被使用” 2、原因分析根据报错提示信息,新建的群组路径已经被占用......
  • Linux-vi/vim编辑器
    vim开始是命令模式1)i,a,o进入输入模式,ESC回到命令模式2):进入底线命令模式,回车结束运行最后输入:wq储存后离开vi如建立文件vimwenyu.txt直接输入vi文件名就......
  • Docker 三节点 MongoDB 修改集群IP
    需求背景因为业务需要服务器IP变更,记录一下mongdb三节点变更的办法,我这边是在vm上进行测试原IP:172.16.16.81新IP:172.16.16.84修改MongoDB集群IP#登录其中......
  • EAS客户端修改新增或编辑窗口为弹窗或者新的tab页签
    @OverrideprotectedStringgetEditUIModal(){returnUIFactoryName.EDITWIN;//UIFactoryName.NEWWIN为弹窗模式//UIFactoryName.NEWTAB......