专栏名称: 深度学习与计算机视觉
深度学习与计算机视觉碰撞出了新的火花,本公众号将坚持分享原创计算机视觉技术相关文章。主要分为实战教程、视觉领域最新咨询、国内外最新论文翻译三类。欢迎志同道合的朋友关注。
目录
相关文章推荐
三联生活周刊  ·  从12位红楼女性的命运,透视清朝法律与社会 ·  3 天前  
51好读  ›  专栏  ›  深度学习与计算机视觉

用Python从PDF文件中提取文本:全面指南

深度学习与计算机视觉  · 公众号  ·  · 2024-06-03 18:16

正文

引言

在大语言模型(LLMs)的时代,它们的应用范围从简单的文本摘要和翻译到基于情感和财务报告主题预测股票表现,文本数据的重要性前所未有。

有许多类型的文档共享这种非结构化信息,从网页文章和博客帖子到手写信件和诗歌。然而,这些文本数据的大部分以PDF格式存储和传输。具体而言,每年在Outlook中打开的PDF文档超过20亿份,而每天在Google Drive和电子邮件中保存的新PDF文件达7300万份(2)。

因此,更系统地处理这些文档并从中提取信息将使我们能够拥有自动化的流程,并更好地理解和利用这庞大的文本数据。而在这项任务中,当然,我们最好的朋友莫过于Python。

然而,在我们开始处理之前,我们需要明确当前存在的不同类型的PDF文档,更具体地说,是三种最频繁出现的类型:

  1. 程序生成的PDF:这些PDF是使用计算机上的W3C技术(如HTML、CSS和Javascript)或其他软件(如Adobe Acrobat)创建的。这种类型的文件可以包含各种组件,如图像、文本和链接,这些组件都是可搜索且易于编辑的。

  2. 传统扫描文档:这些PDF是通过扫描仪或移动应用程序从非电子媒介创建的。这些文件实际上只是存储在PDF文件中的图像集合。换句话说,这些图像中出现的元素,如文本或链接,无法选择或搜索。实质上,PDF文件只是这些图像的容器。

  3. 带有OCR的扫描文档:在这种情况下,扫描文档后使用光学字符识别(OCR)软件来识别文件中每个图像中的文本,并将其转换为可搜索和可编辑的文本。然后,软件在图像上添加一个包含实际文本的层,这样当浏览文件时,您可以将其选择为单独的组件(3)。

尽管现在越来越多的机器都安装了OCR系统来识别扫描文档中的文本,但仍然存在一些包含整个页面的图像格式文档。您可能已经看到过,当您阅读一篇精彩的文章并尝试选择一句话时,却选择了整个页面。这可能是特定OCR机器的限制或其完全缺失的结果。为了不让这些信息在本文中被忽视,我试图创建一个考虑到这些情况并充分利用我们宝贵且信息丰富的PDF的过程。


理论方法

在考虑到所有这些不同类型的PDF文件和构成它们的各种元素的基础上,进行对PDF布局的初步分析以识别每个组件所需的适当工具非常重要。更具体地说,根据这一分析的结果,我们将应用适当的方法从PDF中提取文本,无论是呈现在语料库块中的文本及其元数据、图像中的文本还是表格中的结构化文本。在没有OCR的扫描文档中,识别并从图像中提取文本的方法将完成所有繁重的工作。该过程的输出将是一个Python字典,其中包含从PDF文件的每一页提取的信息。该字典中的每个键将呈现文档的页码,其对应的值将是包含以下5个嵌套列表的列表:

  1. 语料库块的每个文本块提取的文本

  2. 每个文本块中文本的字体系列和大小的格式

  3. 页面上提取的图像中的文本

  4. 以结构化格式提取的表格中的文本

  5. 页面的完整文本内容

