2026/10/23 4:49:19

Python 项目踩坑记录:PDF、Word 上传解析时 page 类型不一致导致的数据转换问题

Python 项目踩坑记录:PDF、Word 上传解析时 page 类型不一致导致的数据转换问题 文件上传解析踩坑为什么 PDF 成功Word/TXT 却失败最近在开发一个文档上传解析系统时遇到了一个比较隐蔽的问题PDF 文件上传成功但是 Word 和 TXT 文件上传失败。一开始以为是Word 解析库的问题TXT 编码问题文档内容格式异常但是经过排查发现真正的问题竟然是数据库字段类型和解析结果类型不一致。一、问题现象系统支持上传PDFWordTXT测试发现文件类型上传结果PDF成功Word失败TXT失败日志中出现类似错误DataError: invalid input syntax for integer或者数据库字段类型错误二、问题定位过程首先查看数据库模型class DocumentChunk(TimestampMixin, Base): __tablename__ document_chunks ... page: Mapped[int | None] mapped_column(Integer)可以看到page: int数据库字段page INTEGER也就是说数据库只接受1 2 3 4这种整数。但是继续查看文件解析代码def extract_pages(path: Path) - List[Tuple[Optional[int], str]]:返回的数据结构[ (page, content) ]其中page应该是int继续往下排查for doc in docs: doc_list.append( ( doc.metadata[page_label], doc.page_content ) )发现问题这里使用的是doc.metadata[page_label]三、为什么 PDF 正常原因在于不同解析器生成 metadata 的方式不同。PDF 解析例如{ page: 0, page_label: 1 }可能内部已经进行了转换。Word/TXT解析可能返回{ page_label: 1 }注意这里的数据类型是str而不是int例如1和1是不一样的。四、问题本质代码doc.metadata[page_label]返回1但是数据库page INTEGER需要1所以字符串 ↓ 数据库 Integer ↓ 类型错误五、解决方案进行类型转换最简单的方法使用int()转换。修改代码原代码doc_list.append( ( doc.metadata[page_label], doc.page_content ) )修改doc_list.append( ( int(doc.metadata[page_label]), doc.page_content ) )转换过程1经过int(1)得到1最终数据库page INTEGER正常保存。六、优化写法增加安全处理但是直接int()也存在风险。例如int(abc)会报错ValueError所以生产环境建议page doc.metadata.get(page_label) if page: page int(page) else: page None完整代码def extract_pages(path: Path): docs loader.load() doc_list [] for doc in docs: page doc.metadata.get( page_label ) if page: page int(page) doc_list.append( ( page, doc.page_content ) ) return doc_list七、为什么数据库设计容易出现这种问题因为文件解析属于外部数据输入。外部数据通常不可控。例如PDF:{ page:1 }Word:{ page:1 }TXT:{ page_label:1 }虽然业务含义一样都是页码。但是类型不同数据类型1int1str进入数据库前必须统一。八、实际开发中的经验总结在文件解析项目中1. 不要相信第三方解析结果例如metadata[page]一定要检查type(metadata[page])建议print( type(doc.metadata[page_label]) )2. 数据入库前统一类型推荐流程文件 | 解析器 | metadata | 数据清洗 | 类型转换 | 数据库不要文件 | 解析器 | 直接入库3. 数据库字段设计要明确例如page: Mapped[int]表示这个字段永远保存整数那么代码层必须保证int九、最终代码版本def extract_pages(path: Path): docs loader.load() doc_list [] for doc in docs: page_label doc.metadata.get( page_label ) page ( int(page_label) if page_label else None ) doc_list.append( ( page, doc.page_content ) ) return doc_list十、总结这次问题表面看是Word/TXT 文件上传失败实际上文件解析后的 metadata 类型不一致导致数据库保存失败。核心知识点第三方解析库返回的数据类型不一定一致数据库存储前需要进行类型校验str和int虽然内容相同但是类型不同使用int()可以完成字符串数字转换记住一句开发经验所有进入数据库的数据都应该经过一次数据清洗和类型确认。这类问题在 RAG、知识库、文档解析系统中非常常见提前做好类型规范可以减少大量隐蔽 Bug。