英文:Mike Driscoll,转自:数据派(ID:datapi),翻译:季洋 英文:Mike Driscoll,转自:数据派(ID:datapi),翻译:季洋 有很多时候你会想用Python从PDF中提取数据,然后将其导出成其他格式。不幸的是,并没有多少Python包可以很好的执行这部分工作。在这篇贴子中,我们将探讨多个不同的Python包,并学习如何从PDF中提取某些图片。尽管在Python中没有一个完整的解决方案,你还是应该能够运用这里的技能开始上手。提取出想要的数据之后,我们还将研究如何将数据导出成其他格式。 让我们从如何提取文本开始学起! 使用PDFMiner提取文本 最被大家所熟知的可能是一个叫做PDFMiner的包。PDFMiner包大约从Python 2.4版本就存在了。它的主要目的是从PDF中提取文本。实际上,PDFMiner可以告诉你某文本在分页上具体的位置和字体信息。对于Python 2.4到2.7版本,你可以参考以下网站来了解PDFMiner的更多信息: GitHub – https://github.com/euske/pdfminer PyPI – https://pypi.python.org/pypi/pdfminer/ Webpage – https://euske.github.io/pdfminer/ GitHub – https://github.com/euske/pdfminer PyPI – https://pypi.python.org/pypi/pdfminer/ Webpage – https://euske.github.io/pdfminer/ PDFMiner是不兼容于Python 3的。幸运的是,PDFMiner家族的一个分支PDFMiner.six在Python 3上完全能胜任同样的功能。 你可以在以下网站上找到: https://github.com/pdfminer/pdfminer.six https://github.com/pdfminer/pdfminer.six 关于PDFMiner的安装说明已经比较过时了。其实你可以用pip命令来安装它: python -m pip install pdfminer 如果你要在Python 3上安装PDFMiner(这也许就是你现在正在做的),你需要这样安装: python -m pip install pdfminer.six PDFMiner的相关文档很少。你将很大可能地需要使用Google和Stack Overflow两个查询工具来弄清楚如何在这篇贴子的涵盖内容之外有效地使用PDFMiner。 提取所有文本 有时你会想要提取PDF文件中的所有文本。PDFMiner包提供了一些不同的方法使你能够做到这一点。我们先来探讨一些编程的方法。让我们试着从一个国税局W9表单中读取所有的文本。 你可以从这里得到表单副本: https://www.irs.gov/pub/irs-pdf/fw9.pdf https://www.irs.gov/pub/irs-pdf/fw9.pdf 保存完这个PDF文件之后,你可以参考以下代码: import io from pdfminer.converter import TextConverter from pdfminer.pdfinterp import PDFPageInterpreter from pdfminer.pdfinterp import PDFResourceManager from pdfminer.pdfpage import PDFPage def extract_text_from_pdf (pdf_path) : resource_manager = PDFResourceManager() fake_file_handle = io.StringIO() converter = TextConverter(resource_manager, fake_file_handle) page_interpreter = PDFPageInterpreter(resource_manager, converter) with open(pdf_path, 'rb' ) as fh: for page in PDFPage.get_pages(fh, caching= True , check_extractable= True ): page_interpreter.process_page(page) text = fake_file_handle.getvalue() # close open handles converter.close() fake_file_handle.close() if text: return text if __name__ == '__main__' : print(extract_text_from_pdf( 'w9.pdf' )) 当你直接使用PDFMiner包时,往往会有点繁琐。这里,我们从PDFMiner的不同模块中引入多个不同的类。由于这些类都没有文档说明,也没有实现其文档字符串属性,我将不会深入讲解它们做了什么。如果你真的好奇的话,尽管可以深入地研究它们的源代码。无论如何,我认为我们可以大致照以上代码行事。 我们做的第一件事就是创建一个资源管理器的实例。然后通过Python的输入输出(io)模块创建一个似文件对象。如果你使用的是Python 2,你应该使用StringIO模块。接下来的步骤是创建一个转换器。在这个例子里,我们选择使用TextConverter,如果你想要的话,你还可以使用HTMLConverter或XMLConverter。最后,我们创建一个PDF解释器对象,携带着我们的资源管理器和转换器对象,来提取文本。 最后一步是打开PDF文件并且循环遍历每一页。结尾部分,我们抓取所有的文本,关闭不同的信息处理器,同时打印文本到标准输出(stdout)。 按页提取文本 通常我们并不需要从一个多页文档中抓取所有的文本。你一般会想要处理文档的某些部分。那么,让我们改写代码以便它提取文本呈分页的格式。这将允许我们在检查文本时,一次一页地进行: # miner_text_generator.py import io from pdfminer.converter import TextConverter from pdfminer.pdfinterp import PDFPageInterpreter from pdfminer.pdfinterp import PDFResourceManager from pdfminer.pdfpage import PDFPage def extract_text_by_page (pdf_path) : with open(pdf_path, 'rb' ) as fh: for page in PDFPage.get_pages(fh, caching= True , check_extractable= True ): resource_manager = PDFResourceManager() fake_file_handle = io.StringIO() converter = TextConverter(resource_manager, fake_file_handle) page_interpreter = PDFPageInterpreter(resource_manager, converter) page_interpreter.process_page(page) text = fake_file_handle.getvalue() yield text # close open handles converter.close() fake_file_handle.close() def extract_text (pdf_path) : for page in extract_text_by_page(pdf_path): print(page) print() if __name__ == '__main__' : print(extract_text( 'w9.pdf' )) 在这个例子中,我们创建了一个生成器函数按页生成(yield)了文本。extract_text函数按页打印出文本。此处我们可以加入一些分析逻辑来得到我们想要的分析结果。或者我们可以仅是将文本(或HTML或XML)存入不同的文件中以便分析。 你可能注意到这些文本没有按你期望的顺序排列。因此你需要思考一些方法来分析出你感兴趣的文本。 PDFMiner的好处就是你可以很方便地按文本、HTML或XML格式来“导出”PDF文件。 你也可以使用PDFMiner的命令行工具,pdf2txt.py和dumppdf.py,来为你执行导出工作。如果你不想试图自己弄明白PDFMiner。