pdf各种处理 PDF 的实用代码:PyPDF2、PDFMiner、pdfplumber

你不懂得安排自己的人生,会有很多人帮你安排,他们需要你做的事。

PDF文件我们经常用,尤其是这两个场景:

  • 下载参考资料,如各类报告、文档

    分享只读资料,方便传播同时保留源文件

场景和模块

所以,对于PDF文件,常见的需求也就是两类:

  1. 处理文件本身,属于文件页面级操作,如合并/分拆PDF页面、加/解密、加/去水印;

    处理文件内容,属于内容级操作,如提取文字、表格数据、图表等。

目前Python用于处理PDF的模块,主要有3个:

  • PyPDF2:模块成熟,最后一次更新在2年前,适合页面级操作,文字提取效果较差。

    PDFMiner:擅长文字抽取,目前主分支已停止维护,取而代之的是pdfminer.six

    pdfplumber:基于pdfminer.six的文本内容抽取工具,使用门槛更低,如支持表格提取。

实战中,可以根据需求的类型选择模块。如果是页面级的操作,就用PyPDF2,如果需要内容抽取,优先使用pdfplumber。

对应的模块安装:

  pip install pypdf2pip install pdfminer.sixpip install pdfplumber

下面按使用场景演示3个模块的使用。

PyPDF2

PyPDF2的主要能力在页面级操作,比如:

  • 获取PDF文档基本信息

    PDF分割及合并

    PDF的旋转及排序

    PDF加水印及去水印

    PDF加密及解密

PyPDF2的核心两个类是PdfFileReader和PdfFileWriter,完成PDF文件的读写操作。

获取PDF文档基本信息

import pathlib
from PyPDF2 import PdfFileReader
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/002pdf')
f_path = path.joinpath('2020-新冠肺炎疫情对中国连锁餐饮行业的影响调研报告-中国连锁经营协会.pdf')
with open(f_path, 'rb') as f:pdf = PdfFileReader(f)info = pdf.getDocumentInfo()cnt_page = pdf.getNumPages()is_encrypt = pdf.getIsEncrypted()
print(f'''
作者: {info.author}
创建者: {info.creator}
制作者: {info.producer}
主题: {info.subject}
标题: {info.title}
总页数: {cnt_page}
是否加密: {is_encrypt}
''')


PDF分割及合并

import pathlib
from PyPDF2 import PdfFileReader, PdfFileWriter
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/002pdf')
f_path = path.joinpath('2020-新冠肺炎疫情对中国连锁餐饮行业的影响调研报告-中国连锁经营协会.pdf')
out_path = path.joinpath('002pdf_split_merge.pdf')
out_path_1 = path.joinpath('002pdf_split_half_front.pdf')
out_path_2 = path.joinpath('002pdf_split_half_back.pdf')
# 把文件分为两半
with open(f_path, 'rb') as f, open(out_path_1, 'wb') as f_out1, open(out_path_2, 'wb') as f_out2:pdf = PdfFileReader(f)pdf_out1 = PdfFileWriter()pdf_out2 = PdfFileWriter()cnt_pages = pdf.getNumPages()print(f'共 {cnt_pages} 页')for i in range(cnt_pages):if i <= cnt_pages //2:pdf_out1.addPage(pdf.getPage(i))else:pdf_out2.addPage(pdf.getPage(i))pdf_out1.write(f_out1)pdf_out2.write(f_out2)
# 再把后半个文件与前半个文件合并,后半个文件在前
with open(out_path, 'wb') as f_out:cnt_f, cnt_b = pdf_out1.getNumPages(), pdf_out2.getNumPages()pdf_out = PdfFileWriter()for i in range(cnt_b):pdf_out.addPage(pdf_out2.getPage(i))for i in range(cnt_f):pdf_out.addPage(pdf_out1.getPage(i))pdf_out.write(f_out)


PDF的旋转及排序

import pathlib
from PyPDF2 import PdfFileReader, PdfFileWriter
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/002pdf')
f_path = path.joinpath('2020-新冠肺炎疫情对中国连锁餐饮行业的影响调研报告-中国连锁经营协会.pdf')
out_path = path.joinpath('002pdf_rotate.pdf')
with open(f_path, 'rb') as f, open(out_path, 'wb') as f_out:pdf = PdfFileReader(f)pdf_out = PdfFileWriter()page = pdf.getPage(0).rotateClockwise(90)pdf_out.addPage(page)# 把第二页放到前面pdf_out.addPage(pdf.getPage(2))page = pdf.getPage(1).rotateCounterClockwise(90)pdf_out.addPage(page)pdf_out.write(f_out)


