发布

  • feat: extract filled AcroForm field text in PDF partitioning (#4372)

    frostbyte_neo 发布于 2026-06-11 22:55:34 +00:00

    Summary

    Values typed into fillable PDF form fields live in widget
    annotations
    (/Annots), not the page content stream. pdfminer's
    layout pass only reads the content stream, so these values were dropped
    entirely from partition output.

    This recovers filled form-field values and emits them as elements
    alongside the content-stream text, for both the fast and hi_res
    strategies.

    Changes

    • pdfminer_processing.py
    • New get_widget_text_from_annots(annots, height) — resolves
      page.annots, keeps /Widget annotations, walks the /Parent chain
      for inherited FT/V, handles text (/Tx) and choice (/Ch) fields,
      and returns {text, bbox} per filled field. Empty//Off fields are
      skipped; /Btn checkboxes/radios are intentionally excluded.
    • _decode_field_value / _decode_scalar_field_value decode PDF string
      (UTF-16/PDFDocEncoded via pdfminer's decode_text) and name values,
      including multi-value choice fields.
    • hi_res: process_page_layout_from_pdfminer accepts a
      widget_list and appends each widget as an extracted text region
      (is_extracted=True, source=PDFMINER); process_data_with_pdfminer
      computes it next to the existing get_uris call. Values then ride the
      normal merge/dedup/coordinate machinery.
    • pdf.py (fast): _process_pdfminer_pages emits a Text element
      per widget after the content-stream loop.

    Tests

    test_pdfminer_processing.py builds a synthetic AcroForm PDF in-test
    (pypdf, empty content stream, generic fields name/date of birth/address + one empty field) and asserts:

    • the helper recovers filled values and skips empty ones,
    • the hi_res extracted layer includes them as IsExtracted.TRUE
      regions,
    • partition_pdf(strategy="fast") recovers them end-to-end.

    All 38 tests in the file pass; lint clean.

    Notes

    • Behavior change: every fillable PDF now yields previously-missing
      field text.
    • Pairs with the init_forms() render fix in unstructured-inference
      (so the flattened image and the extracted layer agree). The shared bbox
      means the existing IoU dedup collapses any OCR overlap.

    🤖 Generated with Claude Code


    Co-authored-by: Claude Opus 4.8 (1M context) noreply@anthropic.com

    下载附件