通过这种方式,我们可以更合理地将从不同源组件中提取的文本分离开,有时可以帮助我们更容易地检索通常出现在特定组件中的信息(例如,标志图像中的公司名称)。此外,从文本中提取的元数据,如字体系列和大小,可以用于轻松识别文本标题或更重要的突出文本,从而帮助我们进一步将文本分成多个不同的块进行后处理。最后,在LLM能够理解的方式中保留结构化表格信息将显著增强对提取数据内关系的推断质量。然后,这些结果可以组合成一个输出,包含每一页上出现的所有文本信息。

您可以在下面的图像中看到这种方法的流程图。


安装所有必要的库

在开始这个项目之前,我们应该安装所需的库。我们假设您的计算机上已经安装了Python 3.10或更高版本。否则,您可以从这里安装。然后让我们安装以下库:

PyPDF2:用于从存储库路径读取PDF文件。

pip install PyPDF2

Pdfminer:用于执行布局分析并从PDF中提取文本和格式(该库的.six版本是支持Python 3的版本)。

pip install pdfminer.six

Pdfplumber:用于识别PDF页面中的表格并从中提取信息。

pip install pdfplumber

Pdf2image:用于将裁剪后的PDF图像转换为PNG图像。

pip install pdf2image

PIL:用于读取PNG图像。

pip install Pillow

Pytesseract:使用OCR技术从图像中提取文本。

这个安装稍微复杂,因为首先您需要安装Google Tesseract OCR,这是一种基于LSTM模型的OCR机器,用于识别行和字符模式。

如果您是Mac用户,您可以通过终端使用Brew来安装,然后即可使用。

brew install tesseract

对于Windows用户,您可以按照这个链接中的步骤进行安装。然后,当您下载并安装软件时,您需要将其可执行路径添加到计算机的环境变量中。或者,您可以运行以下命令,直接在Python脚本中使用以下代码将其路径包含进去:

pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

然后您可以安装Python库。

pip install pytesseract

最后,我们将在脚本的开头导入所有的库。

# To read the PDF
import PyPDF2
# To analyze the PDF layout and extract text
from pdfminer.high_level import extract_pages, extract_text
from pdfminer.layout import LTTextContainer, LTChar, LTRect, LTFigure
# To extract text from tables in PDF
import pdfplumber
# To extract the images from the PDFs
from PIL import Image
from pdf2image import  convert_from_path
# To perform OCR to extract text from images 
import pytesseract 
# To remove the additional created files
import os

现在我们已经准备好了。让我们进入有趣的部分。


使用Python进行文档布局分析

在初步分析中,我们使用了PDFMiner Python库,将文档对象中的文本分离为多个页面对象,然后分解和检查每个页面的布局。PDF文件本质上缺乏结构化信息,如人眼看到的段落、句子或单词。相反,它们只理解文本的单个字符以及它们在页面上的位置。因此,PDFMiner试图将页面的内容重构为其个体字符以及它们在文件中的位置。然后,通过比较这些字符与其他字符的距离,它组合成适当的单词、句子、行和段落的文本(4)。为了实现这一点,该库:

使用高级函数 extract_pages() 将PDF文件中的各个页面分离,并将它们转换为 LTPage 对象。

对于每个LTPage对象,它从上到下迭代每个元素,并尝试识别适当的组件,包括:

  • LTFigure :表示PDF中可以呈现为图形或图像的区域,这些图形或图像已嵌入到页面中作为另一个PDF文档。

  • LTTextContainer :表示矩形区域内的一组文本行,然后进一步分析为 LTTextLine 对象列表。每个 LTTextLine 对象表示一个 LTChar 对象列表,它存储文本的单个字符及其元数据(5)。

  • LTRect :表示可用于框架图像和图形或在 LTPage 对象中创建表格的二维矩形。

基于对页面的这种重构以及将其元素分类为 LTFigure (包含页面上的图像或图形)、 LTTextContainer (表示页面的文本信息)或 LTRect (表明存在表格的强烈迹象),我们可以应用适当的函数更好地提取信息。

