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

Databricks Spark中用pypdf读取多PDF遇KeyError: '/Root'求助

解决Databricks Spark中pypdf UDF多PDF读取的KeyError问题

可能原因及对应解决方案

1. 定位损坏的PDF文件

报错KeyError: '/Root'多数情况是某份PDF本身结构异常或损坏,单条测试时未覆盖到问题文件,多条数据时触发了错误。可以在UDF中添加异常捕获,标记错误记录来定位问题文件:

from pyspark.sql.functions import udf
from pyspark.sql.types import StringType
import pypdf

def extract_pdf_content(pdf_bytes):
    try:
        reader = pypdf.PdfReader(pdf_bytes)
        return "\n".join([page.extract_text() for page in reader.pages])
    except Exception as e:
        return f"ERROR: {str(e)}"

extract_pdf_udf = udf(extract_pdf_content, StringType())

# 筛选出报错的记录
error_records = df.withColumn("content", extract_pdf_udf(df.pdf_content)) \
                  .filter("content LIKE 'ERROR:%'")
display(error_records)

2. 避免UDF内重用pypdf实例

如果UDF外部初始化了全局的PdfReader实例,Spark并行处理时多任务共享同一实例会导致状态混乱,引发异常。必须在UDF内部每次调用都创建新的实例:

# 错误写法:全局实例会导致多任务冲突
# reader = pypdf.PdfReader()

# 正确写法:每次调用UDF都新建实例
def extract_pdf_content(pdf_bytes):
    reader = pypdf.PdfReader(pdf_bytes)
    return "\n".join([page.extract_text() for page in reader.pages])

3. 验证PDF字节流完整性

确保传入UDF的PDF字节流没有截断或编码错误,可尝试将字节流写入临时文件再读取(排查字节流问题):

import tempfile
import os

def extract_pdf_content(pdf_bytes):
    try:
        with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_file:
            tmp_file.write(pdf_bytes)
            tmp_path = tmp_file.name
        reader = pypdf.PdfReader(tmp_path)
        content = "\n".join([page.extract_text() for page in reader.pages])
        os.unlink(tmp_path)
        return content
    except Exception as e:
        return f"ERROR: {str(e)}"

4. 升级pypdf版本

旧版本pypdf对部分PDF结构兼容性差,可能在多文件处理时触发bug。在Databricks Notebook中执行以下命令升级:

%pip install --upgrade pypdf

UDF调试技巧

用mapPartitions替代UDF在小数据集上测试,打印每条记录的处理日志,方便定位问题:

def debug_pdf_processing(partition):
    for row in partition:
        pdf_bytes = row.pdf_content
        try:
            reader = pypdf.PdfReader(pdf_bytes)
            print(f"处理成功,元数据:{row.metadata}")
            yield (row.id, "\n".join([page.extract_text() for page in reader.pages]))
        except Exception as e:
            print(f"处理失败,记录ID:{row.id},错误:{str(e)}")
            yield (row.id, f"ERROR: {str(e)}")

# 取5条样本测试
sample_df = df.limit(5)
debug_result = sample_df.rdd.mapPartitions(debug_pdf_processing).toDF(["id", "content"])
display(debug_result)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 07:07:13