PDF

导图一览:

工具名称功能技术输出格式特点
PyPDF 提取文本、图像和元数据 基于规则 (RB) TXT 成熟的纯 Python 库,处理多种 PDF 操作
pdfminer.six 提取文本、图像、目录、字体大小 基于规则 TXT、HTML、hOCR、JPG 多功能,支持 CJK 语言和垂直书写
PDFPlumber 提取文本和表格 基于规则 (基于 pdfminer) TXT、HTML、hOCR、JPG 提供可视化调试工具,提取过程便捷
PyMuPDF 提取文本、表格和图像 基于规则 (MuPDF),可选 OCR TXT、HTML、SVG、JSON Python 绑定,处理复杂文档布局
pypdfium2 提取文本 基于规则 TXT 轻量级库,专注文本提取
Unstructured 预处理和摄取图像及文本文档 基于规则,支持 OCR TXT 支持元素级文本和表格提取
Tabula 提取表格 基于规则 DataFrame、CSV、JSON Python 包装器,使用 tabula-java
Camelot 提取表格 基于规则 DataFrame、CSV、JSON、HTML 灵活配置,支持流模式和格子模式
Nougat 提取文本 基于 Transformer Markdown 深度学习模型,专为学术文档训练
Table Transformer (TATR) 检测表格 基于 Transformer 图像 对象检测模型,训练于 PubTables-1M 等

 

 

 

 

 

 

 

 

 

pdfplumber

pdfplumber库按页处理 pdf ,获取页面文字,提取表格等操作。

学习文档:

import pdfplumber
with pdfplumber.open("E:\新员工\【学员讲义】企业文化.pdf") as pdf:
    page01 = pdf.pages[9] #指定页码
    text = page01.extract_text()#提取文本
    print(text)

    table = page01.extract_tables()  # 提取表格
    print(table)

优势:

1. pdfplumber能轻松访问有关PDF对象的所有详细信息,且用于提取文本和表格的方法高级可定制,使用者可根据表格的具体形式来调整参数。

2. 最关键的是pdfplumber作者持续在维护该库,而同样受欢迎的PyPDF2已经不再维护了。

劣势:

1. 提取的 英文 中间没有空格

 

PyPDF2 

PyPDF2 是一个纯 Python PDF 库,可以读取文档信息(标题,作者等)、写入、分割、合并PDF文档,它还可以对pdf文档进行添加水印、加密解密等。

官方文档:          https://www.w3cschool.cn/pypdf2/

import PyPDF2
def extract_text_from_pdf(pdf_path):
    with open(pdf_path, 'rb') as file:
        pdf_reader = PyPDF2.PdfFileReader(file)
        num_pages = pdf_reader.numPages
        text = ""
        for page_num in range(num_pages):
            page = pdf_reader.getPage(page_num)
            text += page.extractText()
    return text

pdf_path = 'example.pdf'
extracted_text = extract_text_from_pdf(pdf_path)
print(extracted_text)
View Code

版本 2.6.0

劣势:

1.英文识别不行,识别成单个字母了 S o l a r

2.表格无法识别

 

pdf2docx

可将 PDF 转换成 docx 文件的 Python 库。

该项目通过 PyMuPDF 库提取 PDF 文件中的数据,然后采用 python-docx 库解析内容的布局、段落、图片、表格等,最后自动生成 docx 文件。

from pdf2docx import parse

pdf_file = 'E:\新员工\【学员讲义】企业文化.pdf'
docx_file = 'E:\新员工\【学员讲义】企业文化2.docx'

# convert pdf to docx
parse(pdf_file, docx_file)

 

PDFminer

PDFMiner内置pdf2txt.py和dumppdf.py。但是pdf2txt.py从PDF文件中提取所有文本内容。但不能识别画成图片的文本,这需要对图片特征进行识别。对于加密的PDF你需要提供一个密码才能解析,对于没有提取权限的PDF文档你得不到任何文本。

