You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PyMuPDF提取PDF时,如何保持文本与图片的顺序?

PyMuPDF提取PDF文本与图片时保留顺序的解决方案

问题原因

你的代码先通过get_text("xhtml")获取文本,再从get_text("dict")提取图片块,然后用正则匹配xhtml里的img标签进行替换。但PyMuPDF生成的xhtml中,图片标签的顺序可能和页面实际图片位置不符(比如默认把图片放到页面末尾),同时你直接按索引对应img标签和图片块,两者的顺序并不匹配,导致图片位置错乱。

解决思路

放弃xhtml的方式,直接从get_text("dict")获取页面所有内容块(文本+图片),根据每个块在页面上的顶部y坐标排序(y值越小,位置越靠上),再逐个处理文本和图片块,这样就能严格保留页面上的内容顺序。

修改后的代码

import fitz
import io
from PIL import Image

lst = []
img_name = 1

doc = fitz.open("你的PDF文件路径.pdf")  # 替换为你的PDF路径

for page_num in range(len(doc)):
    page = doc.load_page(page_num)
    # 获取页面所有内容块(文本块type=0,图片块type=1)
    blocks = page.get_text("dict")["blocks"]
    
    # 按块的顶部y坐标排序,保证从上到下的顺序
    blocks.sort(key=lambda b: b["bbox"][1])
    
    page_content = []
    
    for block in blocks:
        if block["type"] == 0:
            # 处理文本块:提取所有行的文本,拼接成段落
            text = ""
            for line in block["lines"]:
                for span in line["spans"]:
                    # 处理格式:粗体、斜体
                    formatted_text = span["text"]
                    if span["flags"] & 1:  # 粗体标记
                        formatted_text = f"<b>{formatted_text}</b>"
                    if span["flags"] & 2:  # 斜体标记
                        formatted_text = f"<i>{formatted_text}</i>"
                    text += formatted_text
                text += " "
            page_content.append(f"<p>{text.strip()}</p>")
        
        elif block["type"] == 1:
            # 处理图片块:保存图片并生成img标签
            try:
                img_data = block["image"]
                image = Image.open(io.BytesIO(img_data))
                img_path = f"img_{img_name}.jpeg"
                image.save(img_path, "JPEG")
                # 添加img标签到内容中
                page_content.append(f'<p><img src="{img_path}" /></p>')
                img_name += 1
            except Exception as e:
                import traceback
                traceback.print_exc()
    
    # 拼接当前页面的所有内容
    lst.append("".join(page_content))

# 输出或保存结果
for content in lst:
    print(content)

代码说明

  1. 块排序:通过blocks.sort(key=lambda b: b["bbox"][1]),根据每个块的bbox(边界框)的第二个值(顶部y坐标)排序,确保内容顺序和页面视觉顺序一致。
  2. 文本块处理:逐个提取文本块中的行和跨度(span),同时保留粗体、斜体格式,拼接成段落标签。
  3. 图片块处理:直接从图片块中提取二进制数据保存,同时生成对应的img标签插入到内容的对应位置。

这样处理后,图片会严格按照页面上的位置插入到文本中,不会出现顺序错乱的问题。

内容的提问来源于stack exchange,提问作者Sourav Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 19:40:20