—— PDF 的读与写
from PyPDF2 import PdfReader
# 打开 PDF
reader = PdfReader("document.pdf")
# 基本信息
print(f"页数: {len(reader.pages)}")
print(f"元数据: {reader.metadata}")
# 提取单页文字
page = reader.pages[0] # 第一页(0索引)
text = page.extract_text()
print(text)
# 提取所有页文字
for i, page in enumerate(reader.pages):
text = page.extract_text()
if text.strip():
print(f"--- 第{i+1}页 ---")
print(text[:200]) # 预览前200字符
# 获取页面信息
page = reader.pages[0]
print(f"页面尺寸: {page.mediabox}")
print(f"宽度: {page.mediabox.width}")
print(f"高度: {page.mediabox.height}")
from PyPDF2 import PdfReader
import re
def extract_text_from_pdf(pdf_path: str) -> str:
"""提取PDF全部文字"""
reader = PdfReader(pdf_path)
all_text = []
for page in reader.pages:
text = page.extract_text()
if text:
all_text.append(text)
return "\n".join(all_text)
def search_in_pdf(pdf_path: str, keyword: str) -> list[dict]:
"""在PDF中搜索关键词"""
reader = PdfReader(pdf_path)
results = []
for i, page in enumerate(reader.pages):
text = page.extract_text()
if text and keyword in text:
# 提取关键词上下文
for m in re.finditer(
rf'.{{0,40}}{re.escape(keyword)}.{{0,40}}', text
):
results.append({
"page": i + 1,
"context": m.group().strip(),
})
return results
# 提取表格数据(简单方案)
def extract_table_like(pdf_path: str) -> list[list[str]]:
"""尝试从PDF提取表格数据"""
reader = PdfReader(pdf_path)
rows = []
for page in reader.pages:
text = page.extract_text()
if not text:
continue
for line in text.split("\n"):
if line.strip():
# 按多空格分割
cells = re.split(r'\s{2,}', line.strip())
if len(cells) >= 2:
rows.append(cells)
return rows
from PyPDF2 import PdfReader, PdfWriter
# 合并多个 PDF
def merge_pdfs(pdf_paths: list[str], output_path: str):
"""合并多个PDF文件"""
writer = PdfWriter()
for path in pdf_paths:
reader = PdfReader(path)
for page in reader.pages:
writer.add_page(page)
with open(output_path, "wb") as f:
writer.write(f)
print(f"合并完成: {output_path} ({len(writer.pages)}页)")
# 拆分 PDF
def split_pdf(pdf_path: str, output_dir: str, pages_per_split: int = 1):
"""拆分PDF为多个小文件"""
reader = PdfReader(pdf_path)
total = len(reader.pages)
from pathlib import Path
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
for start in range(0, total, pages_per_split):
writer = PdfWriter()
end = min(start + pages_per_split, total)
for i in range(start, end):
writer.add_page(reader.pages[i])
out_file = output_path / f"part_{start//pages_per_split + 1}.pdf"
with open(out_file, "wb") as f:
writer.write(f)
print(f"拆分完成: {total}页 → {(total + pages_per_split - 1) // pages_per_split}个文件")
# 提取指定页面
def extract_pages(pdf_path: str, page_numbers: list[int], output_path: str):
"""提取指定页面(0索引)"""
reader = PdfReader(pdf_path)
writer = PdfWriter()
for n in page_numbers:
if 0 <= n < len(reader.pages):
writer.add_page(reader.pages[n])
with open(output_path, "wb") as f:
writer.write(f)
from PyPDF2 import PdfReader, PdfWriter
from reportlab.pdfgen import canvas # pip install reportlab
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
import tempfile
# 第一步:创建水印 PDF
def create_watermark(text: str, output_path: str,
font_size: int = 60, opacity: float = 0.15):
"""生成水印PDF页面"""
c = canvas.Canvas(output_path, pagesize=A4)
width, height = A4
# 设置半透明
c.setFillAlpha(opacity)
c.setFillGray(0.5)
# 旋转45度
c.saveState()
c.translate(width / 2, height / 2)
c.rotate(45)
# 绘制水印文字
c.setFont("Helvetica-Bold", font_size)
c.drawCentredString(0, 0, text)
# 重复绘制
c.setFont("Helvetica-Bold", font_size // 2)
for offset in [-150, 150]:
c.drawCentredString(0, offset, text)
c.restoreState()
c.save()
# 第二步:将水印叠加到原PDF
def add_watermark(pdf_path: str, watermark_text: str,
output_path: str):
"""给PDF添加水印"""
# 创建水印
with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as tmp:
wm_path = tmp.name
create_watermark(watermark_text, wm_path)
# 叠加水印
reader = PdfReader(pdf_path)
wm_reader = PdfReader(wm_path)
wm_page = wm_reader.pages[0]
writer = PdfWriter()
for page in reader.pages:
page.merge_page(wm_page) # 叠加水印
writer.add_page(page)
with open(output_path, "wb") as f:
writer.write(f)
# 清理临时文件
import os
os.unlink(wm_path)
print(f"水印添加完成: {output_path}")
from PyPDF2 import PdfReader, PdfWriter
# 修改元数据
reader = PdfReader("document.pdf")
writer = PdfWriter()
for page in reader.pages:
writer.add_page(page)
writer.add_metadata({
"/Title": "我的文档",
"/Author": "张三",
"/Subject": "自动化课程",
"/Creator": "Python PyPDF2",
})
# 加密
writer.encrypt(user_password="123456", owner_password="admin")
with open("encrypted.pdf", "wb") as f:
writer.write(f)
# 解密读取
reader = PdfReader("encrypted.pdf")
if reader.is_encrypted:
reader.decrypt("123456")
text = reader.pages[0].extract_text()
#!/usr/bin/env python3
"""第20课 PDF处理验证"""
from PyPDF2 import PdfReader, PdfWriter
import tempfile
import os
def create_test_pdf(path, num_pages=3):
"""创建测试PDF"""
from reportlab.pdfgen import canvas
c = canvas.Canvas(path)
for i in range(num_pages):
c.setFont("Helvetica", 12)
c.drawString(100, 700, f"Page {i+1} - Test Content")
c.showPage()
c.save()
def test_pdf_create_read():
"""PDF创建与读取测试"""
with tempfile.TemporaryDirectory() as tmpdir:
pdf_path = os.path.join(tmpdir, "test.pdf")
create_test_pdf(pdf_path)
reader = PdfReader(pdf_path)
assert len(reader.pages) == 3
text = reader.pages[0].extract_text()
assert "Page 1" in text
print("✅ PDF创建与读取测试通过")
def test_pdf_merge():
"""PDF合并测试"""
with tempfile.TemporaryDirectory() as tmpdir:
pdf1 = os.path.join(tmpdir, "part1.pdf")
pdf2 = os.path.join(tmpdir, "part2.pdf")
merged = os.path.join(tmpdir, "merged.pdf")
create_test_pdf(pdf1, 2)
create_test_pdf(pdf2, 3)
writer = PdfWriter()
for p in [pdf1, pdf2]:
for page in PdfReader(p).pages:
writer.add_page(page)
with open(merged, "wb") as f:
writer.write(f)
reader = PdfReader(merged)
assert len(reader.pages) == 5
print("✅ PDF合并测试通过")
def test_pdf_split():
"""PDF拆分测试"""
with tempfile.TemporaryDirectory() as tmpdir:
src = os.path.join(tmpdir, "source.pdf")
create_test_pdf(src, 4)
reader = PdfReader(src)
# 提取第1-2页
writer = PdfWriter()
writer.add_page(reader.pages[0])
writer.add_page(reader.pages[1])
out = os.path.join(tmpdir, "split.pdf")
with open(out, "wb") as f:
writer.write(f)
assert len(PdfReader(out).pages) == 2
print("✅ PDF拆分测试通过")
def test_pdf_watermark():
"""水印测试"""
with tempfile.TemporaryDirectory() as tmpdir:
src = os.path.join(tmpdir, "source.pdf")
wm = os.path.join(tmpdir, "watermark.pdf")
out = os.path.join(tmpdir, "output.pdf")
create_test_pdf(src, 2)
# 创建水印
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
c = canvas.Canvas(wm, pagesize=A4)
c.setFillAlpha(0.15)
c.setFont("Helvetica-Bold", 60)
c.drawCentredString(297, 420, "WATERMARK")
c.save()
# 叠加水印
reader = PdfReader(src)
wm_page = PdfReader(wm).pages[0]
writer = PdfWriter()
for page in reader.pages:
page.merge_page(wm_page)
writer.add_page(page)
with open(out, "wb") as f:
writer.write(f)
result = PdfReader(out)
assert len(result.pages) == 2
print("✅ 水印测试通过")
if __name__ == "__main__":
test_pdf_create_read()
test_pdf_merge()
test_pdf_split()
test_pdf_watermark()
print("\n🎉 第20课全部验证通过!")