PDF加水印及去水印

加图片水印,其实就是在页面中增加一个透明背景的图片,通过页面的mergePage方法即可完成。

import pathlib
from PyPDF2 import PdfFileReader, PdfFileWriter
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/002pdf')
f_path = path.joinpath('2020-新冠肺炎疫情对中国连锁餐饮行业的影响调研报告-中国连锁经营协会.pdf')
wm_path = path.joinpath('watermark.pdf')
en_path = path.joinpath('002pdf_with_watermark_en.pdf')
out_path = path.joinpath('002pdf_with_watermark.pdf')
with open(f_path, 'rb') as f, open(wm_path, 'rb') as f_wm, open(out_path, 'wb') as f_out:pdf = PdfFileReader(f)pdf_wm = PdfFileReader(f_wm)pdf_out = PdfFileWriter()wm_cn_page = pdf_wm.getPage(0)wm_en_page = pdf_wm.getPage(1)cnt_pages = pdf.getNumPages()for i in range(cnt_pages):page = pdf.getPage(i)page.mergePage(wm_cn_page)pdf_out.addPage(page)pdf_out.write(f_out)


去水印,就比较复杂,需要根据不同情况具体分析。因为水印可能是文字、图片或者各种组合,关键是识别出特征。

去水印的3个常见思路参考:

  • 找到特征词后替换,适合英文文档,但不适用于中文等CJK字符。

    把PDF页转成图片后,用图像算法去水印,但这样会破坏文件原信息结构。

    根据水印大小位置特征,找到所有元素后删除。这是更推荐的方式。

第3种方式效果最好,但如果碰到一些复杂的文档水印,就非常考验耐心。

你得一个个识别操作命令,一边替换一边检查效果,直到水印成功去除。

但,未必剩下的所有页都可以用同样特征模式来消除,因为这份PDF可能经过多人加水印,已经包含多种加水印方式。

所以,去水印并没有一种100%安全有效(不错删信息)且通用的方法。

加水印、去水印本质上是一种攻防策略。

比如一些工具推出去水印功能,一旦公开,加水印方就能识别并避开它的去除方法。

最后,尊重版权,是每个人应有的态度。

除了学习外,正式使用时,应该遵守内容创作方的规则。

PDF加密解密

PDF里的密码,分为用户密码和所有者密码。

PyPDF2里提供了基本的加密功能,“防君子不防小人”。

如果打开PDF文件后,复制了新文件,那新文件就不受所有者密码的约束,可被修改。

import pathlib
from PyPDF2 import PdfFileReader, PdfFileWriter
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/002pdf')
f_path = path.joinpath('2020-新冠肺炎疫情对中国连锁餐饮行业的影响调研报告-中国连锁经营协会.pdf')
out_path_encrypt = path.joinpath('002pdf_encrypt.pdf')
out_path_decrypt = path.joinpath('002pdf_decrypt.pdf')
with open(f_path, 'rb') as f, open(out_path_encrypt, 'wb') as f_out:pdf = PdfFileReader(f)pdf_out = PdfFileWriter()cnt_pages = pdf.getNumPages()for i in range(cnt_pages):page = pdf.getPage(i)pdf_out.addPage(page)pdf_out.encrypt('123456', owner_pwd='654321')pdf_out.write(f_out)
# 重新读取加密文件并生成解密文件
with open(out_path_encrypt, 'rb') as f, open(out_path_decrypt, 'wb') as f_out:pdf = PdfFileReader(f)if not pdf.isEncrypted:print('文件未被加密')else:success = pdf.decrypt('123456')# if not success:pdf_out = PdfFileWriter()pdf_out.appendPagesFromReader(pdf)pdf_out.write(f_out)


pdfminer.six

PDFMiner的操作门槛比较高,需要部分了解PDF的文档结构模型,适合定制开发复杂的内容处理工具。

平时直接用PDFMiner比较少,这里只演示基本的文档内容操作:

