属性错误 - 使用Borb检测PDF中的表格

1 投票
1 回答
48 浏览
提问于 2025-04-14 18:21

我需要在PDF文件中检测表格,这样我才能在空白单元格中创建字段表单。

为了测试borb这个工具是否能实现这个目标,我尝试使用作者的示例作为参考。

我的代码是:

from decimal import Decimal
from borb.pdf import Document
from borb.pdf.page.page import Page
from borb.pdf.pdf import PDF
from borb.toolkit.table.table_detection_by_lines import TableDetectionByLines as TDBL
from borb.pdf.canvas.layout.annotation.square_annotation import SquareAnnotation
from borb.pdf.canvas.color.color import HexColor, X11Color

def main(infile, outfile):

    # get doc
    t = TDBL()
    doc = None
    with open(infile, "rb") as pdf_file_handle:
        doc = PDF.loads(pdf_file_handle, [t])
    assert doc is not None

    # get page
    p = doc.get_page(0)

    # get Tables
    for r in t.get_table_bounding_boxes():
        r = r.grow(Decimal(5))
        p.add_annotation(SquareAnnotation(r, stroke_color=X11Color("Green")))

    with open(outfile, "wb") as pdf_file_handle:
        PDF.dumps(pdf_file_handle, doc)

    return

if __name__ == "__main__":
    infile = "Parameter.pdf"
    outfile = "ParameterOut.pdf"
    main(infile, outfile)

我在这里使用了自己的PDF文件:"Parameter.pdf"


当我运行程序时,出现了这个错误:

# etc..
r = r.grow(Decimal(5))
AttributeError: 'int' object has no attribute 'grow'

我哪里出错了?

1 个回答

0

免责声明:我是 borb 的作者

0. 关于 borb

请查看 get_table_bounding_boxes 的签名:

    def get_table_bounding_boxes(self) -> typing.Dict[int, typing.List[Rectangle]]:
        """
        This function returns the bounding boxes (as Rectangle objects) of each Table
        that was recognized on the given page.
        """

简单来说,这个方法返回的是一个 dict,而不是一个 list[Rectangle]

这就是你代码出错的地方。你试图在一个不是 Rectangle 的东西上调用 grow

1. 关于你的PDF

免责声明2:我检查了你的文档。我可能错了。但这是我对发生情况的理解。

你的PDF有些奇怪。在最基本的层面上,PDF文档使用后处理指令在页面上绘制东西(线条、曲线、图像、文本)。这些后处理指令通常以压缩的形式存储在PDF中。

我解压了你的PDF。它包含以下指令:

q
72.504 706.06 77.4 13.464 re
W* n
 /Span <</MCID 0/Lang (en-US)>> BDC q
72.504 706.06 77.4 13.464 re
W* n
BT
/F1 11.04 Tf
1 0 0 1 77.664 709.06 Tm
/GS10 gs
0 g
/GS11 gs
0 G
[<0057>17<0102018C>24<01020175>6<011E>9<019A>9<011E018C>] TJ
ET
Q

现在来解释一下(你可以在PDF规范中查看,附录A - 操作符摘要。规范的副本可以在borb库中找到):

q: 保存图形状态
re: 将矩形添加到路径中
W*: 使用奇偶规则设置剪切路径
n: 结束路径,不填充或描边

所以,你的文档是在指示PDF查看器将一个矩形添加到路径中,但之后却没有发出实际填充或描边该路径的指令。

为了强调这一点,规范对 re 操作符的解释是:

将一个矩形作为完整的子路径添加到当前路径中,左下角坐标为 (x, y),宽度和高度在用户空间中。操作
x y width height re
等同于
x y m
( x + width ) y l
( x + width ) ( y + height ) l
x ( y + height ) l
h

l: 从当前点到 (x, y) 的直线段。新的当前点将是 (x, y)。

h: 通过从当前点到子路径起始点添加一条直线段来关闭当前子路径。如果当前子路径已经关闭,h 将不执行任何操作。这个操作结束当前子路径。向当前路径添加另一个段将开始一个新的子路径,即使新段的起点是通过 h 操作到达的端点。

而且PDF规范明确区分了构建路径(并关闭它)和实际描边或填充它。

表60 - 路径绘制操作符中,你可以找到证据:

S: 描边路径。
s: 关闭并描边路径。这个操作符的效果与序列 h S 相同。

撰写回答