https://pdfminersix.readthedocs.io

对于每个LTPage对象,它从上到下遍历每个元素,并尝试将适当的组件识别为:

  • LTFigure:表示PDF中页面上的图形或图像的区域。
  • LTTextContainer:代表一个矩形区域(段落)中的一组文本行(line),然后进一步分析成LTTextLine对象的列表。它们中的每一个都表示一个LTChar对象列表,这些对象存储文本的单个字符及其元数据
  • LTRect表示一个二维矩形,可用于在LTPage对象中占位区或者Panel,图形或创建

因此,使用Python对页面进行重构之后,将页面元素分类为LTFigure(图像或图形)、LTTextContainer(文本信息)或LTRect(表格)

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from io import StringIO

# 打开PDF文件
with open('example.pdf', 'rb') as file:
    # 创建一个PDFResourceManager对象
    resource_manager = PDFResourceManager()
    # 创建一个StringIO对象,用于存储提取的文本内容
    output = StringIO()
    # 创建一个TextConverter对象
    converter = TextConverter(resource_manager, output, laparams=LAParams())
    # 创建一个PDFPageInterpreter对象
    interpreter = PDFPageInterpreter(resource_manager, converter)
    # 逐页解析文档
    for page in PDFPage.get_pages(file):
        interpreter.process_page(page)
    # 获取提取的文本内容
    text = output.getvalue()
    print(text)
View Code
from pdfminer.high_level import extract_text
extracted_text = extract_text(pdf)
print(extracted_text)
View Code

 

Pdfminer.six

Pdfminer.six 是PDFMiner的一个分支。

它是一种从PDF中解析、提取信息的工具文件,侧重于获取和分析文本数据、元数据和图片,还可用于获取文本的确切位置、字体或颜色。Pdfminer.six 直接从页面中提取文本 PDF 的源代码。以模块化的方式构建,因此pdfminer.six的每个组件都可以轻松更换。

官方文档:https://pdfminersix.readthedocs.io/en/latest/index.html

代码参考:https://mp.weixin.qq.com/s/5OQGOT1rllEAE8_L-v4L9A

大概试了下,功能没那么强大

 

pymupdf

import fitz

def MuPDF_extract_text_from_pdf(path):
    doc = fitz.open(path)
    all_content = []
    page_nums = 0
    for i in doc.pages():
        page_nums += 1
        all_content.append(i.get_text())
    text = '\n'.join(all_content)
    # text = ''.join(text.split('\n'))
    return text
View Code

 

papermerge

from papermage.recipes import CoreRecipe

recipe = CoreRecipe()
doc = recipe.run("example.pdf")
for page in doc.pages:
    for row in page.rows:
        print(row.text)

 

xpdf

这个文本介绍了Xpdf,一个免费的PDF浏览器和工具包。它包括文本提取器、图片转换器、HTML转换器等工具,大部分工具都是开源的。

http://www.xpdfreader.com/

 

img2table

https://mp.weixin.qq.com/s/kPxiw4sgrr8Z3dHUt60dyw

 

综合运用上述模块

https://mp.weixin.qq.com/s/4mg59Sb7TzaoXVctEMJVWw  使用python提取PDF中的文本信息(包括表格和图片OCR) 

# 读取PDF
import PyPDF2
# 分析PDF的layout,提取文本
from pdfminer.high_level import extract_pages, extract_text
from pdfminer.layout import LTTextContainer, LTChar, LTRect, LTFigure
# 从PDF的表格中提取文本
import pdfplumber
# 从PDF中提取图片
from PIL import Image
from pdf2image import convert_from_path
# 运行OCR从图片中提取文本
import pytesseract
# 清除过程中的各种过程文件
import os

