资讯动态

Python 操作 PDF 文件实战:文本提取、页面旋转、加密与水印(Python-100-Days 第 27 天)

发布时间:2026/10/1 9:36:17 来源:尧图企业网站定制
文档教程【免费下载链接】Python-100-DaysPython - 100天从新手到大师项目地址https://gitcode.com/GitHub_Trending/py/Python-100-Days点击查看免费下载本指南基于 Python-100-Days 项目 Day21-30/27.Python操作PDF文件.md 展开系统讲解如何用PyPDF2从 PDF 中提取文本、旋转与叠加页面、加密文档、批量添加水印以及如何用reportlab从零创建 PDF。读完本文你将掌握 Python 处理 PDF 的两大核心链路——读解析既有文档与写生成新文档并能直接将其迁移到报表导出、合同批量处理等真实业务场景。PDF 是 Portable Document Format便携式文档格式的缩写通常使用.pdf作为扩展名。在日常开发工作中最容易遇到的两个任务就是从 PDF 中读取文本内容以及用已有的内容生成 PDF 文档。前者对应文档解析与数据提取后者对应报表生成与文档输出。从 PDF 中提取文本PyPDF2 入门在 Python 中可以使用三方库PyPDF2来读取 PDF 文件安装命令如下pip install PyPDF2需要说明的是PyPDF2无法从 PDF 文档中提取图像、图表或其他媒体对象它只负责提取文本并将结果作为 Python 字符串返回。因此它非常适合做正文内容的批量抓取但不适合做版面级的信息还原。读取并打印全部文本的代码如下import PyPDF2 reader PyPDF2.PdfReader(test.pdf) for page in reader.pages: print(page.extract_text())核心 API 要点PyPDF2.PdfReader(文件路径)创建 PDF 读取器对象对应旧版 API 中的PdfFileReaderreader.pages一个可迭代的页面集合每个元素是一个页面对象PageObjectpage.extract_text()提取当前页的文本返回字符串。提取失败的场景与替代方案PyPDF2并不是什么样的 PDF 文档都能成功提取文字尤其是扫描版 PDF本质是图片和中文内容排版复杂的文档提取效果可能很差甚至返回空字符串这个问题目前并没有特别通用的解决方法。针对这类场景可以采用下面的替代方案使用三方的命令行工具pdfminer.six它对文本布局和编码的处理更为精细安装与用法如下pip install pdfminer.six pdf2text.py test.pdf对于扫描版 PDF可先用 OCR光学字符识别库将其转为可检索文本再交给正则或自然语言处理流程使用本项目 Day61-65 之后的爬虫与数据采集课程中也有类似的处理思路。若只是验证提取效果仓库内已有一份真实的加密 PDF 样本 公开课/第05次公开课-算法入门系列1-周而复始/code/Python_Tricks_encrypted.pdf可用来测试读取与解密流程若文件带密码读取前需调用reader.decrypt(密码)完成解锁。旋转和叠加页面PageObject 的变换能力通过创建PdfReader对象读取 PDF 文档后其页面对象支持多种版面变换操作。以将偶数页顺时针旋转 90 度、奇数页逆时针旋转 90 度为例reader PyPDF2.PdfReader(XGBoost.pdf) writer PyPDF2.PdfWriter() for no, page in enumerate(reader.pages): if no % 2 0: new_page page.rotate(-90) else: new_page page.rotate(90) writer.add_page(new_page) with open(temp.pdf, wb) as file_obj: writer.write(file_obj)这里用到了三类对象与方法需要辨析清楚PdfReader负责解析输入文档reader.pages提供页面序列PageObject.rotate(角度)返回旋转后的新页面对象角度为顺时针方向的角度值负数表示逆时针该方法对应旧版 API 中的rotateClockwise与rotateCounterClockwise两个方法新版本统一为带符号的角度参数PdfWriter负责汇集页面并写出新文档add_page()把页面加入输出队列write(文件对象)将结果落盘。enumerate(reader.pages)用于同时取得页序号no与页面对象本身适合做奇偶页差异化处理这类按页号分支的逻辑。整个流程遵循读取 → 变换 → 写出三段式结构这是 PyPDF2 处理任务的通用骨架。加密 PDF 文件给文档设置统一口令使用PyPDF2中的PdfWriter对象可以为 PDF 文档加密。如果业务上需要给一系列 PDF 文档设置统一的访问口令例如批量分发内部资料时统一加密码用 Python 程序批量处理会非常方便import PyPDF2 reader PyPDF2.PdfReader(XGBoost.pdf) writer PyPDF2.PdfWriter() for page in reader.pages: writer.add_page(page) writer.encrypt(foobared) with open(temp.pdf, wb) as file_obj: writer.write(file_obj)要点说明writer.encrypt(foobared)在写出前对全部页面施加用户口令打开加密后的temp.pdf时需要输入密码foobared加密发生在write()之前先完成页面收集与加密设置再统一落盘批量场景下只需把读取文件路径、密码做成参数循环即可例如遍历一个目录下的所有 PDF 并应用同一密码。从安全角度补充一点encrypt设置的是打开文档所需的用户口令属于访问控制层防护适合防止他人随意打开但不应视为高强度内容加密手段。批量添加水印mergePage 的页面叠加PageObject还有一个名为merge_page的方法对应旧版mergePage可以将两个 PDF 页面叠加到同一画布上。借助它很容易实现给 PDF 批量添加水印的功能。具体思路是先准备一个提供水印页面的 PDF 文件例如用 Word 或reportlab生成一张只含公司名称、半透明文字的单页 PDF读取其中第 1 页作为水印模板然后遍历目标文档的每一页将水印页与原始页合并最后写出新文件reader1 PyPDF2.PdfReader(XGBoost.pdf) reader2 PyPDF2.PdfReader(watermark.pdf) writer PyPDF2.PdfWriter() watermark_page reader2.pages[0] for page in reader1.pages: page.merge_page(watermark_page) writer.add_page(page) with open(temp.pdf, wb) as file_obj: writer.write(file_obj)这段代码的关键在于reader2.pages[0]取出水印页作为叠加模板水印 PDF 中建议只放置水印内容方便复用page.merge_page(watermark_page)会把水印页内容绘制到当前页之上两个页面的内容同时保留水印页通常制作为透明背景 浅色文字这样叠加后不会遮挡正文阅读。如果想更精细还可以让奇数页和偶数页使用不同的水印例如偶数页加机密、奇数页加草稿做法与上一节的旋转示例一致——用enumerate(reader1.pages)按页号选择不同水印页再合并即可留给大家自行实践。创建 PDF 文件reportlab 从零绘制文档创建全新的 PDF 文档需要三方库reportlab的支持安装方式如下pip install reportlabreportlab提供了底层canvas绘图 API可以把页面当成一张画布自由绘制图片、文本并控制字体与颜色。下面是一个完整示例展示了 A4 页面上的绘图、注册中文字体、写字与保存四个核心步骤from reportlab.lib.pagesizes import A4 from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfgen import canvas pdf_canvas canvas.Canvas(resources/demo.pdf, pagesizeA4) width, height A4 # 绘图 image canvas.ImageReader(resources/guido.jpg) pdf_canvas.drawImage(image, 20, height - 395, 250, 375) # 显示当前页 pdf_canvas.showPage() # 注册字体文件 pdfmetrics.registerFont(TTFont(Font1, resources/fonts/Vera.ttf)) pdfmetrics.registerFont(TTFont(Font2, resources/fonts/青呱石头体.ttf)) # 写字 pdf_canvas.setFont(Font2, 40) pdf_canvas.setFillColorRGB(0.9, 0.5, 0.3, 1) pdf_canvas.drawString(width // 2 - 120, height // 2, 你好世界) pdf_canvas.setFont(Font1, 40) pdf_canvas.setFillColorRGB(0, 1, 0, 0.5) pdf_canvas.rotate(18) pdf_canvas.drawString(250, 250, hello, world!) # 保存 pdf_canvas.save()逐段拆解这段代码背后的 API 语义canvas.Canvas(resources/demo.pdf, pagesizeA4)创建画布并指定输出文件与页面尺寸A4来自reportlab.lib.pagesizes解包后的width, height即页面的宽高点数canvas.ImageReader(resources/guido.jpg)加载图片源drawImage(image, x, y, w, h)以(x, y)为左下角、宽w高h绘制图片height - 395表示从页面顶部向下偏移定位pdf_canvas.showPage()结束当前页并开始新的一页绘图与写字是两页先图后字pdfmetrics.registerFont(TTFont(Font1, 字体文件路径))注册 TrueType 字体第一个参数是字体别名后续setFont(Font2, 40)用它引用注意中文字体示例中的青呱石头体用于输出中文西文字体Vera.ttf用于输出英文setFillColorRGB(r, g, b, a)设置文字填充色支持第四个透明度参数如0.9, 0.5, 0.3, 1为不透明橙色、0, 1, 0, 0.5为半透明绿色drawString(x, y, 文本)以基线位置写入文本rotate(18)会旋转后续绘图坐标系因此第二行英文是旋转 18 度后写出的pdf_canvas.save()保存画布并落盘所有内容在此之前都要绘制完毕。如果手头没有示例字体文件也可以使用仓库内已有的中文字体 Day66-80/code/res/SimHei.ttf 和图片 Day66-80/code/res/guido.jpg 替换路径验证字体注册与图片绘制逻辑——字体注册方式与字体文件名无关只要路径指向真实的 TTF 文件即可。实战延伸用 reportlab 导出 PDF 报表reportlab的能力不止于本地生成文件还可以与 Web 框架结合把 PDF 作为 HTTP 响应直接输出给浏览器。在项目 Day46-60/50.制作报表.md 的导出 PDF 报表一节中展示了如何在 Django 视图中用reportlab生成 PDF 并指定application/pdf的 MIME 类型def export_pdf(request: HttpRequest) - HttpResponse: buffer io.BytesIO() pdf canvas.Canvas(buffer) pdf.setFont(Helvetica, 80) pdf.setFillColorRGB(0.2, 0.5, 0.3) pdf.drawString(100, 550, hello, world!) pdf.showPage() pdf.save() resp HttpResponse(buffer.getvalue(), content_typeapplication/pdf) resp[content-disposition] inline; filenamedemo.pdf return resp与本地写文件相比这里的关键差异是canvas.Canvas(buffer)把输出目标从文件路径换成io.BytesIO内存缓冲save()后通过buffer.getvalue()取出二进制内容交给HttpResponse并设置content_typeapplication/pdfcontent-disposition: inline表示浏览器内联预览而不是强制下载。这正是 README.md 中使用reportlab生成 PDF 报表一节的落地用法也说明本文介绍的canvas绘图 API 可以直接复用到后端报表系统。总结围绕 PDF 的读与写两个方向本文覆盖了PyPDF2与reportlab两条工具链的完整用法任务库核心对象/方法提取文本PyPDF2 / pdfminer.sixPdfReader、page.extract_text()旋转页面PyPDF2PageObject.rotate()加密文档PyPDF2PdfWriter.encrypt()叠加页面/水印PyPDF2PageObject.merge_page()创建 PDFreportlabcanvas.Canvas、drawImage、drawString在掌握上述基础后合并多个 PDF、批量加水印、统一加密码、导出 PDF 报表等工作都可以用几十行 Python 代码实现。更复杂的中文排版与表格布局需求可以进一步研究reportlab的platypus布局引擎或结合 Day46-60/50.制作报表.md 中的报表导出实践将 PDF 生成能力集成到真实项目中。赞分享文档教程【免费下载链接】Python-100-DaysPython - 100天从新手到大师项目地址https://gitcode.com/GitHub_Trending/py/Python-100-Days点击查看免费下载相关推荐Python 解析 HTML 页面实战XPath 与 CSS 选择器全解Python-100-Days 第 62 天Python 解析 HTML 页面实战XPath 与 CSS 选择器全解Python 100 Days 第 62 天 在前面的课程中我们已经掌握了用 r文档教程QQ空间说说一键导出GetQzonehistory 把历史说说、评论和配图备份成本地 ExcelQQ空间说说一键导出GetQzonehistory 把历史说说、评论和配图备份成本地 Excel QQ空间没有官方导出入口老说说只能逐条截图。GetQzon网页爬虫数据分析Python-100-Days 第 25 讲openpyxl 读写 Excel 文件完整实战指南Python 100 Days 第 25 讲openpyxl 读写 Excel 文件完整实战指南 openpyxl 是 Python 生态中最流行的 xlsx文档教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