PAYATHON 2026

如何自动或批量修复 PDF,以满足 WCAG 2.0 无障碍要求?

技术老齐

可以用编程和现成工具批量修复部分 PDF 无障碍问题。但对于来源复杂的 100,000+ 份文件,仅凭自动处理完成或检测通过,还不能认定全部符合 WCAG 2.0。建议先将文件分类,自动处理规则明确的问题,再由人工检查内容语义和实际操作。

Author 可以批量补充,但 WCAG 2.0 并未要求所有 PDF 都填写作者。作者字段通常也不是最影响使用的问题,应优先处理文档标题、语言、可读取的文本、标签结构和阅读顺序。

先明确验收要求和自动化边界

“符合 WCAG 2.0”需要明确到具体等级,例如 Level AA。以 AA 为目标,就要满足所有适用的 A 级和 AA 级成功准则。验收时应逐项核对具体要求,不能只看检测工具是否全部显示绿色。参见 WCAG 2.0 的符合性要求。

PDF/UA 可以作为 PDF 结构方面的技术目标,但它与 WCAG 的检查范围不同,两者不能直接互换。PDF/UA 主要规定 PDF 如何支持辅助技术;验收时还需要检查内容是否清楚、替代文本是否准确等问题。参见 PDF/UA Foundation 的 PAC 指南。

问题可以自动处理的部分仍需判断的内容
缺少标题从可信业务数据写入标题标题是否描述文档主题或用途
缺少默认语言按已确认的语言设置 /Lang多语言段落是否需要单独标记
扫描件没有文本使用 OCR 添加文本层识别结果是否准确
缺少结构标签自动识别并生成初步标签标题层级、表格结构、阅读顺序是否正确
图片缺少替代文本检测缺失情况,生成待审核草稿描述是否传达图片在当前语境中的信息
表单无障碍问题检测部分字段属性字段名称、键盘操作和错误提示是否可用

给 PDF 设置 /MarkInfo /Marked true,或创建一个空的 /StructTreeRoot,都不会自动生成正确的标签结构。OCR 也只解决文本识别问题,不会完成标题、列表、表格等语义标记。

大规模修复应如何安排

1. 建立清单,按来源和模板分类

清单至少要记录文件位置、哈希、页数、来源系统、是否有源文件,以及文本层、标签、表单、加密和数字签名等情况。

先区分以下几类:

  • 有 Word、InDesign 等可编辑源文件的文档;
  • 由同一业务系统、同一模板生成的文档;
  • 来源不统一、版式复杂的历史文件;
  • 扫描件。

有源文件时,通常应先修复源文件或生成模板,再重新导出带标签的 PDF。对于同一模板生成的数万份文件,值得开发专门的处理规则;零散的历史文件往往需要更多人工修复。

2. 按用户需求确定处理顺序

优先处理仍在使用的重要文档,例如申请表、操作说明,以及访问量高或用户已提出无障碍需求的文件。旧文件是否删除、替换或归档,由内容负责人根据组织要求决定。

资源有限时可以分批交付,但列入排期的文件仍需修复才能满足要求。对尚未修复、又有使用需求的文件,应提供可访问版本或其他获取方式。

3. 用代表性样本试跑

选择能覆盖不同语言、模板、扫描质量、表格和表单的样本,比较候选工具处理前后的结果。

评估时记录每份文件的处理费用、人工复核时间、失败原因和返工情况。生成的标签数量不足以衡量工具节省了多少修复时间。

哪些工具值得评估

工具适合的用途使用边界
Adobe Acrobat Pro自动打标、检查,以及逐份修复阅读顺序和结构报告中仍有需要人工检查的项目
Adobe PDF Accessibility Auto-Tag API将自动打标接入批处理工作流自动打标只是修复过程的一部分,输出需要复核
axesFlip通过模板处理重复版式,提供 CLI 和 REST Server是否适合现有文档,需要用实际样本验证
pikepdf按明确规则批量修改元数据、PDF 字典等内容不负责自动理解文档语义
OCRmyPDF为扫描件添加可搜索文本层OCR 后仍需修复结构、检查识别结果
PAC、veraPDF检查和验证,辅助人工复核或接入自动流程检测工具不会完成内容修复;veraPDF 的 PDF/UA 验证限于机器可检查的要求

