---
name: "pdf"
description: "PDF 处理与转换工程完整指南"
---

# PDF 处理与转换工程完整指南

## 适用场景
当需要对复杂版面的 PDF 文档进行逆向结构化提取（文本、多列排版、嵌入式表格、向量图表）、PDF 表单填充、多文档合并拆分、脱敏加密，或为 RAG 知识库做嵌入前的高质量解析预处理时，指导 AI 构建端到端的 PDF 处理流水线。

## 功能说明
> 解决 PDF 解析中常见的“表格粘连成一团”、“双栏混排顺序错乱”、“页眉页脚污染正文”以及“扫描件 OCR 识别丢字”等顽疾，输出结构化 Markdown、JSON 与合规清洗后的高质量文本。

## 这个案例能帮你做什么
- 自动化判断 PDF 类型（纯文本型、扫描图片型、数字表单型、混合加密型）。
- 使用 `pdfplumber` / `pypdf` / `fitz (PyMuPDF)` 精确提取跨页表格、保留多列自然阅读顺序。
- 自动化去除页眉、页脚、版权水印与页码噪音，保留清洗纯净的核心语义内容。
- 支持 PDF/A 长期归档标准合规化、数字表单填充（AcroForm）与敏感数据自动马赛克遮罩。

## 你需要的 Skills（按类型）

| 类型 | Skill / 工具 | 用途 | 来源 |
|---|---|---|---|
| 核心工具 | `PyMuPDF` (`fitz`) / `pdfplumber` | 高性能流式解析与复杂表格检测 | Python Package |
| OCR 引擎 | `tesseract` / 视觉大模型接口 | 扫描版与图表内文字逆向提取 | CLI / API |
| 格式转换 | `pdfminer.six` | 底层坐标布局（LTLayout）精细分析 | Python Package |
| 内置 | `filesystem` | 本地文档暂存与处理结果持久化 | Built-in |

## 快速体验版（先跑一轮）

```text
你是我的 PDF 数据工程专家。
请帮我处理一份双栏排版的学术/技术白皮书 PDF：
1. 识别并过滤掉每页顶部的统一页眉与底部的页码。
2. 保持先左栏后右栏的自然阅读顺序，不要跨栏横向截断句子。
3. 提取其中的数据对比表格，并将其转换为标准 Markdown 表格。
4. 将提取出的正文输出为带层级标题的干净 Markdown 格式。
```

## 稳定自动版（可长期运行）

### 1) 自动化 Python 深度提取脚本 (`parse_pdf_pipeline.py`)

```python
import fitz  # PyMuPDF
import pdfplumber
import json
import re

def extract_clean_markdown(pdf_path, output_md_path):
    doc = fitz.open(pdf_path)
    full_markdown = []
    
    with pdfplumber.open(pdf_path) as plum_doc:
        for page_idx, page in enumerate(doc):
            plum_page = plum_doc.pages[page_idx]
            page_height = page.rect.height
            
            # 定义有效内容区域（排除顶部 8% 页眉与底部 8% 页脚）
            header_margin = page_height * 0.08
            footer_margin = page_height * 0.92
            
            # 1. 优先提取表格并记录表格占据的 bounding box
            tables = plum_page.extract_tables()
            table_bboxes = [t.bbox for t in plum_page.find_tables()] if hasattr(plum_page, "find_tables") else []
            
            # 2. 提取文本块（考虑双栏排版：按 x0 排序决定栏位）
            blocks = page.get_text("blocks")
            # block: (x0, y0, x1, y1, text, block_no, block_type)
            # 过滤页眉页脚与非文本块
            valid_blocks = [
                b for b in blocks 
                if b[6] == 0 and header_margin < b[1] < footer_margin
            ]
            
            # 排序：按是否偏左/右栏分流，再按 y 坐标自上而下排序
            page_mid_x = page.rect.width / 2.0
            left_col = [b for b in valid_blocks if b[0] < page_mid_x]
            right_col = [b for b in valid_blocks if b[0] >= page_mid_x]
            
            left_col.sort(key=lambda b: b[1])
            right_col.sort(key=lambda b: b[1])
            ordered_blocks = left_col + right_col if right_col else valid_blocks
            
            full_markdown.append(f"\n<!-- Page {page_idx + 1} -->\n")
            for b in ordered_blocks:
                text = b[4].strip()
                if not text:
                    continue
                # 简单启发式标题识别：字号较大或短句带序号
                if re.match(r'^(第[一二三四五六七八九十]+章|\d+\.\d*|\bChapter\b)', text):
                    full_markdown.append(f"\n### {text}\n")
                else:
                    full_markdown.append(text + "\n")
                    
            # 3. 拼接表格
            for tbl in tables:
                if tbl and len(tbl) > 1:
                    full_markdown.append("\n" + markdown_table(tbl) + "\n")
                    
    with open(output_md_path, "w", encoding="utf-8") as f:
        f.write("\n".join(full_markdown))

def markdown_table(data):
    if not data:
        return ""
    header = [str(c or "").strip().replace("\n", " ") for c in data[0]]
    sep = ["---" for _ in header]
    lines = ["| " + " | ".join(header) + " |", "| " + " | ".join(sep) + " |"]
    for row in data[1:]:
        cleaned_row = [str(c or "").strip().replace("\n", " ") for c in row]
        lines.append("| " + " | ".join(cleaned_row) + " |")
    return "\n".join(lines)

if __name__ == '__main__':
    extract_clean_markdown("sample_input.pdf", "cleaned_output.md")
```

## 风险与边界
- 纯扫描件或手机翻拍图片必须前置 OCR 模块，不可直接通过文本流解析，否则会返回空字符。
- 带有安全密码保护（User Password / Owner Password）的文档需先解密。
- 特殊排版（如公式、竖排古籍、复杂嵌套表格）需要结合专门的视觉模型进行结构化复现。

## 使用建议
- 在灌入 RAG 向量数据库前，务必对 PDF 做“分块前清洗”，剔除重复率极高的页眉（如期刊名、卷号）以防向量检索命中歧义。
- 表格提取时若发现单元格边框缺失，可启用 `pdfplumber` 的 `explicit_vertical_lines` 策略。

## 成功标准
- 双栏文档阅读流无拼合倒错。
- 提取出的 Markdown 表格行列对齐、表头清晰。
- 知识库分块检索召回率相比直接文本抽取提升 30% 以上。

## 源文件
来源：awesome-openclaw-zh  
原始文件：pdf.md
