从PDF文档解析表格
这个链接里的PDF文档(http://www.lenovo.com/psref/pdf/psref450.pdf)里面有很多像这样的表格:
我想通过编程的方式提取这些表格里的数据和结构。
我尝试过的办法有:
- Tika:可惜的是,表格被转换成了用空格分隔的段落,而且有些字符串里也有空格,所以没法分开。
- Python的PDFMiner:因为缺少字体返回了一个错误。我怀疑转换成HTML的结果和Tika的输出差不多,不过我需要先解决缺少字体的问题才能确认。
- 在线工具:我试过http://www.zamzar.com/和其他几个工具。要么文件太大无法处理(对于在线服务来说),要么出现了错误。
我原本打算把PDF转换成HTML,然后用BeautifulSoup来解析。
输出结果可以是JSON格式(比如每个表格一个对象)、XML,或者任何能保持结构的格式。
4 个回答
使用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)
仅供参考,因为我的工具不是公开的:这确实是可能的。这里有一个简单的文本表格——中间的空格是制表符,而不是普通空格:
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中找到了小剪刀图标 :)
@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调用它们。当然,这需要一些额外的工作。
希望对你有帮助。
你可以试试PDFBox这个工具。它的使用说明在这里:
https://pdfbox.apache.org/1.8/cookbook/textextraction.html
你可以扩展一个叫做org.apache.pdfbox.pdfviewer.PDFPageDrawer的类,并重写它的strokePath方法。通过这个方法,你可以拦截绘制水平和垂直线段的操作,然后利用这些信息来确定文本在表格中的行和列位置。你可以设置文本区域,来判断哪些数字、字母或字符是在什么区域内绘制的。因为你知道这些区域是按照表格布局的,所以你可以定义表格,并用简单的算法来判断提取出来的文本属于哪个列和行。