采购或接入前,还要确认授权方式、文件及页数限制、并发配额、中文识别效果,以及文档是否允许上传到云服务。批量处理能力和最终修复质量都需要单独验证。

代码示例:按审核清单更新标题、作者和语言

可以先从文档管理系统取得可靠数据,批量写入 PDF。标题应使用经过确认的信息,不要一律填成文件名;作者未知时,也不要统一填组织名称。

W3C 的 PDF18 技术说明了文档标题及 DisplayDocTitle 的设置;PDF16 技术说明了默认语言 /Lang 的设置。

以下是使用 pikepdf 的最小批处理示例。运行前,清单应已审核,输入文件应未加密、未签名,并且允许重新保存。代码会按清单更新已有值,将结果写入独立目录。

安装依赖:

python -m pip install pikepdf

准备 manifest.json。author 为可选字段,未知时省略:

[
  {
    "path": "guides/application-guide.pdf",
    "title": "申请办理指南",
    "language": "zh-CN",
    "author": "业务服务部门"
  }
]

将清单中的 PDF 放在 pdf-in/ 下,然后运行:

import json
from pathlib import Path

import pikepdf

source_root = Path("pdf-in").resolve()
output_root = Path("pdf-out").resolve()

items = json.loads(
    Path("manifest.json").read_text(encoding="utf-8")
)

for item in items:
    try:
        source = (source_root / item["path"]).resolve()
        relative = source.relative_to(source_root)
        target = output_root / relative

        if target.exists():
            raise FileExistsError(target)

        with pikepdf.Pdf.open(source) as pdf:
            if pdf.is_encrypted:
                raise ValueError("Encrypted PDF requires separate handling")

            with pdf.open_metadata() as metadata:
                metadata["dc:title"] = item["title"]
                if item.get("author"):
                    metadata["dc:creator"] = [item["author"]]

            pdf.Root["/Lang"] = item["language"]

            preferences = pdf.Root.get("/ViewerPreferences")
            if preferences is None:
                preferences = pikepdf.Dictionary()
                pdf.Root["/ViewerPreferences"] = preferences

            preferences["/DisplayDocTitle"] = True

            target.parent.mkdir(parents=True, exist_ok=True)
            pdf.save(target)

        result = {"path": item["path"], "status": "metadata_updated"}
    except Exception as exc:
        result = {
            "path": item.get("path"),
            "status": "failed",
            "error": str(exc),
        }

    print(json.dumps(result, ensure_ascii=False))

open_metadata() 会协调更新 XMP 和旧式 Document Info 中对应的常用字段,具体行为见 pikepdf 元数据文档。

这段代码只更新元数据,不生成标签,也不修复阅读顺序。默认语言描述的是文档的主要语言,其他语言的段落可能仍需单独标记。

批处理后如何验收

每个批次都应重新运行自动检查,并由人工复核工具无法可靠判断的问题,包括:

  • 标题、段落、列表和表格是否按合理顺序读取;
  • 表头是否与对应数据正确关联;
  • 图片替代文本是否准确,装饰内容是否恰当处理;
  • 链接和表单能否通过键盘操作;
  • OCR 是否误识别了数字、符号或关键文字;
  • 对比度及依赖颜色传递的信息是否符合目标要求。

还要使用选定的 PDF 阅读器和屏幕阅读器组合实际操作。Acrobat 将检查结果分为自动通过、失败和 Needs Manual Check,其中 Needs Manual Check 必须人工验证。参见 Adobe 的检查说明。

对于稳定模板,可以安排分层抽样和回归检查,但抽样通过不能证明每份文件都合规。独有版式、复杂表格、交互表单和异常输出都需要明确安排复核。

批量修改时的注意事项

保留原文件、输入哈希、工具版本、修改记录和检查报告,方便重试失败任务、追溯处理结果。数字签名文件应单独处理,重新保存可能使签名失效;加密文件也需要先确认处理权限和输出策略。

不要对所有文件强制重新 OCR 或重新打标,这可能破坏已有结构。OCRmyPDF 的相关文档也说明了部分处理方式对标签结构的影响。

如果采用敏捷方式推进,可以将“已完成”的条件定为:指定问题已修复,自动检查已重新运行,所需的人工复核已完成,并已保存验收记录。同时修正文档生成流程,避免历史文件尚未处理完,新的无障碍问题又不断进入库中。

备注:内容仅供参考。