mylogo

退役程序员的茶室 RetiredCoder.cn

← 返回上一页

如何用Python提取PDF文件中的图片

上文我们介绍如何用pdfplumber快速将PDF文档转化为可编辑的纯文本文件,这次我们来看看对图片的提取(对应的视频课程已先在视频号「退役程序员」中发布)。

所需要的库pdfplumber

有很多的库都可以用于处理PDF文档,例如PyMuPDF、PyPDF2、pdfplumber、pikepdf等等,它们各自有着特定的优势和用途,为了实现对文本、图片和表格的简单提取功能,这里我选用的是pdfplumber,大家可以访问下面链接来对这个库有个大致了解:

https://pypi.org/project/pdfplumber/

在开始写代码前,我们需要用以下命令对这个库进行安装:

pip install pdfplumber

提取图片的代码部分

def extract_image(file_path):
    try:
        with pdfplumber.open(file_path) as pdf:
            for i, page in enumerate(pdf.pages):
                for j, image in enumerate(page.images):
                    image_stream = image['stream']
                    image_data = image_stream.get_data()
                    image_bytes = io.BytesIO(image_data)
                    extrImage = Image.open(image_bytes)
                    extrImage.save(f"image_{i+1}_{j}.jpg")
    except FileNotFoundError:
        print(f"Error: The file '{file_path}' does not exist.")
    except Exception as e:
        print(f"Error: An error occurred while processing the file: {e}")

代码解析

for i, page in enumerate(pdf.pages):
    for j, image in enumerate(page.images):

这两行代码中的第一个for循环,用于遍历PDF文档中的每一页。pdf.pages是一个类似于列表的对象,包含PDF的所有页面。enumerate函数用于同时获取页面的索引 (i,从 0 开始) 和页面对象 (page)。

而嵌套的第二个for循环遍历当前page上找到的每一个图像。page.images提供了一个包含该特定页面上所有图像对象的列表。同样,enumerate 用于获取图像的索引 (j) 和image对象。

image_stream = image['stream']

这里的每个image对象是一个字典类型的数据,包含着各种键值。这行代码访问存储在'stream'键下原始图像数据流,并将其赋值给image_stream

image_data = image_stream.get_data()

这行代码通过调用image_stream对象的get_data()方法,从 image_stream中提取实际的二进制图像数据。这些数据随后存储在 image_data变量中。

image_bytes = io.BytesIO(image_data)

用于图像处理的PIL(Pillow) 库通常要求图像数据以类似文件对象的格式存在。这行代码使用io.BytesIO将原始image_data包装在一个内存中的二进制流中,使其表现得像一个文件。

extrImage = Image.open(image_bytes)

这行代码使用Pillow库中的Image.open()函数从image_bytes流中打开图像数据。打开的图像对象被赋值给extrImage

extrImage.save(f"image_{i+1}_{j}.jpg")

这行代码将提取的图像保存到文件中。文件名使用 f-string 构建:

  • {i+1}表示页码(i 从 0 开始,所以加 1)。

  • {j}表示该页面上的图像序号(从 0 开始)。

完整代码

# pdfconverter.py
import pdfplumber
import sys
import io
from PIL import Image

def extract_text(file_path):
    """
    Extracts text from a PDF file and saves it as a TXT file.
    
    Args:
        file_path (str): Path to the PDF file.
    
    Returns:
        None
    """
    output_file = file_path.split('.')[0] + '.txt'
    try:
        with pdfplumber.open(file_path) as pdf:
            txt = ''
            for page in pdf.pages:
                txt += page.extract_text()
            with open(output_file, 'w', encoding='utf-8') as f:
                f.write(txt)
    except FileNotFoundError:
        print(f"Error: The file '{file_path}' does not exist.")
    except Exception as e:
        print(f"Error: An error occurred while processing the file: {e}")

def extract_image(file_path):
    try:
        with pdfplumber.open(file_path) as pdf:
            for i, page in enumerate(pdf.pages):
                for j, image in enumerate(page.images):
                    image_stream = image['stream']
                    image_data = image_stream.get_data()
                    image_bytes = io.BytesIO(image_data)
                    extrImage = Image.open(image_bytes)
                    extrImage.save(f"image_{i+1}_{j}.jpg")
    except FileNotFoundError:
        print(f"Error: The file '{file_path}' does not exist.")
    except Exception as e:
        print(f"Error: An error occurred while processing the file: {e}")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python pdfconverter.py <pdf_file>")
    else:
        file_path = sys.argv[1]
        extract_text(file_path)
        extract_image(file_path)