关于Python使用pdfminer库对PDF文件三线表中直线的识别,并返回相应的Y轴坐标

  • 依赖库
  • 测试文件
  • 实现目标
  • 识别原理介绍
  • 1. 全部解析
  • 2. 直线对象获取
  • 3. 直线过滤
  • 测试直线
  • 具体代码
  • LTRect对象介绍
  • 可能存在的问题
  • 最终效果


参考文章:
pdfminer官方文档 pdfminer源码

依赖库

pdfminer

测试文件

pdf文件一整页(含有5张三线表, 15条直线)

实现目标

获取所有直线对象,并获得其相应的Y轴坐标(5张表,共15条直线)

识别原理介绍

1. 全部解析

利用pdfminer库能获取单页PDF页面中的所有对象:包括

  • LTPage代表一个完整的页面。
  • LTTextBox它包含 LTTextLine 对象的列表。
  • LTTextLine包含一个LTChar对象的列表,表现为单行文本字符表现为一行或一列。
  • LTChar / LTAnno LTChar对象有真实的分隔符。
  • LTAnno 对象是虚拟分隔符,按照两个字符之间的关系,布局分析器插入虚拟分隔符。
  • LTFigure代表一个被PDF Form对象使用的区域。
  • LTImage代表一个图形对象。
  • LTLine代表一根直线。
  • LTRect代表一个矩形。
  • LTCurve代表一个贝塞尔曲线。
2. 直线对象获取

失败方案:先前在测试时首先想到 对获取到每个内存中的对象筛选出LTLine即可获得内存对象。
失败原因:某些直线并不会被识别成LTLine,就算获得的坐标也并不符合PDF原输入文件的相应位置。

可行方案:对识别出的所有对象,筛选出 LTRect矩形对象
原因分析:直线可以被pdfminer识别成LTRect矩形对象,可以将直线看做高度非常小的一种特殊矩形(实际测试数据三线表直线对象高度大约为0.6~0.8左右,可以认为<2)。

3. 直线过滤

利用 直线可以被看做高度小于2的矩形 的特点 设置过滤条件

测试直线

针对测试用的PDF文件,其中三线表的直线的高度大约为0.6~0.8。 不同高度的直线 可以适度调节 过滤时 LTRect对象的 height 的取值。

Java pdf取xy坐标 python解析pdf获取坐标_测试数据

具体代码

(1) pdfminer相关初始化操作

fp = open(path, 'rb')

# 创建pdf文档对象,并获取所有页面pages
parser = PDFParser(fp)
document = PDFDocument(parser)
pages = PDFPage.create_pages(document)

# 断言文档对象可提取
assert document.is_extractable

# 设置参数并获得pdf解释器
rsrcmgr = PDFResourceManager()
laparams = LAParams()
device = PDFPageAggregator(rsrcmgr, laparams=laparams)
interpreter = PDFPageInterpreter(rsrcmgr, device)

(2) 获取 *** 单页 *** 所有pdfminer扫描得到的内存对象的集合:layout布局对象

for eachPage in pages:
    interpreter.process_page(eachPage)
    layout = device.get_result()

(3) 对 *** 单页 *** 获得的 layout布局对象 中筛选 LTRect对象 并过滤 LTRect对象 , 同时记录Y轴坐标

coordinateY = []
    for each in layout:
        # 利用LTRect对象来检测直线
        if type(each) == LTRect:
            # 将高度 > 2的矩形过滤,(测试数据可推测直线会被扫描成高度接近1的矩形)
            if each.height > 2:
                continue
            # 解决同一直线被分段扫描检测为多段直线的问题(同一个Y坐标,但是宽度不一致,其总和为原始直线)
            if each.bbox[1]not in coordinateY:
                coordinateY.append(each.bbox[1])
LTRect对象介绍

其某层父类为:LTComponent
其拥有一个bbox绑定盒子对象,其记录了该LTComponent对象的左下角和右上角坐标 (x0, y0, x1, y1)

源码中的体现:

Java pdf取xy坐标 python解析pdf获取坐标_python_02

可能存在的问题

在获取所有LTRect对象时,可能会出现如下情况:
原本pdf中三线表的一条直线,可能被分为三段子直线,其Y轴坐标一致,但是每条直线的width(即每条直线的宽度或称之为长度)不一致,但是 三段子直线的总长度和 = 原直线长度
即(x轴方向的总长度): Line = subLine[0] + subLine[1] + subLine[2]

最终效果

获取的该页5张表 共15条直线 不同的Y轴坐标:

Java pdf取xy坐标 python解析pdf获取坐标_python_03