文档结构化场景(非常规文件)

Posted by mjTree on September 25, 2024

更新于:2024-09-27 09:50

一、引言

由于工作涉及文档结构化的模块,我经常遇到一些不常见的文件和奇怪的协议码文件,这导致原有系统无法提供正确的输出。涉及的格式很多,有 Excel、Word、PDF 和图像等。接下来,我将介绍一些在工作中遇到的非常规文件及其处理方案。

二、非常规文件举例

IMAGE 格式

在图片类型中,很少遇到一些非常规或不常见的文件。在文档结构化中,主要问题是 尺寸异常多帧格式 两种类型问题。

1. 尺寸异常
对于图片文件,需要进行OCR步骤以识别其中的文字信息。然而,所用视觉模型对图片尺寸有特定要求,因此通常需要进行缩放操作。对于尺寸比例异常的图片,处理方式有限:要么拒绝识别,要么在拆剪后再进行识别。异常比例的图片主要是长度过长的类型,虽然可以进行拆剪处理,但这种方案可能会破坏原始文件的结构信息。

2. 多帧图片
多帧图片在我们的生活中非常常见,手机上通常会有许多动图和表情包。除了常见的GIF格式,其他类型的多帧图片格式在企业办公文档领域较少见。

在文档结构化中,通常会把一份图片文件认为是一页的文件,但在实际场景中会有一些企业的文件打破这个规定。TIF/TIFF,对于这类拓展名的格式不做过多介绍,下面提供两段代码分别用于判断TIF/TIFF格式图片是否为多帧,以及把多帧的图片转换成 pdf 文件。

import os
from PIL import Image


def is_multi_image(img_path: str) -> bool:
    is_multi = False
    if img_path.lower().endswith(('.tif', '.tiff')):
        try:
            with Image.open(img_path) as img:
                is_multi = getattr(img, 'n_frames', 1) > 1
        except Exception as e:
            print(f'check {img_path} is multi image error, {e}')
    return is_multi


def multi_img_convert_pdf(img_path: str, pdf_file_path: str = '') -> str:
    pillow_img_list = []
    pdf_file_path = pdf_file_path or img_path.rsplit('.', 1)[0] + '.pdf'
    try:
        os.makedirs(os.path.dirname(pdf_file_path), exist_ok=True)
        img = Image.open(img_path)
        for i in range(img.n_frames):
            img.seek(i)
            pillow_img_list.append(img.convert('RGB'))
        pillow_img_list[0].save(pdf_file_path, "PDF", save_all=True, append_images=pillow_img_list[1:])
    except Exception as e:
        print(f'multi page img convert to pdf error, {e}')
    return pdf_file_path

WORD 格式

在前面的文章中我们介绍过,word 文件在文档结构化中可以通过读取协议码信息来解析,也可以使用 工具 转换成 pdf 格式再进行处理。这也对应着 文件协议码异常 以及 格式转换 问题。

1. 协议码异常
文件打开内容错乱,基本等同于乱码的层面;工具提示文件破损无法打开,但在其他操作系统上对应工具能正常正常。

1-1. 内容错乱
遇到一个.wps格式的文件,windows-wps可以正常打开,但是在其他系统(MacOS/Linux)上打开则出现了乱码的现象,由于.wps是二进制文件,金山公司专属格式,暂时无法找到解决方案。初步推测是不同系统不同版本的 wps 工具可能有不兼容问题,导致读取信息错位,展示成乱码现象。

1-2. 文件破损
不同系统的 wps 工具在打开一个docx文件,都提示“在试图打开文件时遇到错误。请尝试下列方法:***”,Documents.Open 方法中有OpenConflictDocumentOpenAndRepair参数,也无法处理。不过Microsoft-Wordcalibre 工具都能够正常打开。

2. 转换问题
关于 word 格式转换的问题比较多,涉及系统缺少字体、工具渲染引擎等问题(外国语种、内嵌字体)。

2-1. 缺少字体
字体缺失会导致 word 排版出现错位,一般现象是字符间隔变化、字符样式变化等。当排版错位问题过多时,会导致转换出来的 pdf 页数与客户自己在工具上所看到的 word 文件页数不一致,这是比较致命的问题。

我们可以通过协议码或其他方式确定缺失的字体信息,安装相应字体后即可解决,关于字体可能存在的商业授权或不可商用这类风险。