import pathlib
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfpage import PDFPage
from pdfminer.pdfinterp import PDFResourceManager
from pdfminer.pdfinterp import PDFPageInterpreter
from pdfminer.pdfdevice import PDFDevice
from pdfminer.layout import LAParams, LTTextBox, LTFigure, LTImage
from pdfminer.converter import PDFPageAggregator
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/002pdf')
f_path = path.joinpath('2020-新冠肺炎疫情对中国连锁餐饮行业的影响调研报告-中国连锁经营协会.pdf')
with open(f_path, 'rb') as f:parser = PDFParser(f)doc = PDFDocument(parser)rsrcmgr = PDFResourceManager()laparams = LAParams()device = PDFPageAggregator(rsrcmgr, laparams=laparams)interpreter = PDFPageInterpreter(rsrcmgr, device)for page in PDFPage.create_pages(doc):interpreter.process_page(page)layout = device.get_result()for x in layout:# 获取文本对象if isinstance(x, LTTextBox):print(x.get_text().strip())# 获取图片对象if isinstance(x,LTImage):print('这里获取到一张图片')# 获取 figure 对象if isinstance(x,LTFigure):print('这里获取到一个 figure 对象')


虽然pdfminer使用门槛较高,但遇到复杂情况,最后还得用它。目前开源模块中,它对PDF的支持应该是最全的了。

下面这个pdfplumber就是基于pdfminer.six开发的模块,降低了使用门槛。

pdfplumber

相比pdfminer.six,pdfplumber提供了更便捷的PDF内容抽取接口。

日常工作中常用的操作,比如:

  • 提取PDF内容,保存到txt文件

    提取PDF中的表格到Excel

    提取PDF中的图片

    提取PDF中的图表

提取PDF内容,保存到txt文件

import pathlib
import pdfplumber
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/002pdf')
f_path = path.joinpath('2020-新冠肺炎疫情对中国连锁餐饮行业的影响调研报告-中国连锁经营协会.pdf')
out_path = path.joinpath('002pdf_out.txt')
with pdfplumber.open(f_path) as pdf, open(out_path ,'a') as txt:for page in pdf.pages:textdata = page.extract_text()txt.write(textdata)


提取PDF中的表格到Excel

import pathlib
import pdfplumber
from openpyxl import Workbook
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/002pdf')
f_path = path.joinpath('2020-新冠肺炎疫情对中国连锁餐饮行业的影响调研报告-中国连锁经营协会.pdf')
out_path = path.joinpath('002pdf_excel.xlsx')
wb = Workbook()
sheet = wb.active
with pdfplumber.open(f_path) as pdf:for i in range(19, 22):page = pdf.pages[i]table = page.extract_table()for row in table:sheet.append(row)
wb.save(out_path)

上面用到了openpyxl的功能创建了一个Excel文件,后面会有单独文章介绍它。

提取PDF中的图片

import pathlib
import pdfplumber
from PIL import Image
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/002pdf')
f_path = path.joinpath('2020-疫情影响下的中国社区趋势研究-艾瑞.pdf')
out_path = path.joinpath('002pdf_images.png')
with pdfplumber.open(f_path) as pdf, open(out_path, 'wb') as fout:page = pdf.pages[10]# for img in page.images:im = page.to_image()im.save(out_path, format='PNG')imgs = page.imagesfor i, img in enumerate(imgs):size = img['width'], img['height']data = img['stream'].get_data()out_path = path.joinpath(f'002pdf_images_{i}.png')with open(out_path, 'wb') as fimg_out:fimg_out.write(data)

上面用到了PIL(Pillow)的功能处理图片。

提取PDF中的图表

图表与图像不同,指的是类似直方图、饼图之类的数据生成图。

import pathlib
import pdfplumber
from PIL import Image
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/002pdf')
f_path = path.joinpath('2020-新冠肺炎疫情对中国连锁餐饮行业的影响调研报告-中国连锁经营协会.pdf')
out_path = path.joinpath('002pdf_figures.png')
with pdfplumber.open(f_path) as pdf, open(out_path, 'wb') as fout:page = pdf.pages[7]im = page.to_image()im.save(out_path, format='PNG')figures = page.figuresfor i, fig in enumerate(figures):size = fig['width'], fig['height']crop = page.crop((fig['x0'], fig['top'], fig['x1'], fig['bottom']))img_crop = crop.to_image()out_path = path.joinpath(f'002pdf_figures_{i}.png')img_crop.save(out_path, format='png')im.draw_rects(page.extract_words(), stroke='yellow')im.draw_rects(page.images, stroke='blue')im.draw_rects(page.figures)
im # show in notebook

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/478938.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文浅尝 - ESWC2020 | ESBM:一个面向实体摘要的评测集

