使用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)
代码说明
- 块排序:通过
blocks.sort(key=lambda b: b["bbox"][1]),根据每个块的bbox(边界框)的第二个值(顶部y坐标)排序,确保内容顺序和页面视觉顺序一致。 - 文本块处理:逐个提取文本块中的行和跨度(span),同时保留粗体、斜体格式,拼接成段落标签。
- 图片块处理:直接从图片块中提取二进制数据保存,同时生成对应的img标签插入到内容的对应位置。
这样处理后,图片会严格按照页面上的位置插入到文本中,不会出现顺序错乱的问题。
内容的提问来源于stack exchange,提问作者Sourav Singh
相关产品推荐
相关产品推荐