2-2. 外国语言
存在一些外国语言的 word 文件,将其转换成 pdf 后,对应读取出的字符信息和原文件不一致。起初想尝试 Document.SaveAs2Encoding参数的msoEncodingThai值强制成泰语,也无法解决,也验证过并非字体缺失问题。

最后定位是linux-wps工具的渲染引擎问题,尝试把linux-wps更换成国际版本则正常,或使用calibre工具也能解决(注:Microsoft-Word正常,windows-wps正常,mac-wps正常)。

2-3. 内嵌字体
一些 word 文件内部不多但占有的存储很大,原因是文件包中含有字体文件。因为字体的特殊性,导致转换后相关的字符变成了矢量图片。正常情况系统中没有对应的字体,工具会使用默认相近的字体代替(会出现上面缺少字体的现象)。截止目前(2024-09-25)不同系统的 wps 都无法处理这个问题,测试Microsoft-Wordcalibre都能使用默认字体代替。

样例文件 ,仔细研究了这个文件,内部包含了一个 odttf 格式字体,在 Document.ExportAsFixedFormat 方法中有个BitmapMissingFonts参数,但未能解决,初步推断是 wps 渲染引擎这边没实现好导致的这个问题吧(给金山提过暂无反馈)。

EXCEL 格式

在文档结构化中,使用openpyxl是解析 excel 文件是个很不错的方案,但是该库只接受标准ooxml协议格式的 xlsx 文件。因此需要把不满足条件的文件转换成标准的格式才可以使用,而这类文件常常出现 协议码内容和文件格式拓展名不对应

1. 真实格式与拓展名不一致
早期团队里有人尝试读取文件头部信息来判断真实格式,方案很拉垮被摒弃了。即使头部信息表明和标准的 xlsx 格式一致,也会出现openpyxl解析报错问题,excel 就是这么神奇,与其这么说倒不如说是工具(Microsoft-Office/金山wps)兼容性做的太好了导致的。

可参考 样例文件 ,xls 理论上是一个二进制格式文件,但该文件内容为 html,将其后缀名更换成.html便可以在浏览器中打开。这类文件的来源的话,很早曾听过运维同事说可以用 IE 浏览器把网页上面的表格导出成 excel 格式,当然熟悉这方面的也可以直接把 html 上的<table>标签内容保存修改成 excel 格式也可以。

PDF 格式

pdf 是我在文档结构化工作中遇到最多的格式,这类文件的问题主要归纳成 文件协议码错乱文件字符信息异常 问题。

1. 协议码错乱
pdf 的来源有很多,由一些常规的工具导出或者转换得来的文件,协议码基本很规范,具体可参考之前介绍的 pdf协议码 文章。但现实中会遇到大量的协议码不规范的 pdf 文件,不太不影响 pdf 工具(pdfminer.six/pymupdf)正常打开和读取字符信息。不过还是有些文件的协议码错乱丢失(pdf 包含大量对象,经常编辑修改删除页等导致 xref 表指向失效),影响读取对象信息的速度。

这里推荐使用上面文章提到的pdftk工具来重构 pdf 协议码(不影响展示内容),测试一个文件(不便提供)在处理前读取全部页码的字符信息用时 60s,重构协议码后读取不到 3s,而且重构步骤耗时不到 2s。由于pdftk工具没有 arm 系统版本,这里推荐使用 pdftk-java 来代替。

java -Xms1g -Xmx1g -jar /path/pdftk-all.jar /path/badcase.pdf output /path/new.pdf

2. 字符信息异常
该问题现象是 pdf 展示的字符和工具读取出来的字符内部不一致,和上面的 word 文件问题中提到的“外国语言”现象一样,这里提供 样例文件

有全部字符都不对应,有局部字符不对应。这类文件来源,除了刚才提到的暂时没遇到其他能触发的。遇到这类问题,我暂无能力去修复这类文件,目前只能通过OCR来识别字符规避。在网络中查找了很久才发现一个 案例 ,距今已有七年了,供大家参考。

三、小结

本篇文章主要介绍了个人在文档结构化的工作中遇到的一些非常规文件,涉及了图片、word、excel、pdf 等类型格式文件,列举了一些详细的样例以及解决方案。虽然这些可能是文档处理工作困难的的冰山一角(后续工作中大概率还会遇到其他的非常规文件),但希望能为读者提供一些参考和帮助。