# 创建一个从pdf中裁剪图像元素的函数
def crop_image(element, pageObj):
    # 获取从PDF中裁剪图像的坐标
    [image_left, image_top, image_right, image_bottom] = [element.x0,element.y0,element.x1,element.y1]
    # 使用坐标(left, bottom, right, top)裁剪页面
    pageObj.mediabox.lower_left = (image_left, image_bottom)
    pageObj.mediabox.upper_right = (image_right, image_top)
    # 将裁剪后的页面保存为新的PDF
    cropped_pdf_writer = PyPDF2.PdfWriter()
    cropped_pdf_writer.add_page(pageObj)
    # 将裁剪好的PDF保存到一个新文件
    with open('cropped_image.pdf', 'wb') as cropped_pdf_file:
        cropped_pdf_writer.write(cropped_pdf_file)

# 创建一个将PDF内容转换为image的函数
def convert_to_images(input_file,):
    images = convert_from_path(input_file)
    image = images[0]
    output_file = "PDF_image.png"
    image.save(output_file, "PNG")

# 创建从图片中提取文本的函数
def image_to_text(image_path):
    # 读取图片
    img = Image.open(image_path)
    # 从图片中抽取文本
    text = pytesseract.image_to_string(img)
    return text

# 从页面中提取表格内容

def extract_table(pdf_path, page_num, table_num):
    # 打开PDF文件
    pdf = pdfplumber.open(pdf_path)
    # 查找已检查的页面
    table_page = pdf.pages[page_num]
    # 提取适当的表格
    table = table_page.extract_tables()[table_num]
    return table

# 将表格转换为适当的格式
def table_converter(table):
    table_string = ''
    # 遍历表格的每一行
    for row_num in range(len(table)):
        row = table[row_num]
        # 从warp的文字删除线路断路器
        cleaned_row = [item.replace('\n', ' ') if item is not None and '\n' in item else 'None' if item is None else item for item in row]
        # 将表格转换为字符串,注意'|'、'\n'
        table_string+=('|'+'|'.join(cleaned_row)+'|'+'\n')
    # 删除最后一个换行符
    table_string = table_string[:-1]
    return table_string


# 创建一个文本提取函数

def text_extraction(element):
    # 从行元素中提取文本
    line_text = element.get_text()

    # 探析文本的格式
    # 用文本行中出现的所有格式初始化列表
    line_formats = []
    for text_line in element:
        if isinstance(text_line, LTTextContainer):
            # 遍历文本行中的每个字符
            for character in text_line:
                if isinstance(character, LTChar):
                    # 追加字符的font-family
                    line_formats.append(character.fontname)
                    # 追加字符的font-size
                    line_formats.append(character.size)
    # 找到行中唯一的字体大小和名称
    format_per_line = list(set(line_formats))

    # 返回包含每行文本及其格式的元组
    return (line_text, format_per_line)

# 查找PDF路径
pdf_path = r'E:\5.pdf'


# 创建一个PDF文件对象
pdfFileObj = open(pdf_path, 'rb')
# 创建一个PDF阅读器对象
pdfReaded = PyPDF2.PdfReader(pdfFileObj)

