Claude Code 处理 PDF 文件的完整指南

Claude Code 学习笔记

分类:文件处理

核心主题:Claude Code 与 PDF 文件的交互方法

主要内容:系统总结 Claude Code 处理 PDF 文件的九大方法,涵盖读取、文本提取、表格提取、格式转换、PDF 生成、合并拆分、图片提取以及实际业务场景中的应用案例。

关键词:Claude Code, PDF处理, PyMuPDF, pdfplumber, pdfminer, reportlab, Markdown转换, 文件批处理, OCR, Python

一、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 安装 PyMuPDF pip install PyMuPDF # 验证安装 python -c "import fitz; print(fitz.__doc__)"

提取文本与元数据的完整示例:

import fitz # PyMuPDF 的导入名称为 fitz def extract_pdf_info(pdf_path): """提取 PDF 文件的文本内容和元数据""" doc = fitz.open(pdf_path) # 1. 提取元数据 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}") # 2. 逐页提取文本 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: # b[0:4] 为矩形坐标, b[4] 为文本内容 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): # 转换为 pandas DataFrame df = pd.DataFrame(table[1:], columns=table[0]) print(f"第 {page_num+1} 页 - 表格 {table_num+1}") print(df.head()) # 保存为 CSV 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 # 将 PDF 转换为 Markdown(需要先使用其他工具提取文本) # 实际工作中通常分两步:先提取文本,再用 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" # 第二步:使用 pypandoc 做进一步格式化 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![图片-第{page_num+1}页](image_p{page_num+1}.png)\n") # 写入 Markdown 文件 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() # 批量处理目录下的所有 PDF 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) # 生成 PDF 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 # 合并多个 PDF 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}") # 拆分 PDF(每页一个文件) 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: # PyMuPDF 页码从 0 开始 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 # 为 PDF 添加密码保护 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}") # 解密 PDF 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 # 使用 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: # 旋转页面 90 度 page.rotate_clockwise(90) writer.add_page(page) # 添加书签 writer.add_outline_item("第一章", 0) # 第 1 页 writer.add_outline_item("第二章", 10) # 第 11 页 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] # 方法一:通过 get_images 获取图片引用 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"] # png, jpg, jpeg, etc. 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] # 转为 0 基索引 # 设置缩放倍率(DPI),提高截取清晰度 zoom = 2.0 # 2 倍缩放 = 144 DPI 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 = {} # 发票号码(常见格式: 发票号码: 12345678) 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")
发票提取工作流总结:
  1. 将发票 PDF 存放在统一目录中
  2. 使用 PyMuPDF 提取每张发票的文本内容
  3. 通过正则表达式匹配关键字段(发票号、日期、金额、购买方等)
  4. 将结构化数据输出为 JSON 或 CSV 格式
  5. 与财务系统对接或生成汇总报表

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 / 摘要部分) 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 方案

# 方案一:使用 pytesseract + 中文语言包 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 # 3 倍缩放提高 OCR 精度 matrix = fitz.Matrix(zoom, zoom) pix = page.get_pixmap(matrix=matrix) # 保存为临时图片 img_path = "temp_page.png" pix.save(img_path) # OCR 识别(使用中文简体 + 英文语言包) # 需要提前安装: tesseract-ocr-chi-sim text = pytesseract.image_to_string( Image.open(img_path), lang="chi_sim+eng", # 中文简体 + 英文 config="--psm 6" # 假设为统一文本块 ) doc.close() return text # 方案二:使用 PaddleOCR(中文 OCR 效果更优) # pip install paddlepaddle paddleocr 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 # 注册中文字体(在 reportlab 中使用中文的必备步骤) # Windows 系统:使用系统自带的微软雅黑字体 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, ) # 创建中文 PDF 文档 doc = SimpleDocTemplate("chinese_report.pdf", pagesize=A4) story = [] story.append(Paragraph("中文数据分析报告", styles["Title"])) story.append(Paragraph( "本报告展示了如何使用 reportlab 生成包含中文内容的 PDF 文件。 需要注意的是,必须显式注册中文字体才能正常显示中文。", chinese_style )) doc.build(story) # 字体路径参考(Linux/Mac 不同) # Linux: /usr/share/fonts/truetype/ # Mac: /System/Library/Fonts/

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] # 策略 1: 标准文本提取 text1 = page.get_text("text") # 策略 2: 使用 HTML 模式,对某些编码问题更健壮 text2 = page.get_text("html") # 策略 3: 按单词提取,跳过编码错误的字符 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 的最佳工作流

  1. 需求分析:明确处理目标(提取、转换、生成还是批量操作),确定合适的 Python 库
  2. 脚本生成:向 Claude Code 描述需求,让其生成初始 Python 脚本
  3. 测试验证:用样本 PDF 测试脚本,检查提取结果的准确性和完整性
  4. 优化迭代:根据测试结果调整正则表达式、提取参数或处理逻辑
  5. 批量运行:对全量 PDF 执行处理,并使用 Claude Code 对结果进行分析和总结
  6. 输出归档:将结构化数据保存为 JSON/CSV/Markdown 格式,建立可检索的知识库

掌握这些技能后,你将能够高效地利用 Claude Code 处理各种 PDF 相关的自动化任务,大幅提升文档处理的效率和质量。