使用PyMuPDF(fitz)提取多栏PDF文本时顺序异常的问题求助
解决PyMuPDF提取多栏PDF文本顺序混乱的问题
当处理多栏PDF时,sort=True的全局排序逻辑(按块坐标从上到下、从左到右)会导致文本顺序错乱——它会把所有文本块按全局位置排序,而非遵循"左栏从上到下读完再读右栏"的自然阅读顺序,这就是你遇到第一段文本跑到中间的原因。
解决方案:按栏分组排序文本块
核心思路是先识别页面的栏布局,将同一栏的文本块归为一组,再对每组内的块按垂直位置排序,最后按栏的左右顺序拼接文本。
以下是可直接运行的代码实现:
import fitz def extract_multi_column_text(page): # 获取页面所有文本块(过滤非文本块) blocks = page.get_text("dict", sort=True)["blocks"] text_blocks = [block for block in blocks if block["type"] == 0] if not text_blocks: return "" # 计算分组阈值:用首个文本块宽度的10%作为栏间距判断标准 first_block_width = text_blocks[0]["bbox"][2] - text_blocks[0]["bbox"][0] col_threshold = first_block_width * 0.1 # 按块的左边界x坐标排序,再聚类分组(区分不同栏) sorted_blocks = sorted(text_blocks, key=lambda b: b["bbox"][0]) columns = [] current_column = [sorted_blocks[0]] for block in sorted_blocks[1:]: prev_block_x = current_column[-1]["bbox"][0] # 若当前块与组内最后一块的左边界差小于阈值,归为同一栏 if block["bbox"][0] - prev_block_x < col_threshold: current_column.append(block) else: columns.append(current_column) current_column = [block] columns.append(current_column) # 按栏顺序拼接文本:每栏内按垂直位置(y坐标)从上到下排序 final_text = "" for col in columns: sorted_col = sorted(col, key=lambda b: b["bbox"][1]) for block in sorted_col: # 提取块内所有文本片段 for line in block["lines"]: for span in line["spans"]: final_text += span["text"] + " " final_text += "\n\n" return final_text # 使用示例 doc = fitz.open("你的多栏PDF文件.pdf") target_page = doc[0] # 取第一页示例 extracted_text = extract_multi_column_text(target_page) print(extracted_text)
代码说明
- 过滤文本块:只保留
type=0的文本块,排除图片、图形等非文本元素。 - 栏分组逻辑:通过文本块的左边界坐标聚类,把位置相近的块归为同一栏,适配大多数等宽多栏布局。
- 栏内排序:每栏内的文本块按顶部y坐标排序,保证从上到下的阅读顺序。
- 文本拼接:按栏的左右顺序依次拼接每栏的文本,还原自然阅读流。
如果遇到不等宽栏、嵌套栏等复杂布局,可以进一步优化分组逻辑(比如用page.get_text("words")获取单词级坐标,再按栏分组),但上述代码足以覆盖常规多栏PDF的提取需求。
内容的提问来源于stack exchange,提问作者user116936
相关产品推荐
相关产品推荐

