自动化办公:4、 Python操作PDF

2023-11-11

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

在这里插入图片描述

拓展一下:此处可以结合前面 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')

在这里插入图片描述

如果当页不止一个表格,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,需要输入密码才能打开。
在这里插入图片描述

那么如何解密呢,使用 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)

在这里插入图片描述

解密完成后打开PDF不再需要输入密码,就成功了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自动化办公:4、 Python操作PDF 的相关文章

  • 如何使用 django (python) 和 s3 上传文件?

    我正在寻找一种将文件上传到 s3 的方法 我正在使用 django 我目前正在使用亚马逊的 python 库进行上传以及以下代码 View def submitpicture request fuser request session lo
  • 如何移动我的图像? python 3.10.4 pygame

    我会移动我的图像 图像是matiskinfinal png 我尝试将像素添加到 x 或其他我不知道它是什么的东西 因为我真的是 python 的初学者 pygame但是是 x x 变化 但图像没有移动 import os import py
  • 在 Python 中绘制分类数据的三个维度

    我的数据包含三个我试图可视化的分类变量 城市 五个之一 职业 四种之一 血型 四种之一 到目前为止 我已经成功地以一种我认为易于使用的方式对数据进行了分组 import numpy as np pandas as pd Make data
  • Spyder 导入模块出错

    我正在尝试在 Spyder 中使用 sklearn 一开始 当我尝试导入它时 我收到 ImportError No module named sklearn 然后我用 PYTHONPATH 管理器设置 PATH 然后使用工具菜单中的 更新模
  • 使用 Pymongo 从 Windows 连接到 AWS 实例上的 MongoDB

    此行反复抛出错误 client MongoClient ec2 12 345 67 89 us east 2 compute amazonaws com 27017 ssl True ssl keyfile C mongo pem 由于显而
  • 强制 Java 最低版本以“java -version:”运行在 Windows 上不起作用

    我想强制应用程序运行的 JVM 最低版本为 1 6 或更高版本 即 1 6 我的理解是 您可以使用 version 命令行参数来执行此操作 我尝试了一下 在Linux下似乎可以正常工作 但在Windows下却不行 LINUX 我在 Linu
  • Windows Defender 检测 Python EXE 为木马

    我制作了一个 Python 脚本 将 Windows 目录以 zip 形式邮寄给我 我使用 sched 模块添加了一个调度程序 每小时重复一次 我试图制作一个简单的同步应用程序供个人使用 在 Windows 启动时启动 我使用将其转换为 e
  • 检测/删除 Python 2 + GTK 中不成对的代理字符

    在Python 2 7中我可以成功转换Unicode字符串 abc udc34xyz 转换为 UTF 8 结果是 abc xed xb0 xb4xyz 但是当我将 UTF 8 字符串传递给例如时 pango parse markup or
  • Flask 中的 import 和 extends 有什么区别?

    我正在阅读 Flask Web 开发 在例4 3中 extends base html import bootstrap wtf html as wtf 我想知道 extends 和 import 有什么区别 我认为它们在用法上很相似 在什
  • python:是否有用于对输入流进行分块的库函数?

    我想对输入流进行分块以进行批处理 给定一个输入列表或生成器 x in 1 2 3 4 5 6 我想要一个能够返回该输入块的函数 说 如果chunk size 4 then x chunked 1 2 3 4 5 6 这是我一遍又一遍地做的事
  • 如何为 Python 中的应用程序设置专用屏幕区域?

    MS OneNote 就是一个很好的例子 它可以选择固定在屏幕的一侧 并将所有其他窗口推到一侧 当最大化或调整其他窗口大小时 它们只能扩展到 OneNote 的边缘 Python 使用 Tkinter 或其他模块是否具有此功能 感谢您的帮助
  • 使用 C 语言使用 strftime() 获取缩写时区

    我看过this https stackoverflow com questions 34408909 how to get abbreviated timezone and this https stackoverflow com ques
  • PyCharm - 如何挂起所有线程

    我们使用 PyCharm 5 0 1 进行多线程调试 当它在断点处停止时 只有特定线程停止 而所有其他线程继续 这使得 冻结时刻 和检查参数值以及其他线程的当前状态变得困难 当其中一个线程在断点处停止时 是否可以挂起所有线程 这在最新的 P
  • 如何在 Sublime 2 REPL Mac 中运行 Python 3

    我的问题如下 我安装了 sublime 2 和 sublime repl 插件 一切正常 我唯一需要的是更改在控制台内置的 sublimerepl 上运行的 python 版本 我的意思是 我有 python 2 7 5 预先安装了 mav
  • 如何修改 contenteditable 元素的innerHTML

    我使用 Selenium 与 Chrome driver 和 python3 6 来测试网站 我在网页中有代码片段如下 div class 3F6QL 2WovP div class 39LWd Type a message div div
  • Python 中的十进制到二进制半精度 IEEE 754

    我只能使用以下命令将十进制转换为二进制单精度 IEEE754struct pack模块 或者使用相反的方法 float16 或 float32 numpy frombuffer 是否可以使用 Numpy 将十进制转换为二进制半精度浮点数 我
  • 有适用于 Windows 的 Bonjour SDK 吗?

    我想知道如何在 Windows 上实现 bonjour 以便我可以在 Windows 上设置服务器并使用 iphone 客户端 中的 bonjour 服务访问 Windows 服务器 中的文件 谁能告诉我我们是否有适用于 Windows 的
  • (de)从 CSV 序列化为对象(或者最好是类型对象的列表)

    我是一名 C 程序员 试图学习 C 似乎有一些内置的对象序列化 但我在这里有点不知所措 我被要求将测试数据从 CSV 文件加载到对象集合中 CSV 比 xml 更受青睐 因为它更简单且更易于人类阅读 我们正在创建测试数据来运行单元测试 该集
  • 在至少 7 天内连续三天登录该产品的用户

    我有一个用于用户参与的数据框 df 如下所示 time stamp user id 2013 01 01 10 05 23 1 2013 01 03 16 35 23 1 2013 01 06 11 06 35 1 2013 01 10 1
  • 在Python中从CSV文件中获取随机行并找到相应的单词,就像测验一样

    抱歉标题含糊不清 想不出更好的表达方式 我有一个包含德语 英语单词的 CSV 文件 如下所示 Ja Yes Nein No Katze Cat 我希望我的 python 脚本从 CSV 文件中打印一个随机的德语单词 并要求他们输入英语单词

