解析 PDF 文件并输出单个字符位置
Parse PDF file and output single character locations
我正在尝试通过识别每个 字符 和每个单词的内容和位置,从(数字)PDF 中提取文本信息。对于文字,来自 xpdf / poppler 的 pdftotext --bbox
效果很好,但我找不到提取字符位置的简单方法。
我试过的
我目前的解决方案是将 pdf 转换为 svg(通过 pdf2svg
),然后解析生成的 svg 以提取单个字符(=字形)位置。在第三步中,比较结果框,将每个字符分配给一个单词,希望数字匹配。
问题
虽然以上方法适用于大多数 "basic" 字体,但在两种(主要)情况下此方法会失败:
- 在脚本字体(或一些极端的斜体字体)中,边界框比它们的内容大得多;结果,单词明显重叠,一个字符完全包含在两个单词中很可能发生。在这种情况下,映射失败,因为一旦我转换为 svg,我就没有关于哪个字符包含在哪个字形中的信息。
- 在许多字体中,可以连接多个字符,从而产生单个字形。在这种情况下,字符框的数量与单词中的字符数不匹配,将每个字母匹配到一个框又是有问题的。
第二点(对我来说是主要的)通过识别常见的连字和(如果计数不匹配)将相应的边界框分成多个部分来实现部分解决方法;但这并不总是有效,因为例如 "ffi" 有时连接到单个字形,有时连接到两个字形 "ff" + "i",有时连接到两个字形 "f" + "fi",取决于字体。
我所希望的
据我了解,pdf 实际上包含字形信息,而不是文字。如果是这样,所有从pdf中提取文本的程序(如pdftotext
)都必须首先提取并定位各种字符,然后可能将它们分组为words/lines;所以我有点惊讶我找不到为每个单个字符输出位置的选项。转换为 svg 本质上给了我这个,但是在那个转换中关于内容的所有信息(即映射字形到字符,或者字形到字符,如果有连字)都丢失了,因为不再有字体。通过再次查看字体来重做将每个字形与字符匹配的工作感觉就像重写 pdf 解析器...
因此,我将非常感谢任何有关如何解决此问题的想法。 The top answer here 建议使用 TET 这可能是可行的,但它是一种付费选项,更换我的整个基础设施以处理一个极限情况似乎有点矫枉过正...
PDF 文件不一定明确指定每个字符的位置。通常,它将文本分成 运行 个字符(全部使用相同的字体,我认为最多一行)然后为每个 运行 指定边界框的位置应该包含这些字符的字形。因此每个字形的确切位置将取决于用于呈现它的字体的规格(主要是 glyph-widths)。
Python 包 pdfminer
有一个脚本 pdf2txt.py
。尝试使用 -t xml
调用它。文档只是说 XML format. Provides the most information.
但我的笔记表明它将应用 font-metrics 并为每个字形提供一个 <text>
元素,带有字体和 bounding-box 信息。
在不同的地方有不同的版本(例如 PyPI 和 github)。如果您需要 Python 3 支持,请寻找 pdfminer.six
.
我正在尝试通过识别每个 字符 和每个单词的内容和位置,从(数字)PDF 中提取文本信息。对于文字,来自 xpdf / poppler 的 pdftotext --bbox
效果很好,但我找不到提取字符位置的简单方法。
我试过的
我目前的解决方案是将 pdf 转换为 svg(通过 pdf2svg
),然后解析生成的 svg 以提取单个字符(=字形)位置。在第三步中,比较结果框,将每个字符分配给一个单词,希望数字匹配。
问题
虽然以上方法适用于大多数 "basic" 字体,但在两种(主要)情况下此方法会失败:
- 在脚本字体(或一些极端的斜体字体)中,边界框比它们的内容大得多;结果,单词明显重叠,一个字符完全包含在两个单词中很可能发生。在这种情况下,映射失败,因为一旦我转换为 svg,我就没有关于哪个字符包含在哪个字形中的信息。
- 在许多字体中,可以连接多个字符,从而产生单个字形。在这种情况下,字符框的数量与单词中的字符数不匹配,将每个字母匹配到一个框又是有问题的。
第二点(对我来说是主要的)通过识别常见的连字和(如果计数不匹配)将相应的边界框分成多个部分来实现部分解决方法;但这并不总是有效,因为例如 "ffi" 有时连接到单个字形,有时连接到两个字形 "ff" + "i",有时连接到两个字形 "f" + "fi",取决于字体。
我所希望的
据我了解,pdf 实际上包含字形信息,而不是文字。如果是这样,所有从pdf中提取文本的程序(如pdftotext
)都必须首先提取并定位各种字符,然后可能将它们分组为words/lines;所以我有点惊讶我找不到为每个单个字符输出位置的选项。转换为 svg 本质上给了我这个,但是在那个转换中关于内容的所有信息(即映射字形到字符,或者字形到字符,如果有连字)都丢失了,因为不再有字体。通过再次查看字体来重做将每个字形与字符匹配的工作感觉就像重写 pdf 解析器...
因此,我将非常感谢任何有关如何解决此问题的想法。 The top answer here 建议使用 TET 这可能是可行的,但它是一种付费选项,更换我的整个基础设施以处理一个极限情况似乎有点矫枉过正...
PDF 文件不一定明确指定每个字符的位置。通常,它将文本分成 运行 个字符(全部使用相同的字体,我认为最多一行)然后为每个 运行 指定边界框的位置应该包含这些字符的字形。因此每个字形的确切位置将取决于用于呈现它的字体的规格(主要是 glyph-widths)。
Python 包 pdfminer
有一个脚本 pdf2txt.py
。尝试使用 -t xml
调用它。文档只是说 XML format. Provides the most information.
但我的笔记表明它将应用 font-metrics 并为每个字形提供一个 <text>
元素,带有字体和 bounding-box 信息。
在不同的地方有不同的版本(例如 PyPI 和 github)。如果您需要 Python 3 支持,请寻找 pdfminer.six
.