本文转载自公众号&#xff1a;南大Websoft。实体摘要&#xff08;Entity Summarization&#xff09;&#xff0c;是知识图谱研究与应用中的一个关键问题。南京大学Websoft团队为此制作了一个评测集&#xff0c;称作ESBM&#xff0c;是目前可以公开获取的规模最大的评测集。这项…

Android官方开发文档Training系列课程中文版:手势处理之滚动动画及Scroller

原文地址&#xff1a;http://android.xsoftlab.net/training/gestures/scroll.html 在Android中&#xff0c;滑动经常由ScrollView类来实现。任何超出容器边界的布局都应该将自己内嵌在ScrollView中&#xff0c;以便提供可滚动的视图效果。自定义滚动只有在特定的场景下才会被…

美团在O2O场景下的广告营销

美团作为中国最大的在线本地生活服务平台&#xff0c;覆盖了餐饮、酒店、旅行、休闲娱乐、外卖配送等方方面面生活场景&#xff0c;连接了数亿用户和数百万商户。如何帮助本地商户开展在线营销&#xff0c;使得他们能快速有效地触达目标用户群体提升经营效率&#xff0c;是美团…

LeetCode 202. 快乐数(快慢指针)

1. 题目 2. 解题 一个数经过若干次各位数平方和后&#xff0c;会等于它自己使用类似环形链表的快慢指针法&#xff0c;最终快慢指针相遇&#xff0c;若不为1则是不快乐数 class Solution { public:int bitSquareSum(int n) {int sum 0, bit;while(n > 0){bit n % 10;su…

全栈深度学习第4期: 机器学习岗位区别与团队管理

一起追剧鸭简介Berkeley全栈深度学习追剧计划是由夕小瑶的卖萌屋发起的优质公开课打卡项目&#xff0c;通过微信群为同期追剧的小伙伴提供交流平台。关于该计划的详请见这里。Berkeley深度学习追剧群目前已有1000小伙伴加入&#xff0c;公众号后台回复口令 深度学习追剧 入群。…

会议交流 | DataFunCon 线上大会 - 知识图谱专题论坛

OpenKG开放知识图谱&#xff08;简称 OpenKG&#xff09;旨在促进中文知识图谱数据的开放与互联&#xff0c;促进知识图谱和语义技术的普及和广泛应用。点击阅读原文&#xff0c;进入 OpenKG 博客。

Android官方开发文档Training系列课程中文版:手势处理之多点触控处理

原文地址&#xff1a;http://android.xsoftlab.net/training/gestures/multi.html 多点触控是指多个手指同时触摸屏幕的情况。这节课主要学习如何检测多点触控手势。 记录多个触控点 当多根手指同时触碰到屏幕时&#xff0c;系统会产生以下触摸事件&#xff1a; ACTION_DOW…

我国政务大数据政策的文本分析:推进逻辑与未来进路

原文地址&#xff1a;https://www.sohu.com/a/238844423_99983415 摘要&#xff1a;[目的/意义]从已颁布政策文件中找出我国推进政务大数据发展和应用的内在逻辑, 为优化未来的政策路径提供对策建议。[方法/过程]通过政府门户网站收集189条有效政策文本, 综合运用词频分析软件…

Flutter原理与实践

Flutter是Google开发的一套全新的跨平台、开源UI框架&#xff0c;支持iOS、Android系统开发&#xff0c;并且是未来新操作系统Fuchsia的默认开发套件。自从2017年5月发布第一个版本以来&#xff0c;目前Flutter已经发布了近60个版本&#xff0c;并且在2018年5月发布了第一个“R…

LeetCode 522. 最长特殊序列 II

1. 题目 给定字符串列表&#xff0c;你需要从它们中找出最长的特殊序列。 最长特殊序列定义如下&#xff1a;该序列为某字符串独有的最长子序列&#xff08;即不能是其他字符串的子序列&#xff09;。 子序列可以通过删去字符串中的某些字符实现&#xff0c;但不能改变剩余字…

