PDF 处理指南
本技能用 Python 库 + 命令行工具完成各类 PDF 操作。进阶用法与 JavaScript 库见 references/pdf_reference.py(内含可直接运行示例)。
快速上手
from pypdf import PdfReader, PdfWriter
reader = PdfReader("document.pdf")
print(f"页数: {len(reader.pages)}")
text = ""
for page in reader.pages:
text += page.extract_text()
Python 库速查
pypdf —— 基础操作
合并:
from pypdf import PdfWriter, PdfReader
writer = PdfWriter()
for pdf_file in ["a.pdf", "b.pdf", "c.pdf"]:
for page in PdfReader(pdf_file).pages:
writer.add_page(page)
with open("merged.pdf", "wb") as f:
writer.write(f)
拆分(每页一个文件):
reader = PdfReader("input.pdf")
for i, page in enumerate(reader.pages):
w = PdfWriter(); w.add_page(page)
with open(f"page_{i+1}.pdf", "wb") as f:
w.write(f)
旋转页面:
page = reader.pages[0]
page.rotate(90) # 顺时针 90 度
writer.add_page(page)
提取元数据:
meta = reader.metadata
print(meta.title, meta.author, meta.subject)
pdfplumber —— 文字与表格提取
import pdfplumber
with pdfplumber.open("document.pdf") as pdf:
for i, page in enumerate(pdf.pages):
print(page.extract_text())
for t in page.extract_tables():
for row in t:
print(row)
reportlab —— 新建 PDF
基础(画布):
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
c = canvas.Canvas("hello.pdf", pagesize=letter)
c.drawString(100, 750, "你好,PDF")
c.line(100, 740, 400, 740)
c.save()
多页 + 段落流:
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak
from reportlab.lib.styles import getSampleStyleSheet
doc = SimpleDocTemplate("report.pdf", pagesize=letter)
styles = getSampleStyleSheet(); story = []
story.append(Paragraph("报告标题", styles['Title']))
story.append(Paragraph("正文内容 " * 20, styles['Normal']))
story.append(PageBreak())
story.append(Paragraph("第二页", styles['Heading1']))
doc.build(story)
> 上标/下标坑:reportlab 内置字体不含 Unicode 上下标字形(₀₁²³…),会渲染成黑块。改用 XML 标签:<sub>2</sub>(下标)、<super>2</super>(上标)。
命令行工具
| 任务 | 工具 | 命令 |
|---|---|---|
| 提取文字 | pdftotext(poppler) |
pdftotext -layout in.pdf out.txt |
| 合并 | qpdf |
qpdf --empty --pages a.pdf b.pdf -- merged.pdf |
| 拆分 | qpdf |
qpdf in.pdf --pages . 1-5 -- p1-5.pdf |
| 旋转 | qpdf |
qpdf in.pdf out.pdf --rotate=+90:1 |
| 解密 | qpdf |
qpdf --password=PASS --decrypt enc.pdf dec.pdf |
| 提取图片 | pdfimages(poppler) |
pdfimages -j in.pdf prefix |
常见任务
扫描件 OCR(需 pytesseract + pdf2image):
import pytesseract
from pdf2image import convert_from_path
text = ""
for i, img in enumerate(convert_from_path('scanned.pdf')):
text += f"第{i+1}页:\n" + pytesseract.image_to_string(img) + "\n\n"
加水印:
wm = PdfReader("watermark.pdf").pages[0]
for page in PdfReader("doc.pdf").pages:
page.merge_page(wm)
writer.add_page(page)
加密:
writer.encrypt("user_pass", "owner_pass")
速查表
| 任务 | 最佳工具 |
|---|---|
| 合并 | pypdf / qpdf |
| 拆分 | pypdf / qpdf |
| 提取文字 | pdfplumber |
| 提取表格 | pdfplumber |
| 新建 | reportlab |
| OCR 扫描件 | pytesseract |
| 填表单 | pypdf(详见 references/pdf_reference.py 注释) |
依赖
pypdf · pdfplumber · reportlab(本技能环境已预装)· 可选:poppler-utils(pdftotext/pdfimages) · 可选:qpdf · 可选 OCR:pytesseract + pdf2image(需系统 Tesseract)。