我有一个关于从pdf文件中提取文本,准确地说是表格数据的一般问题。
pdf查看器如何读取和显示表格?为什么我们不能以同样的方式获取必要的列信息呢?
我已经搜索了一个星期,主要是使用pdftoxml处理令牌坐标和太宽的表格单元格(这样就不可能准确地识别中间的空表格单元格)。
我为我的一堆pdf文件解决了这个问题,方法是重新展开文本(顺便说一下。如果行与行之间的距离被否定并“粘贴回一起”,则逐行实现是非常成功的),但这当然只是一个实例解决方案。
这让我有点头疼。pdf查看器为单元格绘制线条,并知道单元格的开始和结束位置,但我们无法从pdf源文件中读取这些内容。这怎么可能呢?他们知道什么是我们不能推断的?
发布于 2012-12-22 20:20:10
您的误解是将列作为列存储在PDF文件中。事实并非如此。PDF查看器无法理解表格、列、段落、文本行或单词。
PDF是作为页面描述语言创建的,它非常擅长在许多不同的设备上重现完全相同的页面。因为这是它的目标,它不关心结构,而你指的是所有的结构。
PDF绘制文本的方式非常非常简单。页面上的说明如下所示:
虽然也可以将一些结构信息与这些指令一起存储在PDF中,但通常不会这样做,它是在事后才以PDF格式实现的。
当你看上面的(伪)指令时,很容易理解表格是如何绘制的。只需在文件中指示移动到某个单元格的某个位置并绘制文本即可。然后是移动到另一个单元格并绘制文本的更多指令。
如果想要反向操作并从PDF页面中提取结构化信息,则必须“重新发明”结构信息。这意味着要找出哪些文本在相同的基线上,因此可能属于同一行。哪些文本在基线上足够接近,因此它可能是单词或列……等等。
正如你已经发现的那样,这不是一件容易的事情!
发布于 2012-12-23 05:47:16
在未压缩的pdf文档中,存在伪正则表达式形式的以下不确定格式((0,0)位于左下角)的“流对象”:
(x1 y1 m x2 y2 l [whitespace or blank or newline seperator symbol])* S (BT .* ET)*哪里
x1, y1, x2, y2 are coordinates
l probably for "draw line"
m move to, "from to" or "merge"
S is the command for "draw" or the like
BT Begin Text
ET End Text所有命令后缀。
编辑:
一种可能的Java regexp是(参考PDF32000_2008.pdf),在未压缩的pdf源文件中用空格替换换行符之后:
((\s+\d+(\.\d+)?){2}(\s+m|\s+l|(\s+\d+(\.\d+)?){2}(\s+re|\s+y|\s+v|(\s+\d+(\.\d+)?){2}\s+c))\s+)+([SsFn]|[fBb](\*)?) 在流中还有像"W*“或"Q q”这样的其他元素,它们通常似乎可以调整线条粗细或字体属性。由于我找不到一个特别的语言规范,这就是我从实验中得出的结论。
使用此信息和文本标记的坐标(在ET和BT之间),可以推断表格单元格宽度、表格开始和结束位置(用于识别不同的表格)。
问题仍然是任何类型的解压缩流。使用pdftk,我能够解压从openoffice writer创建的pdf文件,但任意的pdf文件中仍然有神秘的符号。
更多信息:
http://www.gnupdf.org/Introduction_to_PDF
http://blog.idrsolutions.com/2011/05/understanding-the-pdf-file-format-%E2%80%93-carriage-returns-spaces-and-other-gaps/
http://blog.idrsolutions.com/2012/03/understanding-the-pdf-file-format-names-locations/
http://blog.idrsolutions.com/2011/05/understanding-the-pdf-file-format-%E2%80%93-pdf-xref-tables-explained/
PDF page-stream optimizer library?
http://www.gnupdf.org/Stream
https://stackoverflow.com/questions/14001973
复制相似问题