论文浅尝 - 计算机工程 | 大规模企业级知识图谱实践综述

本文转载自公众号&#xff1a;计算机工程。大规模企业级知识图谱实践综述王昊奋, 丁军, 胡芳槐, 王鑫中文摘要&#xff1a;近年来&#xff0c;知识图谱及其相关技术得到快速发展&#xff0c;并被广泛应用于工业界各种认知智能场景中。在简述知识图谱相关研究的基础上&#xff0…

python实现拆分、合并、删除pdf

PDF&#xff08;Portable Document Format&#xff09;&#xff0c;中文名称便携文档格式是我们经常会接触到的一种文件格式&#xff0c;文献、文档…很多都是PDF格式。它以格式稳定的优势&#xff0c;使得我们在打印、分享、传输过程中能够最优的保持原有色彩和格式。PDF是以P…

Android官方开发文档Training系列课程中文版:手势处理之拖拽或缩放

原文地址&#xff1a;https://developer.android.com/training/gestures/scale.html 这节课主要学习如何使用触摸手势来拖动、放大屏幕上的对象。 拖动对象 如果你的重点在Android 3.0以上的版本&#xff0c;那么你可以使用内置的拖拽事件监听器View.OnDragListener。 触摸手…

2021年了,对话系统凉透了吗?

文 | 兔子酱编 | 夕小瑶大家好&#xff0c;我是可盐可甜的兔子酱&#xff0c;一枚卖萌屋的资深潜水小编&#xff0c;今天终于有了自己的第一篇文章&#xff0c;希望耗时一周撰写的本文能让大家有所收获~这篇文章&#xff0c;算是对自己在头部大厂2年算法岗炼丹经历的一个经验浓…

前端可用性保障实践

本文基于已发表在Infoq的“美团收银台前端可用性保障实践”一文编辑而成。 一般可用性都是说后端服务的可用性&#xff0c;都说我们的服务可用性到了几个9&#xff0c;很少有人把可用性放到前端来。其实对于任何一个有UI交互流程的业务&#xff0c;都会有前端服务可用性&#x…

LeetCode 762. 二进制表示中质数个计算置位

1. 题目 给定两个整数 L 和 R &#xff0c;找到闭区间 [L, R] 范围内&#xff0c;计算置位位数为质数的整数个数。 &#xff08;注意&#xff0c;计算置位代表二进制表示中1的个数。例如 21 的二进制表示 10101 有 3 个计算置位。还有&#xff0c;1 不是质数。&#xff09; …

报名通道开启 | 顶会 ICLR 2021:医疗对话生成与自动诊断国际竞赛,邀你来战!...

ICLR&#xff0c;2013 年由深度学习三巨头中的Yoshua Bengio 和 Yann LeCun 牵头创办&#xff0c;已受到研究者和开发者的广泛认可&#xff0c;是当之无愧的深度学习领域顶级会议。今年&#xff0c;由中山大学、加利福尼亚大学圣迭戈分校和腾讯天衍实验室等组织联合举办的医疗对…

论文浅尝 | 图神经网络的对抗攻击和防御相关文献集

本文转载自公众号&#xff1a;专知。作者&#xff1a;Wei Jin。导读&#xff1a;本资源整理了关于图形数据或GNN(图形神经网络)上的对抗攻击和防御的论文链接。并对其进行分类。目录Survey PapersAttack PapersDefense PapersCertified Robustness Papers地址连接&#xff1a;h…

Android官方开发文档Training系列课程中文版:手势处理之ViewGroup的事件管理

原文地址&#xff1a;https://developer.android.com/training/gestures/viewgroup.html 在ViewGroup中处理触摸事件要格外小心&#xff0c;因为在ViewGroup中有很多子View&#xff0c;而这些子View对于不同的触摸事件来说是不同的目标。要确保每个View都正确的接收了相应的触…

李宏毅《机器学习》作业班+带打比赛

人工智能来势汹汹&#xff0c;学习人工智能该从哪里开始呢&#xff1f;人工智能的学习路径又是怎样的&#xff1f;须知入门人工智能第一步就是机器学习。但是&#xff0c;在上千份同学的学习反馈中&#xff0c;我们发现了2个人工智能学习领域的痛难点&#xff1a;1、课程偏理论…