如何使用pdfminer.six提取指定PDF文本并保留原有布局?
如何用pdfminer.six提取PDF时保留原有布局?
嘿,我来帮你搞定这个问题!你现在用的TextConverter确实只会输出纯文本,完全丢掉了原PDF的布局结构——要实现保留布局的文本提取,得换个思路:直接解析PDF的布局元素,然后根据它们的位置信息来重新排版。
核心思路
PDF里的文本都是以带位置信息的元素(文本块、文本行、单个字符)存在的,我们可以用PDFPageAggregator来获取这些元素的坐标,然后按原页面的上下左右顺序排列文本,再用空格模拟缩进和分栏,还原大致布局。
完整代码示例
首先导入需要的模块:
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer.pdfpage import PDFPage from pdfminer.layout import LAParams, LTTextBox, LTTextLine from pdfminer.converter import PDFPageAggregator
然后定义提取函数:
def convert_pdf_to_layout_txt(path): # 初始化资源管理器和布局参数 rsrcmgr = PDFResourceManager() laparams = LAParams() # 可根据PDF调整这些参数优化识别效果 laparams.line_overlap = 0.5 laparams.word_margin = 0.1 # 创建布局聚合器,用于解析页面布局 device = PDFPageAggregator(rsrcmgr, laparams=laparams) interpreter = PDFPageInterpreter(rsrcmgr, device) full_text = [] with open(path, 'rb') as pdf_file: for page in PDFPage.get_pages(pdf_file, check_extractable=True): interpreter.process_page(page) # 获取当前页面的布局对象 layout = device.get_result() # 收集所有带位置的文本行 text_lines = [] for obj in layout: # 遍历文本块和文本行元素 if isinstance(obj, (LTTextBox, LTTextLine)): for line in obj: if isinstance(line, LTTextLine): # PDF的y轴是从下往上的,所以用-y来实现从上到下排序 y_position = -line.bbox[1] x_position = line.bbox[0] line_text = line.get_text().strip() if line_text: text_lines.append((y_position, x_position, line_text)) # 先按垂直位置(从上到下),再按水平位置(从左到右)排序 text_lines.sort(key=lambda item: (item[0], item[1])) # 生成带布局的页面文本 page_content = [] last_y = None for y, x, text in text_lines: # 遇到新的行就换行 if y != last_y: page_content.append('\n') last_y = y # 用空格模拟水平缩进(这里按x坐标每5单位加一个空格,可按需调整) page_content.append(' ' * int(x // 5) + text) full_text.append(''.join(page_content)) return '\n\n'.join(full_text)
代码说明
PDFPageAggregator:替代原来的TextConverter,它会解析出PDF页面的布局结构,包括每个文本元素的位置、大小等信息。- 坐标排序:利用PDF的坐标系统(y轴从下往上),通过
-y_position实现从上到下的排序,再按x_position实现从左到右的排列。 - 模拟布局:通过计算文本行的x坐标,添加对应数量的空格来还原原有的缩进和分栏效果。如果需要更精确的对齐,可以进一步获取单个字符的宽度信息(
LTChar对象的adv属性)来调整空格数。
另一种简便方法
如果不需要太精细的布局,也可以用pdfminer的高级API,设置layout_mode="layout":
from pdfminer.high_level import extract_text text = extract_text("Wochenkarte-KW-15-Neu.pdf", layout_mode="layout") print(text)
这个方法会直接输出带基本布局的文本,适合快速需求。
内容的提问来源于stack exchange,提问作者Joker
相关产品推荐
相关产品推荐

