返回

Google Document AI 文档拆分:解决训练文档数量不足问题

Ai

如何将 Google Document AI 文档拆分成单独的页面?

遇到了 Document AI 自定义抽取器训练的难题?想要训练,却被告知需要至少 10 个训练文档和 10 个测试文档,而不是 10 个页面? 我之前就踩过这个坑。标注了四个不同的文档,每个文档 15-30 页,总共差不多标注了 100 页。 结果准备训练时,却被这个“文档数量”门槛卡住了。

我的使用场景里,这些页面完全可以作为独立的文档存在。问题是,有没有办法把这些文档拆开,让每个已标注的页面都变成一个独立的文档,从而绕过 Document AI 的限制?

我研究过 Document JSON 的结构,想看看能不能写点代码直接处理,但没搞定。下面,我把我的解决过程和找到的一些方法分享给你。

一、 问题根源:Document AI 的文档定义

Document AI 对“文档”的定义,与我们日常理解的“文档”可能不太一样。 在 Document AI 看来,一个上传的 PDF 文件,不管里面有多少页,它都算作一个“文档”。 这也是为什么我们即使标注了上百页,也会被提示“文档数量不足”的原因。

二、 解决方案:拆分!

既然问题出在“文档”数量不够,那我们就想办法把“文档”变多。 核心思路:将多页的 PDF 文档拆分成多个单页的 PDF 文档。

1. 使用 Python 和 PyPDF2

PyPDF2 是一个非常流行的 Python 库,可以用来处理 PDF 文件,包括拆分、合并、旋转页面等操作。

  • 原理: PyPDF2 通过读取 PDF 文件的每一页,然后将每一页单独写入一个新的 PDF 文件,从而实现拆分。

  • 代码示例:

from PyPDF2 import PdfReader, PdfWriter

def split_pdf(input_pdf_path, output_folder):
    """
    将 PDF 文件拆分为单页 PDF。

    Args:
        input_pdf_path: 输入 PDF 文件的路径。
        output_folder:  输出文件夹的路径。
    """
    try:
        with open(input_pdf_path, "rb") as input_file:
            pdf_reader = PdfReader(input_file)
            num_pages = len(pdf_reader.pages)

            for page_num in range(num_pages):
                pdf_writer = PdfWriter()
                pdf_writer.add_page(pdf_reader.pages[page_num])

                output_filename = f"{output_folder}/page_{page_num + 1}.pdf"
                with open(output_filename, "wb") as output_file:
                    pdf_writer.write(output_file)

            print(f"已将 {input_pdf_path} 拆分为 {num_pages} 个单页 PDF 文件,保存在 {output_folder}")

    except FileNotFoundError:
        print(f"错误:找不到文件 {input_pdf_path}")
    except Exception as e:
        print(f"发生错误:{e}")
# 示例用法: 假设你的 pdf 在同一文件夹,且命名为 document.pdf。要导出到 output文件夹
split_pdf("document.pdf", "output")

  • 安装 PyPDF2
pip install PyPDF2
  • 使用说明:

    1. 将上面的代码保存为 Python 文件 (例如 split_pdf.py).
    2. 将需要拆分的 PDF 文件放到与脚本相同的目录下,或者修改 input_pdf_path 为 PDF 文件的绝对路径。
    3. 创建一个用于存放拆分后文件的文件夹 (例如 output),或修改output_folder.
    4. 运行脚本: python split_pdf.py
  • 进阶技巧:
    可以根据文件名进行批量处理.

import os
from PyPDF2 import PdfReader, PdfWriter

def split_pdf(input_pdf_path, output_folder):
    #与之前相同,略过.
    try:
        with open(input_pdf_path, "rb") as input_file:
            pdf_reader = PdfReader(input_file)
            num_pages = len(pdf_reader.pages)

            for page_num in range(num_pages):
                pdf_writer = PdfWriter()
                pdf_writer.add_page(pdf_reader.pages[page_num])

                output_filename = f"{output_folder}/page_{page_num + 1}.pdf"
                with open(output_filename, "wb") as output_file:
                    pdf_writer.write(output_file)

            print(f"已将 {input_pdf_path} 拆分为 {num_pages} 个单页 PDF 文件,保存在 {output_folder}")

    except FileNotFoundError:
        print(f"错误:找不到文件 {input_pdf_path}")
    except Exception as e:
        print(f"发生错误:{e}")

