Claude Code 处理 PDF 文件的完整指南
Claude Code 学习笔记
一、Claude Code 处理 PDF 的基本方式
Claude Code 原生具备读取和解析 PDF 文件的能力,这是实现自动化 PDF 工作流的基础。当用户向 Claude Code 提供 PDF 文件时,系统会将其转换为文本格式进行处理,但理解其能力边界和正确使用方法至关重要。
核心能力:Claude Code 的 Read 工具可以直接读取 PDF 文件。对于单页或少量页面的 PDF,可获取完整文本内容;对于多页 PDF,支持按页面范围分段读取(通过 pages 参数指定)。
重要限制:Claude Code 无法直接查看 PDF 中的图片内容或复杂表格布局,只能提取到文字层。对于扫描版 PDF(图片形式),需要配合 OCR 工具使用。
与 Claude Code 协作处理 PDF 的基础流程通常包含以下几个环节:首先,使用 Read 工具读取 PDF 以了解文档结构和内容概要;然后,根据需要对内容进行分段处理和提取;最后,结合 Python 脚本库执行更复杂的批量操作。
实用提示词示例
将 PDF 文件拖入 Claude Code 对话框后,可以这样提问:
"请读取这个 PDF 文件,提取其中的核心论点、关键数据和作者结论,并以 Markdown 格式整理成结构化笔记。"
或者指定页码范围:
"请读取这个 PDF 的第 3 到第 8 页,重点关注其中的实验方法和数据结果部分。"
| 读取方式 |
适用场景 |
注意事项 |
| 直接读取(Read 工具) |
文本型 PDF、少量页面 |
无法处理图片、复杂表格 |
| 按页分段读取 |
多页文档、需要精确定位 |
使用 pages 参数控制范围 |
| 配合 Python 库提取 |
批量处理、结构化数据 |
需要编写提取脚本 |
| OCR + 读取 |
扫描版 PDF |
需要安装 Tesseract 等 OCR 引擎 |
二、使用 PyMuPDF (fitz) 提取 PDF 文本与元数据
PyMuPDF(也称为 fitz)是 Python 生态中最强大的 PDF 处理库之一,它基于 MuPDF 渲染引擎,提供了极高的性能和丰富的功能接口。无论是提取文本、元数据,还是操作页面元素,PyMuPDF 都能胜任。
什么是 PyMuPDF?
PyMuPDF 是对 MuPDF 渲染器的 Python 绑定,MuPDF 是一个轻量级但功能强大的 PDF、XPS 和电子书渲染引擎。PyMuPDF 的主要优势在于其处理速度快、API 设计直观,并且支持几乎所有 PDF 操作场景。
安装方法:
pip install PyMuPDF
python -c "import fitz; print(fitz.__doc__)"
提取文本与元数据的完整示例:
import fitz
def extract_pdf_info(pdf_path):
"""提取 PDF 文件的文本内容和元数据"""
doc = fitz.open(pdf_path)
metadata = doc.metadata
print(f"标题: {metadata.get('title', 'N/A')}")
print(f"作者: {metadata.get('author', 'N/A')}")
print(f"主题: {metadata.get('subject', 'N/A')}")
print(f"页数: {doc.page_count}")
full_text = []
for page_num in range(doc.page_count):
page = doc[page_num]
text = page.get_text("text")
full_text.append(f"--- 第 {page_num + 1} 页 ---\n{text}")
blocks = page.get_text("blocks")
for b in blocks:
print(f"位置 ({b[0]:.0f}, {b[1]:.0f}): {b[4][:50]}")
doc.close()
return "\n".join(full_text)
text = extract_pdf_info("document.pdf")
实战技巧:提取模式的选择
PyMuPDF 的 get_text() 方法支持多种提取模式:
- "text":纯文本模式,按阅读顺序提取,适合大多数场景
- "blocks":文本块模式,保留每段文本的位置信息和边界框
- "words":单词级提取,返回每个单词及其精确坐标,适合做自定义布局分析
- "html":HTML 格式输出,保留基本的排版样式
- "dict":字典结构,包含完整的页面元素层次信息,适合精细控制
PyMuPDF 的独特优势:
- 速度极快:相比 pdfplumber 和 pdfminer,PyMuPDF 的提取速度通常快 5-10 倍
- 内存占用低:流式处理大文件时表现优异
- 中文支持良好:对 CJK(中日韩)字符有原生支持
- 可操作页面元素:支持插入图片、绘制图形、添加注释等
三、使用 pdfplumber / pdfminer 进行表格数据提取
对于包含结构化表格的 PDF 文件,PyMuPDF 的文本提取能力有限,这时候需要专门的表格提取工具。pdfplumber 和 pdfminer.six 是两个最常用的选择,它们能够解析 PDF 的底层图形指令,从而准确还原表格结构。
3.1 pdfplumber 表格提取
pdfplumber 基于 pdfminer 构建,但提供了更友好的 API 和更强大的表格检测功能。它能自动识别 PDF 中的表格线条和文本对齐方式,提取出结构化的表格数据。
import pdfplumber
import pandas as pd
def extract_tables_from_pdf(pdf_path):
"""提取 PDF 中的所有表格,并保存为 CSV 文件"""
with pdfplumber.open(pdf_path) as pdf:
for page_num, page in enumerate(pdf.pages):
tables = page.extract_tables()
for table_num, table in enumerate(tables):
df = pd.DataFrame(table[1:], columns=table[0])
print(f"第 {page_num+1} 页 - 表格 {table_num+1}")
print(df.head())
csv_name = f"table_p{page_num+1}_t{table_num+1}.csv"
df.to_csv(csv_name, index=False, encoding="utf-8-sig")
def extract_tables_advanced(pdf_path):
with pdfplumber.open(pdf_path) as pdf:
page = pdf.pages[0]
table_settings = {
"vertical_strategy": "lines",
"horizontal_strategy": "lines",
"intersection_tolerance": 5,
}
tables = page.find_tables(table_settings)
for table in tables:
data = table.extract()
print(data)
pdfplumber 的表格策略对比
pdfplumber 提供了多种表格检测策略,可以灵活组合:
- lines 策略:通过检测 PDF 中的绘制线条来确定表格边界,适合有线表格
- text 策略:通过分析文本的对齐方式和间距来推断表格结构,适合无线表格
- explicit 策略:手动指定表格区域坐标,适合完全控制
- 混合策略:组合使用多种策略,提高检测准确率
3.2 pdfminer.six 高级文本分析
pdfminer.six 是 Python 中最成熟的 PDF 内容分析库,提供了对 PDF 内部结构的深度解析能力。与 pdfplumber 不同,pdfminer 更偏底层,适合需要精细控制提取过程的场景。
from pdfminer.high_level import extract_pages
from pdfminer.layout import LTTextBox, LTFigure, LTImage, LTTable
def analyze_pdf_structure(pdf_path):
"""分析 PDF 的页面结构层次"""
for page_layout in extract_pages(pdf_path):
print(f"页面尺寸: {page_layout.width} x {page_layout.height}")
def show_element(element, depth=0):
indent = " " * depth
if isinstance(element, LTTextBox):
print(f"{indent}文本框: {element.get_text()[:60]}...")
elif isinstance(element, LTFigure):
print(f"{indent}图形区域: ({element.x0:.0f}, {element.y0:.0f})")
for child in element:
show_element(child, depth + 1)
elif isinstance(element, LTImage):
print(f"{indent}图片: {element.width}x{element.height}")
for element in page_layout:
show_element(element)
库选择建议:
- 简单文本提取:优先使用 PyMuPDF,速度快、代码简洁
- 表格提取:使用 pdfplumber,表格检测算法成熟
- 深度结构分析:使用 pdfminer.six,API 层次最丰富
- 中文 PDF 表格:pdfplumber 配合中文字体设置效果最佳
四、PDF 转 Markdown / HTML / 文本的自动化处理
将 PDF 转换为可编辑的 Markdown 或 HTML 格式是日常工作中最常见的需求之一。Claude Code 可以在这一环节发挥重要作用,既可以辅助编写转换脚本,也可以对转换后的内容进行清洗、重组织和格式化。
4.1 使用 pypandoc 进行格式转换
Pandoc 是文档格式转换的瑞士军刀,而 pypandoc 是其 Python 封装。虽然 Pandoc 本身对 PDF 的直接支持有限(需要 LaTeX 引擎),但可以结合其他工具构建完整的工作流。
import pypandoc
import fitz
doc = fitz.open("input.pdf")
markdown_content = ""
for page in doc:
blocks = page.get_text("dict")["blocks"]
for block in blocks:
if block["type"] == 0:
for line in block["lines"]:
text = "".join([span["text"] for span in line["spans"]])
font_size = line["spans"][0]["size"] if line["spans"] else 12
if font_size > 20:
markdown_content += f"## {text}\n\n"
elif font_size > 16:
markdown_content += f"### {text}\n\n"
else:
markdown_content += f"{text}\n\n"
html_output = pypandoc.convert_text(
markdown_content,
"html",
format="markdown",
extra_args=["--toc", "--mathjax"]
)
with open("output.html", "w", encoding="utf-8") as f:
f.write(html_output)
4.2 完整的 PDF 转 Markdown 自动化脚本
import os
import fitz
import re
from pathlib import Path
def pdf_to_markdown(pdf_path, output_dir="output"):
"""将 PDF 转换为结构化的 Markdown 文件"""
Path(output_dir).mkdir(parents=True, exist_ok=True)
doc = fitz.open(pdf_path)
base_name = Path(pdf_path).stem
lines = []
for page_num in range(doc.page_count):
page = doc[page_num]
blocks = page.get_text("dict")["blocks"]
for block in blocks:
if block["type"] == 0:
for line in block["lines"]:
text = "".join(
span["text"] for span in line["spans"]
).strip()
if not text:
continue
size = line["spans"][0]["size"]
font = line["spans"][0]["font"]
if size >= 18:
lines.append(f"## {text}\n")
elif size >= 14:
lines.append(f"### {text}\n")
elif size >= 12:
lines.append(f"**{text}**\n" if "bold" in font.lower() else f"{text}\n")
else:
lines.append(f"{text}\n")
elif block["type"] == 1:
lines.append(f"\n\n")
md_path = Path(output_dir) / f"{base_name}.md"
with open(md_path, "w", encoding="utf-8") as f:
f.writelines(lines)
print(f"转换完成: {md_path}")
doc.close()
def batch_convert(pdf_dir):
for pdf_file in Path(pdf_dir).glob("*.pdf"):
pdf_to_markdown(str(pdf_file))
提示词示例:让 Claude Code 帮你编写转换脚本
"我需要将一批 PDF 论文转换为 Markdown 格式。请帮我编写一个 Python 脚本,使用 PyMuPDF 提取文本,并根据字体大小自动推断标题层级(字号大于 18pt 为一级标题,14-18pt 为二级标题),同时保留列表和段落结构。输出格式为标准的 GitHub Flavored Markdown。"
五、使用 reportlab 生成 PDF 报告
reportlab 是 Python 生态中最强大的 PDF 生成库,支持从零开始创建包含丰富格式的 PDF 文档,包括文字排版、表格、图表、图片插入、页眉页脚等。在数据报告自动生成的场景中,reportlab 是首选工具。
reportlab 的核心概念
reportlab 采用"画布(Canvas)+ 文档模板(DocTemplate)"的双层架构。Canvas 提供了底层的绘图 API,适合精细控制每个元素的位置;DocTemplate 提供了高层的页面布局框架,支持自动分页、页眉页脚、多栏排版等高级功能。
安装方法:
pip install reportlab
基础使用:创建第一个 PDF 文档
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Image
from reportlab.lib import colors
doc = SimpleDocTemplate(
"report.pdf",
pagesize=A4,
topMargin=2*cm,
bottomMargin=2*cm,
leftMargin=2.5*cm,
rightMargin=2.5*cm,
)
styles = getSampleStyleSheet()
title_style = ParagraphStyle(
"CustomTitle",
parent=styles["Title"],
fontSize=24,
textColor=colors.HexColor("#2c3e50"),
spaceAfter=20,
)
story = []
story.append(Paragraph("数据分析报告", title_style))
story.append(Spacer(1, 20))
story.append(Paragraph(
"本报告基于 2025 年度销售数据生成,涵盖各区域市场的关键业绩指标。",
styles["Normal"]
))
story.append(Spacer(1, 15))
table_data = [
["地区", "销售额", "增长率", "占比"],
["华东", "1,280万", "15.3%", "32%"],
["华南", "960万", "12.1%", "24%"],
["华北", "720万", "8.7%", "18%"],
["合计", "2,960万", "12.4%", "74%"],
]
table = Table(table_data, colWidths=[4*cm, 4*cm, 4*cm, 3*cm])
table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#6c5ce7")),
("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
("FONTSIZE", (0, 0), (-1, -1), 10),
("ALIGN", (0, 0), (-1, -1), "CENTER"),
("GRID", (0, 0), (-1, -1), 0.5, colors.grey),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.white, colors.HexColor("#f8f9fa")]),
]))
story.append(table)
doc.build(story)
print("PDF 报告生成成功: report.pdf")
reportlab 高级功能一览:
- Flowable 框架:Paragraph、Table、Image 等组件可自动排版和分页
- 页面模板:支持多套页面模板切换,适应不同章节的布局需求
- 矢量图形:直接绘制图表、流程图、签名等矢量元素
- 中文支持:需要注册中文字体,详见第九章说明
- 加密保护:支持设置文档密码和权限控制
提示词示例:生成报告
"请帮我编写一个 reportlab 脚本,生成一份季度销售报告 PDF。要求包含:封面页(公司Logo、报告标题、日期)、目录页、数据表格(带交替行颜色和表头样式)、饼图(使用 reportlab.graphics)、页脚页码。数据可以模拟。"
六、PDF 合并、拆分、加密解密的脚本化处理
PyMuPDF 和 PyPDF2(及其继任者 pypdf)提供了全面的 PDF 文档操作功能,包括页面级别的合并、拆分、旋转、加密解密等。这些操作在文档管理自动化和工作流集成中非常实用。
6.1 使用 PyMuPDF 进行页面操作
import fitz
def merge_pdfs(input_files, output_file):
"""合并多个 PDF 文件为一个"""
merged = fitz.open()
for pdf_path in input_files:
with fitz.open(pdf_path) as src:
merged.insert_pdf(src)
merged.save(output_file)
merged.close()
print(f"合并完成: {output_file}")
def split_pdf(input_file, output_dir):
"""将 PDF 按页拆分为单独文件"""
with fitz.open(input_file) as doc:
for i in range(doc.page_count):
new_doc = fitz.open()
new_doc.insert_pdf(doc, from_page=i, to_page=i)
output_path = f"{output_dir}/page_{i+1:03d}.pdf"
new_doc.save(output_path)
new_doc.close()
print(f"拆分完成,共 {doc.page_count} 个文件")
def extract_pages(input_file, output_file, page_ranges):
"""提取指定页码范围,page_ranges 格式: [(1,3), (5,7)]"""
with fitz.open(input_file) as doc:
new_doc = fitz.open()
for start, end in page_ranges:
new_doc.insert_pdf(doc, from_page=start-1, to_page=end-1)
new_doc.save(output_file)
new_doc.close()
6.2 加密与解密
import fitz
def encrypt_pdf(input_file, output_file, password, permission=fitz.PDF_PERM_ACCESSIBILITY):
"""加密 PDF 文件
permission 可选值:
- fitz.PDF_PERM_PRINT: 允许打印
- fitz.PDF_PERM_MODIFY: 允许修改
- fitz.PDF_PERM_COPY: 允许复制
- fitz.PDF_PERM_ANNOTATE: 允许添加注释
- 组合: fitz.PDF_PERM_PRINT | fitz.PDF_PERM_COPY
"""
doc = fitz.open(input_file)
doc.save(
output_file,
encryption=fitz.PDF_ENCRYPT_AES_256,
user_pw=password,
owner_pw=password,
permissions=permission,
)
doc.close()
print(f"加密完成: {output_file}")
def decrypt_pdf(input_file, output_file, password):
doc = fitz.open(input_file)
if doc.is_encrypted:
authenticated = doc.authenticate(password)
if not authenticated:
raise ValueError("密码错误")
doc.save(output_file)
doc.close()
print(f"解密完成: {output_file}")
encrypt_pdf("secret.pdf", "encrypted.pdf", "mypassword123")
decrypt_pdf("encrypted.pdf", "decrypted.pdf", "mypassword123")
6.3 使用 pypdf 进行兼容性更强的操作
from pypdf import PdfReader, PdfWriter, PdfMerger
merger = PdfMerger()
for pdf in ["file1.pdf", "file2.pdf", "file3.pdf"]:
merger.append(pdf)
merger.write("merged.pdf")
merger.close()
writer = PdfWriter()
reader = PdfReader("source.pdf")
for page in reader.pages:
page.rotate_clockwise(90)
writer.add_page(page)
writer.add_outline_item("第一章", 0)
writer.add_outline_item("第二章", 10)
with open("output.pdf", "wb") as f:
writer.write(f)
提示词示例:批量处理
"请帮我写一个 Python 脚本,遍历指定文件夹中的所有 PDF 文件,将它们按文件名的数字前缀分组(例如 01_xxx.pdf, 02_yyy.pdf),每组合并成一个 PDF,并添加密码保护(密码为 group123)。输出合并后的文件到 output 目录。"
七、从 PDF 中提取图片与附件的技巧
PDF 文件中常常包含嵌入的图片和附件(嵌入式文件)。提取这些资源对于内容复用和文档分析非常重要。PyMuPDF 在这方面提供了最完善的 API 支持。
7.1 提取嵌入图片
import fitz
import os
from pathlib import Path
def extract_images_from_pdf(pdf_path, output_dir="extracted_images"):
"""从 PDF 中提取所有嵌入图片"""
Path(output_dir).mkdir(parents=True, exist_ok=True)
doc = fitz.open(pdf_path)
image_count = 0
for page_num in range(doc.page_count):
page = doc[page_num]
image_list = page.get_images(full=True)
print(f"第 {page_num+1} 页: 发现 {len(image_list)} 张图片")
for img_idx, img in enumerate(image_list):
xref = img[0]
base_image = doc.extract_image(xref)
image_bytes = base_image["image"]
image_ext = base_image["ext"]
image_filename = f"img_p{page_num+1}_{img_idx+1}.{image_ext}"
image_path = Path(output_dir) / image_filename
with open(image_path, "wb") as f:
f.write(image_bytes)
image_count += 1
print(f" 保存: {image_filename} ({len(image_bytes)} bytes)")
doc.close()
print(f"\n提取完成: 共 {image_count} 张图片")
def extract_page_sections(pdf_path, page_num, rect):
"""提取页面中指定矩形区域的图像
rect 格式: fitz.Rect(x0, y0, x1, y1)
坐标单位: 点(points),72 点 = 1 英寸
"""
doc = fitz.open(pdf_path)
page = doc[page_num - 1]
zoom = 2.0
matrix = fitz.Matrix(zoom, zoom)
pix = page.get_pixmap(matrix=matrix, clip=rect)
pix.save("section_output.png")
doc.close()
7.2 提取嵌入式附件
import fitz
from pathlib import Path
def extract_attachments(pdf_path, output_dir="attachments"):
"""从 PDF 中提取所有嵌入式附件(嵌入式文件)"""
Path(output_dir).mkdir(parents=True, exist_ok=True)
doc = fitz.open(pdf_path)
attachment_count = 0
embedded_files = doc.embfile_names()
print(f"发现 {len(embedded_files)} 个附件")
for name in embedded_files:
try:
data = doc.embfile_get(name)
file_path = Path(output_dir) / name
with open(file_path, "wb") as f:
f.write(data)
attachment_count += 1
print(f" 提取: {name} ({len(data)} bytes)")
except Exception as e:
print(f" 提取失败: {name} - {e}")
doc.close()
return attachment_count
图片提取的两种策略
策略一:直接提取(extract_image) -- 适合提取 PDF 中嵌入的原始图片文件,输出质量最高。原理是通过 PDF 的交叉引用表直接读取图片流数据。
策略二:页面截取(get_pixmap) -- 适合提取 PDF 页面中由文字和图形混合生成的区域,如流程图、图表等。通过设置缩放矩阵可以控制输出分辨率。
八、实际案例:批量处理发票与论文信息提取
本节通过两个完整的实际案例,展示如何在 Claude Code 协作下完成复杂的 PDF 数据处理任务。每个案例都包含完整的 Python 代码和工作流程说明。
8.1 案例一:批量处理发票 PDF 提取数据
import fitz
import re
import json
from pathlib import Path
from datetime import datetime
def extract_invoice_data(pdf_path):
"""从电子发票 PDF 中提取关键信息"""
doc = fitz.open(pdf_path)
text = ""
for page in doc:
text += page.get_text()
doc.close()
invoice_data = {}
match = re.search(r"发票[号碼码][码號]?\s*[::]\s*(\d+)", text)
if match:
invoice_data["invoice_number"] = match.group(1)
match = re.search(r"开票[日時期]\s*[::]\s*(\d{4}[年\-/]\d{1,2}[月\-/]\d{1,2}[日]?)", text)
if match:
invoice_data["date"] = match.group(1)
match = re.search(r"[价價][税稅][合總][计計]\s*[::]\s*[¥¥]?\s*(\d+\.?\d*)", text)
if match:
invoice_data["total_amount"] = float(match.group(1))
match = re.search(r"(?:购买|购貨|买方)[方名稱]\s*[::]\s*(.+?)[\n\r]", text)
if match:
invoice_data["buyer"] = match.group(1).strip()
return invoice_data
def batch_process_invoices(pdf_dir, output_json):
"""批量处理目录下的所有发票 PDF"""
results = []
for pdf_file in sorted(Path(pdf_dir).glob("*.pdf")):
print(f"处理: {pdf_file.name}")
data = extract_invoice_data(str(pdf_file))
data["filename"] = pdf_file.name
results.append(data)
with open(output_json, "w", encoding="utf-8") as f:
json.dump(results, f, ensure_ascii=False, indent=2)
print(f"处理完成: {len(results)} 张发票, 结果已保存至 {output_json}")
batch_process_invoices("invoices", "invoice_data.json")
发票提取工作流总结:
- 将发票 PDF 存放在统一目录中
- 使用 PyMuPDF 提取每张发票的文本内容
- 通过正则表达式匹配关键字段(发票号、日期、金额、购买方等)
- 将结构化数据输出为 JSON 或 CSV 格式
- 与财务系统对接或生成汇总报表
8.2 案例二:学术论文 PDF 信息提取
import fitz
import re
def extract_paper_metadata(pdf_path):
"""提取学术论文的结构化信息"""
doc = fitz.open(pdf_path)
text = ""
for page in doc:
text += page.get_text()
first_page = doc[0]
blocks = first_page.get_text("dict")["blocks"]
title_candidates = []
for block in blocks:
if block["type"] == 0 and block["lines"]:
for line in block["lines"]:
size = line["spans"][0]["size"]
text_line = "".join(s["text"] for s in line["spans"])
title_candidates.append((size, text_line))
title_candidates.sort(key=lambda x: -x[0])
paper_info = {"title": title_candidates[0][1].strip() if title_candidates else "N/A"}
abstract_match = re.search(
r"(?:Abstract|ABSTRACT|摘要)[::]?\s*(.+?)(?=(?:Keywords|KEYWORDS|关键词|Introduction|INTRODUCTION|1\.\s|$))",
text, re.DOTALL
)
if abstract_match:
paper_info["abstract"] = abstract_match.group(1).strip()[:200]
kw_match = re.search(
r"(?:Keywords|KEYWORDS|关键词)[::]\s*(.+?)[\n\r]",
text, re.DOTALL
)
if kw_match:
paper_info["keywords"] = [k.strip() for k in kw_match.group(1).split(";")]
refs = re.findall(r"\[\d+\]", text)
paper_info["reference_count"] = len(set(refs))
meta = doc.metadata
paper_info["author"] = meta.get("author", "N/A")
doc.close()
return paper_info
def batch_extract_papers(pdf_dir):
papers = []
for pdf_file in Path(pdf_dir).glob("*.pdf"):
print(f"处理: {pdf_file.name}")
info = extract_paper_metadata(str(pdf_file))
info["filename"] = pdf_file.name
papers.append(info)
return papers
两个案例的核心启示
发票提取和论文提取虽然场景不同,但都遵循相似的自动化流程:PDF 读取 -> 文本提取 -> 模式匹配 -> 结构化输出 -> 批量汇总。Claude Code 在这类任务中最大的价值在于:
- 帮助快速编写和调试提取脚本
- 对提取后的数据进行清洗、分类和总结
- 提供正则表达式设计和优化的建议
- 生成可视化的分析报告
提示词示例:完整的提取任务
"我有一个目录 invoices/ 包含约 50 张电子发票 PDF,请帮我编写一个完整的 Python 脚本:1) 遍历目录读取所有 PDF;2) 使用 PyMuPDF 提取文本;3) 用正则表达式提取发票号码、日期、金额、购买方和销售方信息;4) 将所有数据汇总为一个 CSV 文件;5) 统计总金额和发票数量。发票的文本格式如下:[粘贴一份示例发票的文本内容]"
九、中文 PDF 处理的特殊注意事项
处理中文 PDF 文件时,会面临一些特有挑战。字体编码、字符识别、排版解析等方面的问题如果不妥善处理,会导致提取结果出现乱码或内容丢失。
9.1 字体与编码问题
常见中文 PDF 问题清单:
- ToUnicode 映射缺失:部分 PDF 没有正确嵌入 ToUnicode CMap,导致提取的文本为乱码或空白
- CID 字体编码:中文 PDF 常用 CID(Character Identifier)字体,提取时需要正确的编码映射表
- 字体子集化:某些 PDF 只嵌入了使用的部分字体字符,使用自定义字体名(如 AAAAA+BiaodianSong)
- 扫描版 PDF:图片格式的中文文档,需要通过 OCR 才能提取文字
9.2 中文 OCR 方案
import pytesseract
from PIL import Image
import fitz
def ocr_chinese_pdf(pdf_path, page_num=0):
"""对扫描版中文 PDF 进行 OCR 识别"""
doc = fitz.open(pdf_path)
page = doc[page_num]
zoom = 3.0
matrix = fitz.Matrix(zoom, zoom)
pix = page.get_pixmap(matrix=matrix)
img_path = "temp_page.png"
pix.save(img_path)
text = pytesseract.image_to_string(
Image.open(img_path),
lang="chi_sim+eng",
config="--psm 6"
)
doc.close()
return text
from paddleocr import PaddleOCR
ocr = PaddleOCR(use_angle_cls=True, lang="ch")
def ocr_with_paddle(pdf_path, page_num=0):
doc = fitz.open(pdf_path)
page = doc[page_num]
pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))
img_path = "temp_paddle.png"
pix.save(img_path)
result = ocr.ocr(img_path, cls=True)
text = "\n".join([line[1][0] for block in result for line in block])
doc.close()
return text
9.3 reportlab 中文 PDF 生成
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Paragraph
from reportlab.lib.styles import getSampleStyleSheet
pdfmetrics.registerFont(TTFont("MicrosoftYaHei", "msyh.ttc"))
pdfmetrics.registerFont(TTFont("SimSun", "simsun.ttc"))
pdfmetrics.registerFont(TTFont("KaiTi", "simkai.ttf"))
styles = getSampleStyleSheet()
chinese_style = ParagraphStyle(
"ChineseNormal",
fontName="MicrosoftYaHei",
fontSize=12,
leading=20,
spaceAfter=10,
)
doc = SimpleDocTemplate("chinese_report.pdf", pagesize=A4)
story = []
story.append(Paragraph("中文数据分析报告", styles["Title"]))
story.append(Paragraph(
"本报告展示了如何使用 reportlab 生成包含中文内容的 PDF 文件。
需要注意的是,必须显式注册中文字体才能正常显示中文。",
chinese_style
))
doc.build(story)
9.4 PyMuPDF 中文提取优化
import fitz
def extract_chinese_text_optimized(pdf_path):
"""优化的中文 PDF 文本提取方案"""
doc = fitz.open(pdf_path)
full_text = []
for page_num in range(doc.page_count):
page = doc[page_num]
text1 = page.get_text("text")
text2 = page.get_text("html")
words = page.get_text("words")
text3 = " ".join(w[4] for w in words)
candidates = [(t, len(t)) for t in [text1, text2, text3] if t.strip()]
if candidates:
best_text = max(candidates, key=lambda x: x[1])[0]
full_text.append(best_text)
doc.close()
return "\n".join(full_text)
中文 PDF 处理总结提示
- 提取乱码:尝试切换 get_text 的模式,或使用 pdfplumber 替代 PyMuPDF
- 扫描版文档:必须使用 OCR,推荐 PaddleOCR(中文效果好)或 Tesseract(开源免费)
- 生成中文 PDF:reportlab 必须注册中文字体,推荐使用系统自带的微软雅黑或思源字体
- 编码检测:提取后如发现乱码,先用 chardet 或 cjkdetect 检测实际编码
- 混合排版:中英文混排 PDF 提取时,空格和换行可能需要后处理校正
总结与最佳实践
| 需求场景 |
推荐工具 |
优先级 |
| 简单文本提取 |
PyMuPDF (fitz) |
首选 |
| 表格提取 |
pdfplumber |
首选 |
| 图片提取 |
PyMuPDF (fitz) |
首选 |
| PDF 生成 |
reportlab |
首选 |
| 合并/拆分 |
PyMuPDF 或 pypdf |
均可 |
| 格式转换 |
pypandoc + PyMuPDF |
组合 |
| 中文扫描 OCR |
PaddleOCR |
首选 |
| 批量自动化 |
Claude Code + Python 脚本 |
推荐工作流 |
与 Claude Code 协作处理 PDF 的最佳工作流
- 需求分析:明确处理目标(提取、转换、生成还是批量操作),确定合适的 Python 库
- 脚本生成:向 Claude Code 描述需求,让其生成初始 Python 脚本
- 测试验证:用样本 PDF 测试脚本,检查提取结果的准确性和完整性
- 优化迭代:根据测试结果调整正则表达式、提取参数或处理逻辑
- 批量运行:对全量 PDF 执行处理,并使用 Claude Code 对结果进行分析和总结
- 输出归档:将结构化数据保存为 JSON/CSV/Markdown 格式,建立可检索的知识库
掌握这些技能后,你将能够高效地利用 Claude Code 处理各种 PDF 相关的自动化任务,大幅提升文档处理的效率和质量。