如何使用pikepdf提取PDF/A中未识别编码行的实际文本
PDF/A内容类型判断与乱码文本解码方法
一、判断内容是否为图像的操作方式
- 区分绘制指令类型:你贴出的带十六进制编码的
TJ指令属于标准文本绘制指令,不可能是图像调用。图像内容只会通过Do指令触发绘制,不会出现在Tj/TJ这类文本操作指令的参数中。 - 用pikepdf做对象校验:遍历页面对象时,可直接读取
page.images属性获取当前页所有登记在册的图像XObject列表,这些对象的/Subtype属性固定为/Image;如果内容流里Do指令引用的XObject在这个列表里,对应绘制内容就是图像,不存在可直接提取的文本编码。 - 交叉校验:如果某块可见内容既没有对应的文本绘制指令,又能匹配到
Do指令调用的图像对象,就可以判定为扫描图像类内容。
二、非图像类编码文本的映射规则查找路径
你遇到的<00240007>这类十六进制包裹的内容是CID编码格式的文本,所有解码需要的映射规则100%存储在PDF文件内部,Ghostscript转出的PDF/A遵循规范强制要求嵌入完整映射,不存在外部依赖,按以下顺序查找即可:
- 第一步:定位当前文本块绑定的字体。文本块绘制前一定会先执行
Tf指令指定所用字体,比如/F2 10 Tf代表当前文本使用页面资源表中登记名为F2的字体,直接从page.Resources.Font字典里取对应键的字体对象即可。 - 第二步:优先提取
/ToUnicode映射表。这是解码最可靠的依据:找到字体对象后,检查是否存在/ToUnicode属性,该属性指向一个流对象,pikepdf会自动处理流的解压,直接调用.read_bytes().decode('latin-1')就能拿到CMap映射文本,解析其中beginbfchar/beginbfrange段的码值对应关系,就能把<>里的十六进制编码直接转换为可读Unicode文本。 - 第三步:补全缺失映射(PDF/A场景几乎不会遇到):如果没有
/ToUnicode表,再顺着字体对象的/Encoding属性检查:如果是编码字典,先读/Differences数组里的字符码到字形名的映射;如果是CID字体,顺着/DescendantFonts数组找到嵌入的子字体对象,检查/Encoding关联的CMap映射,结合/CIDSystemInfo指定的字符集完成解码。
注意:你之前能直接解析的
(C)这类写法是单字节标准编码的文本写法,<>包裹的十六进制是多字节CID编码的文本写法,两者只是编码存储形式不同,都属于原生可提取文本,不要误判为图像或加密内容。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

