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

如何用Python提取IRS XFA/AcroForm表单的字段标签及详情?

提取IRS PDF表单的字段标签与字段名映射

问题背景

正在处理美国国税局(IRS)发布的XFA或AcroForm类型PDF表单,需要建立用户可见字段标签(如“First Name”)与后台字段名(如“f1_01”)的映射关系。已尝试PyPDF2和Aspose-PDF,但仅能提取字段名,无法获取对应标签。因许可证限制,无法使用iText。

可行解决方案

1. 处理XFA类型表单

XFA表单的结构存储在XML中,可通过解析导出的XFA XML来关联标签与字段名:

  • 先导出XFA的XML数据,再用XML解析库定位字段标签与对应字段名

示例代码:

import PyPDF2 as pypdf
from lxml import etree

def find_xfa_xml(pdf_path):
    pdf = pypdf.PdfReader(pdf_path)
    # 递归查找XFA数据
    def find_in_dict(needle, haystack):
        for key in haystack.keys():
            try:
                value = haystack[key]
            except:
                continue
            if key == needle:
                return value
            if isinstance(value, dict):
                result = find_in_dict(needle, value)
                if result is not None:
                    return result
    xfa = find_in_dict('/XFA', pdf.resolved_objects)
    if xfa:
        xml_data = xfa[7].get_object().get_data().decode('utf-8')
        return xml_data
    return None

def parse_xfa_labels(xml_data):
    root = etree.fromstring(xml_data.encode('utf-8'))
    field_mapping = {}
    # 遍历所有field元素,关联name属性与caption文本
    for field in root.xpath('//field'):
        field_name = field.get('name')
        caption = field.xpath('.//caption/text()')
        if field_name and caption:
            field_mapping[field_name] = caption[0].strip()
    return field_mapping

# 使用示例
xml_content = find_xfa_xml("f1065sk3.pdf")
if xml_content:
    mapping = parse_xfa_labels(xml_content)
    for field_name, label in mapping.items():
        print(f"字段名: {field_name} -> 标签: {label}")

2. 处理AcroForm类型表单

使用PyMuPDF(fitz),可直接读取字段的标签属性,或通过字段位置匹配邻近文本:

示例代码:

import fitz

def extract_acroform_mapping(pdf_path):
    doc = fitz.open(pdf_path)
    field_mapping = {}
    for page in doc:
        fields = page.widgets()
        for field in fields:
            field_name = field.field_name
            # 优先读取字段自带的标签/提示文本
            label = field.field_label or field.tooltip
            if not label:
                # 若无自带标签,提取字段上方邻近区域的文本
                rect = field.rect
                search_rect = fitz.Rect(rect.x0, rect.y1 - 100, rect.x1, rect.y1)
                text = page.get_textbox(search_rect).strip()
                label = text if text else "无标签"
            field_mapping[field_name] = label
    return field_mapping

# 使用示例
mapping = extract_acroform_mapping("your_acroform.pdf")
for field_name, label in mapping.items():
    print(f"字段名: {field_name} -> 标签: {label}")

3. 备选工具:pdfplumber

通过匹配字段坐标与页面文本位置,提取邻近文本作为标签:

import pdfplumber

def extract_with_pdfplumber(pdf_path):
    field_mapping = {}
    with pdfplumber.open(pdf_path) as pdf:
        for page in pdf.pages:
            fields = page.extract_form_fields()
            text_elements = page.extract_words()
            for field_name, field_info in fields.items():
                field_rect = field_info['bbox']
                candidate_labels = []
                # 筛选字段左侧、距离较近的文本
                for text in text_elements:
                    text_rect = (text['x0'], text['top'], text['x1'], text['bottom'])
                    if text_rect[2] < field_rect[0] and abs(text_rect[3] - field_rect[1]) < 20:
                        candidate_labels.append(text['text'])
                label = " ".join(candidate_labels) if candidate_labels else field_name
                field_mapping[field_name] = label
    return field_mapping

内容的提问来源于stack exchange,提问作者Gopa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 19:23:23