You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用borb库RegularExpressionTextExtraction提取PDF文本时触发AssertionError(矩形宽度需非负)问题求助

borb库RegularExpressionTextExtraction提取PDF文本时触发AssertionError(矩形宽度需非负)问题求助

Hey Erik, sorry you're stuck with this annoying error while trying to pull the "Cited by" mentions from your PDF. Let's walk through what's going on and how we can fix it.

First, let's recap your setup: you adapted code from borb's regex text extraction examples, pointing it at your PDF file, but when running the script, it crashes with an AssertionError: A Rectangle must have a non-negative width. This happens because some glyphs in your PDF (likely those in the boxes you mentioned) have a bounding box with a negative width, which borb's internal code doesn't expect.

Here's your code for reference:

#!chapter_005/src/snippet_006.py
import typing

from borb.pdf import Document
from borb.pdf import PDF
from borb.toolkit import RegularExpressionTextExtraction


teonderzoekenpdf = "Jim.pdf"
zoekstring = 'Cited by'

def main():
    
    # read the Document
    # fmt: off
    print("Stap 2")
    doc: typing.Optional[Document] = None
    l: RegularExpressionTextExtraction = RegularExpressionTextExtraction(zoekstring)
    with open(teonderzoekenpdf, "rb") as in_file_handle:
        print("Stap 3")
        doc = PDF.loads(in_file_handle, [l])
        print("Stap 3,5")
    # fmt: on

    # check whether we have read a Document
    print("Stap 4")
    assert doc is not None
    print("Stap 5")
 
    # print matching groups
    for i, m in enumerate(l.get_matches()[0]):
        print("Stap 6")
        print("%d %s" % (i, m.group(0)))
        #for r in m.get_bounding_boxes():
            #print(
            #    "\t%f %f %f %f" % (r.get_x(), r.get_y(), r.get_width(), r.get_height())
            #)


if __name__ == "__main__":
    print("Stap 1")
    main()

And the error you're seeing:

PS C:\Users\Erik\Desktop\Strings_uit_pdf>  c:; cd 'c:\Users\Erik\Desktop\Strings_uit_pdf'; & 'c:\Python312\python.exe' 'c:\Users\Erik\.vscode\extensions\ms-python.debugpy-2024.14.0-win32-x64\bundled\libs\debugpy\adapter/../..\debugpy\launcher' '51988' '--' 'c:\Users\Erik\Desktop\Strings_uit_pdf\stringsuitpdf.py' 
Stap 1
Stap 2
Stap 3
Traceback (most recent call last):
  File "c:\Users\Erik\Desktop\Strings_uit_pdf\stringsuitpdf.py", line 56, in <module>
    main()
  File "c:\Users\Erik\Desktop\Strings_uit_pdf\stringsuitpdf.py", line 29, in main
    doc = PDF.loads(in_file_handle, [l])
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\pdf\pdf.py", line 85, in loads
    document: Document = ReadAnyObjectTransformer().transform(
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\any_object_transformer.py", line 113, in transform
    return super().transform(
           ^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\transformer.py", line 149, in transform
    out = h.transform(
          ^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\reference\xref_transformer.py", line 305, in transform
    trailer = self.get_root_transformer().transform(
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\any_object_transformer.py", line 113, in transform
    return super().transform(
           ^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\transformer.py", line 149, in transform
    out = h.transform(
          ^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\object\dictionary_transformer.py", line 69, in transform
    v = self.get_root_transformer().transform(
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\any_object_transformer.py", line 113, in transform
    return super().transform(
           ^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\transformer.py", line 149, in transform
    out = h.transform(
          ^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\reference\reference_transformer.py", line 169, in transform
    transformed_referenced_object = self.get_root_transformer().transform(
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\any_object_transformer.py", line 113, in transform
    return super().transform(
           ^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\transformer.py", line 149, in transform
    out = h.transform(
          ^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\page\root_dictionary_transformer.py", line 112, in transform
    transformed_root_dictionary = t.transform(
                                  ^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\object\dictionary_transformer.py", line 69, in transform
    v = self.get_root_transformer().transform(
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\any_object_transformer.py", line 113, in transform
    return super().transform(
           ^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\transformer.py", line 149, in transform
    out = h.transform(
          ^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\reference\reference_transformer.py", line 169, in transform
    transformed_referenced_object = self.get_root_transformer().transform(
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\any_object_transformer.py", line 113, in transform
    return super().transform(
           ^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\transformer.py", line 149, in transform
    out = h.transform(
          ^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\object\dictionary_transformer.py", line 69, in transform
    v = self.get_root_transformer().transform(
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\any_object_transformer.py", line 113, in transform
    return super().transform(
           ^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\transformer.py", line 149, in transform
    out = h.transform(
          ^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\object\array_transformer.py", line 69, in transform
    object_to_transform[i] = self.get_root_transformer().transform(
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\any_object_transformer.py", line 113, in transform
    return super().transform(
           ^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\transformer.py", line 149, in transform
    out = h.transform(
          ^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\reference\reference_transformer.py", line 169, in transform
    transformed_referenced_object = self.get_root_transformer().transform(
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\any_object_transformer.py", line 113, in transform
    return super().transform(
           ^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\transformer.py", line 149, in transform
    out = h.transform(
          ^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\io\read\page\page_dictionary_transformer.py", line 129, in transform
    CanvasStreamProcessor(page_out, canvas, []).read(
  File "c:\Python312\Lib\site-packages\borb\pdf\canvas\canvas_stream_processor.py", line 277, in read
    raise e
  File "c:\Python312\Lib\site-packages\borb\pdf\canvas\canvas_stream_processor.py", line 271, in read
    operator.invoke(self, operands, event_listeners)
  File "c:\Python312\Lib\site-packages\borb\pdf\canvas\operator\text\show_text_with_glyph_positioning.py", line 84, in invoke
    l._event_occurred(tri)
  File "c:\Python312\Lib\site-packages\borb\toolkit\text\regular_expression_text_extraction.py", line 326, in _event_occurred
    self._render_text(event)
  File "c:\Python312\Lib\site-packages\borb\toolkit\text\regular_expression_text_extraction.py", line 338, in _render_text
    for e in text_render_info.split_on_glyphs():
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\pdf\canvas\event\chunk_of_text_render_event.py", line 177, in split_on_glyphs
    e._baseline_bounding_box = Rectangle(
                               ^^^^^^^^^^
  File "c:\Python312\Lib\site-packages\borb\pdf\canvas\geometry\rectangle.py", line 30, in __init__
    assert width >= 0, "A Rectangle must have a non-negative width."
           ^^^^^^^^^^
AssertionError: A Rectangle must have a non-negative width.

How to Fix This:

Let's try these solutions in order:

  1. Update borb to the latest version
    This is the easiest first step. The borb team might have already fixed this edge case in a newer release. Run this command in your terminal:

    pip install --upgrade borb
    

    Then re-run your script to see if the error goes away.

  2. Monkey-patch the Rectangle class to handle negative widths
    If updating doesn't work, we can modify how borb's Rectangle class handles width values to avoid the assertion. Add this code at the very top of your script (before importing any borb modules):

    from borb.pdf.canvas.geometry.rectangle import Rectangle
    
    # Save the original initialization method
    original_rect_init = Rectangle.__init__
    
    def patched_rect_init(self, x: float, y: float, width: float, height: float):
        # Convert negative width/height to positive to bypass the assertion
        width = abs(width)
        height = abs(height)
        original_rect_init(self, x, y, width, height)
    
    # Replace the original __init__ with our patched version
    Rectangle.__init__ = patched_rect_init
    

    This will make sure any negative width values are turned positive, so the assertion doesn't trigger.

  3. Get page numbers for your matches
    Once the error is fixed, you can modify your loop to include the page number for each match. The get_matches() method returns a list where each index corresponds to a page (starting from 0), so adding 1 gives you the actual page number:

    # Print matching groups with page numbers
    for page_index, page_matches in enumerate(l.get_matches()):
        print(f"--- Page {page_index + 1} ---")
        for match_index, match in enumerate(page_matches):
            print(f"{match_index + 1}: {match.group(0)}")
    

If All Else Fails:

If none of these fixes work, your PDF might have some non-standard elements that borb struggles with. You could try alternative PDF text extraction libraries like pdfplumber or PyPDF2, but since you're set on using borb, the above patches should get you past the error.

Hope this helps you get those "Cited by" mentions extracted successfully!

备注:内容来源于stack exchange,提问作者ErikDB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 16:39:40