# 创建字典以从每个图像中提取文本
text_per_page = {}
# 我们从PDF中提取页面
for pagenum, page in enumerate(extract_pages(pdf_path)):

    # 初始化从页面中提取文本所需的变量
    pageObj = pdfReaded.pages[pagenum]
    page_text = []
    line_format = []
    text_from_images = []
    text_from_tables = []
    page_content = []
    # 初始化检查表的数量
    table_num = 0
    first_element = True
    table_extraction_flag = False
    # 打开pdf文件
    pdf = pdfplumber.open(pdf_path)
    # 查找已检查的页面
    page_tables = pdf.pages[pagenum]
    # 找出本页上的表格数目
    tables = page_tables.find_tables()

    # 找到所有的元素
    page_elements = [(element.y1, element) for element in page._objs]
    # 对页面中出现的所有元素进行排序
    page_elements.sort(key=lambda a: a[0], reverse=True)

    # 查找组成页面的元素
    for i, component in enumerate(page_elements):
        # 提取PDF中元素顶部的位置
        pos = component[0]
        # 提取页面布局的元素
        element = component[1]

        # 检查该元素是否为文本元素
        if isinstance(element, LTTextContainer):
            print(i, 'LTTextContainer')
            # 检查文本是否出现在表中
            if table_extraction_flag == False:
                # 使用该函数提取每个文本元素的文本和格式
                (line_text, format_per_line) = text_extraction(element)
                # 将每行的文本追加到页文本
                page_text.append(line_text)
                # 附加每一行包含文本的格式
                line_format.append(format_per_line)
                page_content.append(line_text)
            else:
                # 省略表中出现的文本
                pass

        # 检查元素中的图像
        if isinstance(element, LTFigure):
            print(i, 'LTFigure')
            # 从PDF中裁剪图像
            crop_image(element, pageObj)
            # 将裁剪后的pdf转换为图像
            convert_to_images('cropped_image.pdf')
            # 从图像中提取文本
            image_text = image_to_text('PDF_image.png')
            text_from_images.append(image_text)
            page_content.append(image_text)
            # 在文本和格式列表中添加占位符
            page_text.append('image')
            line_format.append('image')

        # 检查表的元素
        if isinstance(element, LTRect):
            print(i, 'LTRect')
            # 如果第一个矩形元素
            if first_element == True and (table_num + 1) <= len(tables):
                # 找到表格的边界框
                lower_side = page.bbox[3] - tables[table_num].bbox[3]
                upper_side = element.y1
                # 从表中提取信息
                table = extract_table(pdf_path, pagenum, table_num)
                # 将表信息转换为结构化字符串格式
                table_string = table_converter(table)
                # 将表字符串追加到列表中
                text_from_tables.append(table_string)
                page_content.append(table_string)
                # 将标志设置为True以再次避免该内容
                table_extraction_flag = True
                # 让它成为另一个元素
                first_element = False
                # 在文本和格式列表中添加占位符
                page_text.append('table')
                line_format.append('table')

            # 检查我们是否已经从页面中提取了表
            # if element.y0 >= lower_side and element.y1 <= upper_side:
            #     pass
            # elif not isinstance(page_elements[i + 1][1], LTRect):
            if not isinstance(page_elements[i + 1][1], LTRect):
                table_extraction_flag = False
                first_element = True
                table_num += 1

    # 创建字典的键
    dctkey = 'Page_' + str(pagenum)
    # 将list的列表添加为页键的值
    text_per_page[dctkey] = [page_text, line_format, text_from_images, text_from_tables, page_content]

# 关闭pdf文件对象
pdfFileObj.close()

# 删除已创建的过程文件
os.remove('cropped_image.pdf')
os.remove('PDF_image.png')

# 显示页面内容
result = ''.join(text_per_page['Page_2'][3])    # text_per_page 看下数据格式
print(result)
View Code

 

doc docx

Python-dox:优点:能够解析docx格式文档;缺点:doc格式文档无法直接解析,需要进行转换为docx格式间接解析

# pip install python-docx
from docx import Document
doc = Document(file_path)

# 遍历文档中的所有段落
text = []
for paragraph in doc.paragraphs:
    text.append(paragraph.text)
print('*' * 200)

# 遍历文档中的所有表格
for table in doc.tables:
    for row in table.rows:
        for cell in row.cells:
            print(cell.text)
print('&' * 50)

# 遍历文档中的所有图片
for image in doc.inline_shapes:
    print(image.filename)
View Code

 

docx2pdf

from docx2pdf import convert
file = r'xx.docx'
convert(file, "output.pdf")

 

版面分析

文本分割模型在文档解析中的角色

单双栏区分

 

汇总 Marker、MinerU、olmOCR、Surya、GOT-OCR 2.0、Mistral OCR等十几个开源/闭源模型 

olmOCR

