从PDF文档解析表格

6 投票
4 回答
5040 浏览
提问于 2025-04-17 23:44

这个链接里的PDF文档(http://www.lenovo.com/psref/pdf/psref450.pdf)里面有很多像这样的表格:

enter image description here

我想通过编程的方式提取这些表格里的数据和结构。

我尝试过的办法有:

  1. Tika:可惜的是,表格被转换成了用空格分隔的段落,而且有些字符串里也有空格,所以没法分开。
  2. Python的PDFMiner:因为缺少字体返回了一个错误。我怀疑转换成HTML的结果和Tika的输出差不多,不过我需要先解决缺少字体的问题才能确认。
  3. 在线工具:我试过http://www.zamzar.com/和其他几个工具。要么文件太大无法处理(对于在线服务来说),要么出现了错误。

我原本打算把PDF转换成HTML,然后用BeautifulSoup来解析。

输出结果可以是JSON格式(比如每个表格一个对象)、XML,或者任何能保持结构的格式。

4 个回答

0

使用PDFplumber从PDF文档中提取表格

import pdfplumber
import pandas as pd
filepath = r"actualFile_path"
outfile = r"destination_path"
pdf = pdfplumber.open(filepath)
for i in range(int(len(pdf.pages))):
      df = pd.DataFrame()
      table = pdf.pages[i].extract_table(table_settings=
      {"vertical_strategy": "text", "horizontal_strategy": "text"})
      df = pd.DataFrame(table, columns=table)
df.to_csv(outfile2, mode='a', index=False)
1

仅供参考,因为我的工具不是公开的:这确实是可能的。这里有一个简单的文本表格——中间的空格是制表符,而不是普通空格:

2469-2TU    i5-3320M    4GBx1   14.0" HD    720p    500G 7200   Intel 620528    WWAN upg    Express 54  Finger  BT  6   Win7 Pro64  10/12
✂ 2469-2SU  i5-3210M    4GBx1   14.0" HD    720p    500G 7200   Intel 2200  WWAN upg    Express 54  None    None    6   Win7 Pro64  10/12
✂ 2469-2RU  i3-3110M    4GBx1   14.0" HD    720p    320G 7200   Intel 2200  WWAN upg    Express 54  None    None    6   Win7 Pro64  10/12
2469-32U    i5-3230M    4GBx1   14.0" HD    720p    320G 7200   Intel 6205  WWAN upg    None    Finger  BT  6   Win7 Pro64  02/13
2469-2ZU    i5-3230M    4GBx1   14.0" HD    720p    320G 7200   Intel 2200  WWAN upg    None    None    None    6   Win7 Pro64  02/13
2469-2YU    i5-3320M    4GBx1   14.0" HD    720p    320G 7200   Intel 6205  WWAN upg    None    Finger  BT  6   Win7 Pro64  02/13
2469-2XU    i5-3320M    4GBx1   14.0" HD    720p    320G 7200   Intel 6205  WWAN upg    None    None    None    6   Win7 Pro64  02/13
2469-2WU    i5-3320M    4GBx1   14.0" HD    720p    320G 7200   WLAN upg    WWAN upg    None    Finger  BT  6   Win7 Pro64  02/13

我也推荐使用PDFBox,因为它的工作方式和我自己写的工具类似:先检查(x,y)的位置,排序,然后把“可能”的字符串拼接在一起,当横向的空白大于正常情况下的预期时,就插入一个制表符。

我甚至在Zapf Dingbats中找到了小剪刀图标 :)

1

@alex-woolford: 一般来说,从PDF中完美提取数据(无论是保持原有格式还是不保持)并不是总能做到的,准确率也不可能达到100%。我之所以这么说,是因为我之前做过类似的项目,遇到过和你一样的问题。网上的一些研究显示,PDF格式本身并不是一个完全可逆的格式,也就是说,从PDF中恢复文本和格式时,准确率不一定能达到100%。在提取过程中,有时字符会丢失,或者顺序会搞错,这些都是常见的问题。这似乎是PDF格式本身的特性造成的,因为它并不是一种基于文本的格式,而是PostScript的衍生物,关于数据布局有一些奇怪的规则。这些信息来自官方的PDF文档,或者一些长期从事PDF相关工作的公司网站,这些公司的产品也很有名。

如果你能接受不那么完美的准确率,有一些产品可以使用(不过我现在不知道有没有适合Python的)。其中一个是xpdf,另一个是PDFTextStream。我用过xpdf,但没用过PDFTextStream。xpdf是一个C语言的库,还有命令行工具。PDFTextStream是一个Java工具/库。之前它是付费产品,但我最后查的时候,它现在对单线程应用是免费的,没记错的话。

虽然xpdf是C语言的,PDFTextStream是Java的,但你可以通过XML-RPC或者其他分布式计算/跨语言通信的方法,比如套接字,从Python调用它们。当然,这需要一些额外的工作。

希望对你有帮助。

6

你可以试试PDFBox这个工具。它的使用说明在这里:

https://pdfbox.apache.org/1.8/cookbook/textextraction.html

你可以扩展一个叫做org.apache.pdfbox.pdfviewer.PDFPageDrawer的类,并重写它的strokePath方法。通过这个方法,你可以拦截绘制水平和垂直线段的操作,然后利用这些信息来确定文本在表格中的行和列位置。你可以设置文本区域,来判断哪些数字、字母或字符是在什么区域内绘制的。因为你知道这些区域是按照表格布局的,所以你可以定义表格,并用简单的算法来判断提取出来的文本属于哪个列和行。

撰写回答