首页 > 解决方案 > PowerShell,itextsharp 提取的文本不再可读(脚本之前很好)

问题描述

我正在使用带有itextsharp的PowerShell脚本 从会计 PDF 中提取一些数据,以在网络服务器数据库上组织重命名的文件(带有提取的数据)...... 直到最近一切正常: 提取的文本不再可读;我有像这样的符号


!9H#SH!#!T !a!ST^ET
8%’?E!8A8A,A ;B;0D3FD
U+.0’$=Q$;L?L\$’($4-R$2’$4+(.’R.-./+($D$
%M%G.T

我想这与会计软件更新后的新编码方式有关。
像下面这样的简单脚本正在工作
function convert-PDFtoText {
    param(
        [Parameter(Mandatory=$true)][string]$file
    )   
    Add-Type -Path "C:\PathTo\itextsharp.dll"
    $pdf = New-Object iTextSharp.text.pdf.pdfreader -ArgumentList $file
    for ($page = 1; $page -le $pdf.NumberOfPages; $page++){
        $text=[iTextSharp.text.pdf.parser.PdfTextExtractor]::GetTextFromPage($pdf,$page)
        Write-Output $text
    }   
    $pdf.Close()
}

$file = "C:\ADA3_FA20210274.pdf"

convert-PDFtoText $file

它不适用于那些新的 PDF 文件。

如果有人能告诉我处理这个问题的方法,我会很感激
我使用 itextsharp 5.5.13.2
编辑:
这里是其中一个 PDF 的链接:pdf_exemple.pdf

标签: powershellcharacter-encodingitext

解决方案


简而言之

正如已经指出的那样,Unicode CMappdftotext.exe中有非法条目。更准确地说, PDF 中字体的 ToUnicode 映射中的所有条目都是无效的。因此,如果它无法从文档中提取文本,则它不是文本提取器中的错误。但是,一些解析器显然以忽略错误的方式解析地图。

详细地

PDF 主要是为 PDF查看器制作的,因此 PDF 中的字体定义只需提供从显示指令的文本字符串参数中使用的代码到字形绘图定义的映射,例如嵌入在 pdf 中的 ttf 流。特别是他们不需要提供从这些代码到Unicode 字符的映射。因此,PDF 正确显示并不意味着可以从中提取文本。

PDF可以在所谓的ToUnicode映射中提供从这些代码到 Unicode 字符的映射。如果是您的 PDF,则提供了此类地图,但它们都已损坏

这些文本形式的映射应包含定义代码性质的代码空间范围部分,特别是单个字节或多个字节是否构成单个字形的代码。然后在bfcharbfrange部分中,单个代码或代码范围应分别映射到单个 Unicode 字符串或其范围。代码和 Unicode 字符串在尖括号中以十六进制表示法给出。

在您的 PDF 中,这些地图已损坏。例如,在字体1的情况下,代码空间范围定义为

1 begincodespacerange
<00> <FF>
endcodespacerange

即作为从 0x00 到 0xFF 的单字节代码。这是正确的,字体是简单字体,因此只能有单字节代码。但...

然后该字体仅使用bfchar部分来映射这些代码:

66 beginbfchar
<0021> <0032#1>
<0022> <0036#1>
<0023> <0030#1>
<0024> <0020#1>
<0025> <0041#1>
<0026> <0076#1>
...
<005D> <0025#1>
<005E> <002C#1>
<005F> <004B#1>
<0060> <0062#1>
<0061> <00A0#1>
<0062> <0044#0>
endbfchar

这部分的条目都坏了

一方面根据上面的codespacerange我们只有单字节码,但这里我们只有双字节码的映射<0021><0022>等等。由于码域也可能是混合长度,所以必须认真对待码长,所以所有这些双字节码-byte 条目不能用于文本提取,因为字体不使用任何双字节代码。

另一方面,这些映射的所有值都被破坏,因为它们包含非法部分#1#0. 这里解析器可以立即忽略这些条目,因为不清楚这意味着什么。

因此,许多文本提取器会忽略这些映射并默认返回原样的代码。在许多 PDF 中,代码实际上是一些常见的 ASCII'ish 编码,所以这个默认值是有意义的。但是,在您的 PDF 中,字体编码不是,它们是不同的、非标准的临时编码。所以你得到的只是胡言乱语。

从您的 PDF 中提取所需文本的 PDF 查看器会忽略上述错误,在其他情况下,这些错误可能会导致他们提取乱码,而更严格的提取器会提取一些合理的内容。

因此,您应该告诉更新会计软件的维护人员他们的 PDF 中的错误,并要求他们解决这个问题。


推荐阅读