def batch_split_pdfs(input_folder, output_folder):
    """批量拆分指定文件夹中的所有 PDF 文件。"""
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)

    for filename in os.listdir(input_folder):
        if filename.endswith(".pdf"):
            input_pdf_path = os.path.join(input_folder, filename)
            split_pdf(input_pdf_path, output_folder)

#使用例子. 将 "input_pdfs" 里的所有 pdf, 拆分输出到"output_pdfs" 文件夹里
batch_split_pdfs("input_pdfs", "output_pdfs")

2. 使用 pdfseparate (Linux 命令行工具)

如果你使用的是 Linux 系统,pdfseparate 是一个非常方便的命令行工具,可以直接用来拆分 PDF 文件。 pdfseparate 通常包含在 poppler-utils 或类似的软件包中。

  • 原理: pdfseparate 直接从 PDF 文件中提取每一页,并将其保存为单独的 PDF 文件。

  • 命令行指令:

pdfseparate input.pdf output-%d.pdf
  • 安装(如果还没有):

    • Debian/Ubuntu: sudo apt-get install poppler-utils
    • Fedora/CentOS/RHEL: sudo yum install poppler-utils
  • 使用说明:

    • input.pdf 替换为你要拆分的 PDF 文件的名称。
    • output-%d.pdf 是输出文件的命名模式,%d 会被替换为页码。例如,第一页会保存为 output-1.pdf,第二页会保存为 output-2.pdf,依此类推。
    • 拆分后的文件会保存在当前目录下。
  • 进阶使用
    你可以使用简单的bash脚本来处理多个文件。

#!/bin/bash

input_folder="input_pdfs"
output_folder="output_pdfs"

mkdir -p "$output_folder"  # 如果输出文件夹不存在,则创建

for file in "$input_folder"/*.pdf; do
  if [ -f "$file" ]; then
    filename=$(basename "$file")
    filename_no_ext="${filename%.*}"
    pdfseparate "$file" "$output_folder/${filename_no_ext}-%d.pdf"
    echo "已拆分:$file"
  fi
done

echo "拆分完成。"

3. 使用 pdftk (跨平台命令行工具)

pdftk (PDF Toolkit) 是一个功能更强大的 PDF 处理工具,支持 Windows、macOS 和 Linux。可以用来执行各种 PDF 操作,包括拆分、合并、加密、解密、旋转、添加水印等。

  • 原理 : 与pdfseparate 相似, pdftk 可以利用burst 操作来提取出文档每一页。

  • 命令行指令:

pdftk input.pdf burst output output-%02d.pdf
  • 安装 (如果没有):
    访问 pdftk 官网或使用包管理器安装

  • 使用说明:

    • input.pdf 是输入 PDF 文件名
    • burst 命令会将 PDF 文件拆分成单页。
    • output output-%02d.pdf 指定了输出文件名。%02d 会被替换为页码,并保证页码至少有两位数(例如 01, 02, 03...)。

4. 使用在线 PDF 拆分工具

如果你不想安装任何软件,或者只需要偶尔拆分一下 PDF 文件,可以使用在线的 PDF 拆分工具。

  • 原理: 这些在线工具通常会在服务器端进行 PDF 文件的处理,然后提供下载链接。
  • 注意: 使用这些工具时需要特别注意数据安全, 上传文件可能有安全风险,对于敏感的 PDF 文件,请选择知名、可靠的在线工具, 或最好使用本地的工具

5. 上传至 Document AI 并重新标注 (最后的步骤!)

无论你选择哪种方法拆分 PDF 文件,最后都需要将拆分后的单页 PDF 文件重新上传到 Document AI,并进行标注。

  • 重点提示: 由于现在每个页面都是一个独立的文档,你需要确保在上传时将它们正确地分配到训练集和测试集,以满足 Document AI 的要求 (最少 10 个训练, 10个测试).

补充说明 : 将每个页面都单独标注虽然有些麻烦, 但从长远来看可以带来好处。 Document AI可以更好地学习每个页面特有的特征,提升模型的准确率。拆分后再训练也是一个常见的优化策略。