本地部署最强OCR大模型olmOCR!支持结构化精准提取复杂PDF文件内容!完美识别中英文文档、模糊扫描件与复杂表格!本地部署与实际测试全过程!医疗法律行业必备_哔哩哔哩_bilibili

olmOCR-7B:文档提取专用模型       GPU

Docling

看看ERC(5)- Docling 解析PDF之进阶篇

Docling:统一的多文档解析框架 支持多种文档类型的处理与转换          内置OCR性能有限,中文开源OCR模型需要自行支持

ParseStudio

想提取文字,要用 PyMuPDF;想识别表格,还得上 pdfplumber 或 Docling;结果提出来的数据格式还不统一,处理麻烦……

现在有了更优雅的选择:ParseStudio。专为PDF解析量身打造,它集成了Docling、PyMuPDF、LlamaParse三种解析引擎,API设计简洁,模块化架构让你随心切换解析器,轻松搞定多模态解析任务。

一站式PDF解析神器!统一封装Docling、PyMuPDF、LlamaParse,批量处理无压力!

 

Umi-OCR:开源、免费、离线、多功能的 OCR 图片文字识别软件 (qq.com) 

AI“落地”系列-RAG前置文档解析

MMDocIR:多模态文档检索新基准,提升长文档的智能检索能力

一个开源、高效、灵活的 PDF OCR 文字识别神器!

基于多模态大语言模型的 PDF 转 Markdown 工具MarkPDFDown

 


 

Pandoc:万能文档转换工具

256M参数多模态OCR神器,0.35秒解锁全文档奥秘!  CPU/低配 GPU

PDF文档解剖术!OCR神器+1,这个开源工具把复杂排版秒变结构化数据!      PDF Document Layout Analysis

MinerU

https://github.com/opendatalab/MinerU    

9.MinerU——RAG知识库预处理,PDF转Markdown文件(对数学公式友好)_哔哩哔哩_bilibili

PDF转markdown,AI知识库绝配,科研文献整理必备,MinerU将PDF转化为机器可读格式的工具_哔哩哔哩_bilibili

MinerU 是一个一站式开源高质量数据提取工具,支持 PDF、网页和多格式电子书的提取。 该项目解决了从各种文档中高效准确地提取数据的问题。

  • 支持多种文件格式,包括 PDF、网页和电子书。
  • 提供强大的表格识别功能,提升数据解析的准确性。
  • 多语言 OCR 支持,可检测和识别 84 种语言。
  • 优化内存使用,大幅降低硬件要求,提高性能表现。
  • 便于快速部署,并提供在线演示以展示功能。

 

MinerU 2.0以及远程调用

 

未开源

从复杂文档到AI秒懂的高质量数据:EasyDoc解析实战指南 

 

新出来的还没研究

PymuPDF4llm:PDF 提取的革命

利用LLM从非结构化PDF中提取结构化知识    PymuPDF4llm

PDF 文档提取和解析 API:使用最先进的 OCR 和 Ollama 支持的模型

 

 

>>>> 在线文档解析服务横评:TextIn、MinerU、MonkeyOCR 谁最适合企业知识库? (qq.com)

由于样本文档、参数配置的局限性,本次测试可能存在一定的随机性。 相对而言,TextIn 在线解析服务在表格识别、文档结构、跨页表格场景下比较优秀。

 

 

参考资料 还有很多方法,自行查看

 

 

 

参考资料:

https://mp.weixin.qq.com/s/9L_LwJvwn_F9C89J-yYezA  大模型下开源文档解析工具总结及技术思考  各种类型  代码很详尽 

https://zhuanlan.zhihu.com/p/344384506  Python操作PDF全总结|pdfplumber&PyPDF2

https://mp.weixin.qq.com/s/gCU1hYmmHpqiV9APHotrYA  只需2行代码,轻松将PDF转换成Word

十大PDF解析工具在不同文档类别中的比较研究 

https://mp.weixin.qq.com/s/W1TciuOp4FTBU09LHQYptQ  AI文档智能助理都是如何处理pdf的?