返回

PyMuPDF \

python

解决 PyMuPDF 的“xref = 137”错误:从 PDF 中提取文本和图像的完整指南

简介

在使用 PyMuPDF 库从 PDF 文档中提取文本和图像时,一个常见的错误是“xref = 137”。这个错误表明使用的交叉引用不正确,阻碍了图像的提取。本文将深入探讨这个错误的原因,并提供一个分步指南,让你准确地提取 PDF 中的文本和图像。

错误根源

“xref = 137”错误源于使用错误的交叉引用来提取图像。代码中通常使用 xref = img[0] 提取图像,但这在某些情况下是不准确的。正确获取交叉引用的方法是使用 xref = block['image'][0]

分步指南

以下是如何解决“xref = 137”错误并从 PDF 中提取文本和图像的分步指南:

  1. 导入库:

    import fitz
    
  2. 打开 PDF 文档:

    doc = fitz.open(pdf_path)
    
  3. 循环遍历页面:

    for page_num in range(len(doc)):
        page = doc.load_page(page_num)
    
  4. 获取文本和图像块:

    blocks = page.get_text("dict")["blocks"]
    
  5. 循环遍历块:

    for block in blocks:
    
  6. 识别图像块:

    if block['type'] == 1:
    
  7. 获取正确的交叉引用:

    xref = block['image'][0]
    
  8. 提取并保存图像:

    base_image = doc.extract_image(xref)
    image_filename = f"image_{image_counter}.png"
    with open(image_filename, "wb") as img_file:
        img_file.write(base_image["image"])
    
  9. 在提取的文本中添加图像标签:

    image_label = f"<<<image_{image_counter}>>>"
    full_text += f"{image_label}\n"
    
  10. 关闭 PDF 文档:

doc.close()

完整示例代码

以下是完整示例代码,展示了如何使用正确的交叉引用从 PDF 文档中提取文本和图像:

import fitz

def extract_text_and_save_images(pdf_path):

    doc = fitz.open(pdf_path)
    full_text = ""
    image_counter = 1  # Initialize the image counter before iterating through pages

    for page_num in range(len(doc)):  # Iterate through each page of the pdf document

        page = doc.load_page(page_num)  # Load the pdf page
        blocks = page.get_text("dict")["blocks"]  # The list of block dictionaries

        for block in blocks:  # Iterate through each block

            if block['type'] == 0:  # If the block is a text block
                for line in block["lines"]:  # Iterate through lines in the block
                    for span in line["spans"]:  # Iterate through spans in the line
                        full_text += span["text"] + " "  # Append text to full_text
                full_text += "\n"  # Add newline after each block

            elif block['type'] == 1:  # If the block is an image block
                image_label = f"<<<image_{image_counter}>>>"  # Label to insert in the extracted text in place of the corresponding image
                full_text += f"{image_label}\n"  # Insert image label at the image location
                img = block['image']
                xref = img[0]
                base_image = doc.extract_image(xref)  # Extract image
                image_bytes = base_image["image"]
                image_filename = f"image_{image_counter}.png"

                with open(image_filename, "wb") as img_file:  # Save the image
                    img_file.write(image_bytes)

                image_counter += 1  # Increment counter for next image

    doc.close()  # Close the pdf document
    return full_text

pdf_path = "path_to_your_pdf_file.pdf"
extracted_text = extract_text_and_save_images(pdf_path)
print(extracted_text)

常见问题解答

1. 如何处理 PDF 中有多个交叉引用指向同一图像的情况?

  • 在这种情况下,你可以使用 doc.resolve_xref(xref) 函数获取正确的交叉引用。

2. 如何识别表格中的图像?

  • 对于表格中的图像,你可以使用 block['type'] == 13 条件来识别它们。

3. 如何使用 PyMuPDF 提取 SVG 图像?

  • PyMuPDF 目前不支持直接提取 SVG 图像。不过,你可以使用 image_bytes 保存图像,然后使用第三方库(如 Pillow)将其转换为 SVG。

4. 我无法获取图像的完整内容。如何解决?

  • 确保你使用 base_image["image"] 而非 base_imagebase_image 包含有关图像的其他元数据。

5. 从 PDF 中提取图像后,如何保持它们的质量?

  • PyMuPDF 提供的图像质量取决于 PDF 文档中的原始图像质量。