for pagenum, page in enumerate(extract_pages(pdf_path)):

    # Iterate the elements that composed a page
    for element in page:

        # Check if the element is a text element
        if isinstance(element, LTTextContainer):
            # Function to extract text from the text block
            pass
            # Function to extract text format
            pass

        # Check the elements for images
        if isinstance(element, LTFigure):
            # Function to convert PDF to Image
            pass
            # Function to extract text with OCR
            pass

        # Check the elements for tables
        if isinstance(element, LTRect):
            # Function to extract table
            pass
            # Function to convert table content into a string
            pass

因此,现在我们理解了流程分析的部分,让我们创建从每个组件中提取文本所需的函数。


定义从PDF中提取文本的函数

从这里开始,从文本容器中提取文本非常简单。

# Create a function to extract text

def text_extraction(element):
    # Extracting the text from the in-line text element
    line_text = element.get_text()

    # Find the formats of the text
    # Initialize the list with all the formats that appeared in the line of text
    line_formats = []
    for text_line in element:
        if isinstance(text_line, LTTextContainer):
            # Iterating through each character in the line of text
            for character in text_line:
                if isinstance(character, LTChar):
                    # Append the font name of the character
                    line_formats.append(character.fontname)
                    # Append the font size of the character
                    line_formats.append(character.size)
    # Find the unique font sizes and names in the line
    format_per_line = list(set(line_formats))

    # Return a tuple with the text in each line along with its format
    return (line_text, format_per_line)

要从文本容器中提取文本,我们只需使用LTTextContainer元素的get_text()方法。此方法检索构成特定语料库框内单词的所有字符,并将输出存储在文本数据列表中。此列表中的每个元素代表容器中包含的原始文本信息。

现在,为了识别此文本的格式,我们迭代LTTextContainer对象以逐个访问此语料库的每一行。在每次迭代中,都会创建一个新的LTTextLine对象,表示此语料块中的文本行。然后,我们检查嵌套的行元素是否包含文本。如果包含,我们访问每个单独的字符元素,即LTChar,其中包含该字符的所有元数据。从这些元数据中,我们提取两种格式,并将它们存储在一个分开的列表中,相应地放置在检查的文本中:

  1. 字符的字体系列,包括字符是否以粗体或斜体格式显示。

  2. 字符的字体大小。

通常,特定文本块中的字符往往具有一致的格式,除非某些字符以粗体突出显示。为了便于进一步分析,我们为文本中的所有字符捕获文本格式的唯一值,并将它们存储在适当的列表中。


定义从图像中提取文本的函数

在这里,我认为这是一个更棘手的部分。

如何处理在PDF中找到的图像中的文本?

首先,我们需要在这里明确,存储在PDF中的图像元素并不是与文件(如JPEG或PNG)不同的格式。因此,为了在它们上应用OCR软件,我们需要首先将它们从文件中分离出来,然后将它们转换为图像格式。

# Create a function to crop the image elements from PDFs
def crop_image(element, pageObj):
    # Get the coordinates to crop the image from the PDF
    [image_left, image_top, image_right, image_bottom] = [element.x0,element.y0,element.x1,element.y1] 
    # Crop the page using coordinates (left, bottom, right, top)
    pageObj.mediabox.lower_left = (image_left, image_bottom)
    pageObj.mediabox.upper_right = (image_right, image_top)
    # Save the cropped page to a new PDF
    cropped_pdf_writer = PyPDF2.PdfWriter()
    cropped_pdf_writer.add_page(pageObj)
    # Save the cropped PDF to a new file
    with open('cropped_image.pdf''wb'as cropped_pdf_file:
        cropped_pdf_writer.write(cropped_pdf_file)

# Create a function to convert the PDF to images
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")

# Create a function to read text from images
def image_to_text(image_path):
    # Read the image
    img = Image.open(image_path)
    # Extract the text from the image
    text = pytesseract.image_to_string(img)
    return text

为实现此目的,我们遵循以下过程:

  1. 我们使用从PDFMiner检测到的LTFigure对象的元数据来裁剪图像框,利用其在页面布局中的坐标。然后,我们使用PyPDF2库将其保存为我们目录中的新PDF。







请到「今天看啥」查看全文