随机推荐

  • curl命令多行执行

    window环境执行 分割符是 curl http surge jdfmgt com core r coreAutoInitiateMain testAddData X POST d objectCreateCount 1 typeCode
  • leecode151 反转字符串中的单词(附有手写思路)

    丑陋的思路 StringJoiner版本 前言 刚开始我是用StringJoiner写的 因为我看到这个每个元素之间有一个固定的空格我就想着能够直接用这个StringJoiner来进行书写 但是我提交的时候说这个StringJoiner无法
  • leetcode分类刷题:哈希表(Hash Table)(三、循环存在问题)

    1 当需要快速判断某元素是否出现在序列中时 就要用到哈希表了 2 本文针对的总结题型为给定的序列或需要构造的序列中是否存在循环 与 160 相交链表 141 环形链表 142 环形链表 II的题型一样 202 快乐数 这道题还考察如何对正整
  • AndroidStudio内各个模拟器的安装位置

    As中 下载的本地模拟器的位置位于 android avd目录下 当该目录被删除后 打开AndroidStudio的AVD 会发现所有的下载过的模拟器都没有了
  • 【2021-04-07华为机试】第二题:各任务执行完毕需要的时间

    题目 给定N个任务 1 lt N lt 100 任务编号从0开始顺序累加 这N个任务在系统中排队顺序执行 每个任务的自身执行时间为非负整数 依次为t1 t2 tn 部分任务之间存在依赖关系的 某任务所依赖的任务如果没有执行 则该任务需要重回
  • IDEA 中设置自动补全方法

    最近转用 IDEA 但习惯于 Eclipse 的快捷键和快捷输入 以下是在 IDEA 中增添快捷键和快捷输入的方法 1 File Settings 2 Editor Live Templates Add Template Group gt
  • Ant Design Pro新增页面步骤

    新增页面步骤 根据页面结构规范创建页面文件后 接着在项目根目录寻找config文件夹下的routes js中添加该页面项的路由配置 如创建子路由则在父路由下定义routes属性 值为一个数组 数组中为该路由的子路由路由配置项 如下图 exp
  • 微信隐藏功能系列3:微信关闭朋友圈广告推送

    我们使用微信好多年了 这个工具不仅仅在社交上为我们带来许多好处 工作 消费中也是给我们带来不少方便之处 大家对微信隐藏功能了解多少 本期分享 微信关闭朋友圈广告推送 虽然微信为我们带来许多方便 但令人不适的东西也是有的 广告就是其中之一 特
  • python如何创建二维数组

    关于python中的二维数组 主要有list和numpy array两种 好吧 其实还有matrices 但它必须是2维的 而numpy arrays ndarrays 可以是多维的 两者可以相互转化 下边是两者区别 数组list gt g
  • linux va_start 编译,如何把unix 下的c程序移植到suse linux下,编译出错?

    FILE gfp out stdout 第45行 报 err c 45 error initializer element is not constant include int err set info char ps error typ
  • c++:STL容器及其接口(string、vector、deque、stack、queue、list、set/multiset、map/multimap)

    STL Standard Template Library 标准模板库 目录 一 STL 六大组件简介 二 string容器 2 1 string容器基本概念 2 2 string 构造函数 2 3 string基本赋值操作 2 4 str
  • 第五章可视化

    1散点图 1 代码 A 未处理异常值 import ggplot as gp import pandas as pd import numpy as np crime pd read csv crimeRatesByState2005 cs
  • git交互式暂存 git add -i 这个骚操作存在的意义为何

    文章目录 启用交互暂存 暂存常用的命令 交互暂存的意义在哪 应该场景的进一步说明 你已经能非常熟练的使用 git了 暂存是其中最基本的操作了 交互暂存是暂存的高级用法 虽然可以不用 但是在某些特定场景下 可以提高我们的工作效率 下边请看详细
  • Opencv3.1+python2.7的CentOS7安装

    time Jan 13 2016 20 29 author duanxxnj 163 com 花了两天时间才把Openv3 1的Python安装完成 中间遇到了好多奇怪的错误 在这里记录下整个安装过程 系统环境 Duanxx CentOS
  • js debugger的两种方式

    第一种 在js代码中加上debugger class ReactiveEffect constructor fn scheduler this fn fn this scheduler scheduler this active true
  • HDU - 6126 Give out candies

    Give out candies 题解 第一次遇见这样处理的网络流模型 将问题转换成最小割问题 具体的题解参考自 传送门 先将每个人的拆成m个人 然后s向第1人连边流量为inf 第i个人向第i 1个人连边 流量为 3000 w 将t视为每组
  • 自用IdeaVim配置

    具体配置如下 nnoremap
  • STL之set集合容器

    set集合容器实现了红黑树 Red Black Tree 的平衡二叉检索树的的数据结构 在插入元素时 它会自动调整二叉树的排列 把该元素放到适当的位置 以确保每个子树根节点的键值大于左子树所有节点的键值 而小于右子树所有节点的键值 另外 还
  • 校门外的树C语言详解

    题目描述 某校大门外长度为 l 的马路上有一排树 每两棵相邻的树之间的间隔都是 1 米 我们可以把马路看成一个数轴 马路的一端在数轴 0 的位置 另一端在 l 的位置 数轴上的每个整数点 即 0 1 2 l 都种有一棵树 由于马路上有一些区
  • 自动化办公:4、 Python操作PDF

    1 相关介绍 PyPDF2 读取 写入 分割 合并PDF文件 pdfplumber 读取 PDF 文件中内容和提取 PDF 中的表格 pip install PyPDF2 pip install pdfplumber 2 批量拆分 将一个完