​ 之前我媳妇儿让我给她找一个PDF转WORD的免费工具,在网上找了半天发现要不就是收费,要不就是转化的格式混乱。既然网上不能找到好用的免费工具那就直接来写一个吧。人生苦短,我用python。

万能的python肯定应该有关于这个第三方库,百度了一下果不其然——PDFminer3k(如果你用的是python2的话那你应该使用的是pdfminer)。

我们先上代码然后再分析吧。

# -*- coding:utf-8 -*-#author:菜鸟小白的学习分享from pdfminer.pdfparser import PDFParser, PDFDocumentfrom pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreterfrom pdfminer.converter import PDFPageAggregatorfrom pdfminer.layout import LTTextBoxHorizontal, LAParamsfrom pdfminer.pdfinterp import PDFTextExtractionNotAlloweddef parse(DataIO, save_path):    # 用文件对象创建一个PDF文档分析器    parser = PDFParser(DataIO)    # 创建一个PDF文档    doc = PDFDocument()    # 分析器和文档相互连接    parser.set_document(doc)    doc.set_parser(parser)    # 提供初始化密码,没有默认为空    doc.initialize()    # 检查文档是否可以转成TXT,如果不可以就忽略    if not doc.is_extractable:        raise PDFTextExtractionNotAllowed    else:        # 创建PDF资源管理器,来管理共享资源        rsrcmagr = PDFResourceManager()        # 创建一个PDF设备对象        laparams = LAParams()        # 将资源管理器和设备对象聚合        device = PDFPageAggregator(rsrcmagr, laparams=laparams)        # 创建一个PDF解释器对象        interpreter = PDFPageInterpreter(rsrcmagr, device)        # 循环遍历列表,每次处理一个page内容        # doc.get_pages()获取page列表        for page in doc.get_pages():            interpreter.process_page(page)            # 接收该页面的LTPage对象            layout = device.get_result()            # 这里的layout是一个LTPage对象 里面存放着page解析出来的各种对象            # 一般包括LTTextBox,LTFigure,LTImage,LTTextBoxHorizontal等等一些对像            # 想要获取文本就得获取对象的text属性            for x in layout:                try:                    if (isinstance(x, LTTextBoxHorizontal)):                        with open('%s' % (save_path), 'a') as f:                            result = x.get_text()                            print(result)                            f.write(result + "\n")                except:                    print("Failed")if __name__ == '__main__':    # 解析同一文件夹下的PDF文件,保存到本地doc文件中    with open(r'菜鸟小白.pdf', 'rb') as pdf_html:        parse(pdf_html, r'11.doc')

分析过程

 

PDF没有WORD、Excel这样简单,可以直接去读取内容,读取PDF文件需要用程序以二进制的方式读取,然后转化成文字。而我们通过pdfminer的转化过程就好比是读取出来具体内容后猜测他们的布局,用于重建文字的结构,但是这个也无法保证100%能够工作。

代码中pdfminer调用的每个函数作用分别为:

  • DFParser(文档分析器)

  • PDFDocument(文档对象)

  • PDFResourceManager(资源管理器)

  • PDFPageInterpreter(解释器)

  • PDFPageAggregator(聚合器)

  • LAParams(参数分析器)

首先我们需要新建一个文档分析器和PDF文档,并且将PDF文档对象和文档分析器关联起来。

 # 用文件对象创建一个PDF文档分析器    parser = PDFParser(DataIO)    # 创建一个PDF文档    doc = PDFDocument()    # 分析器和文档相互连接    parser.set_document(doc)    doc.set_parser(parser)

然后我们新建一个资源管理器和新建一个PDF参数对象

        # 创建PDF资源管理器,来管理共享资源        rsrcmagr = PDFResourceManager()        # 创建一个PDF设备对象        laparams = LAParams()

然后我们新建一个聚合器,用于接收资源管理器和参数对象;创建一个解释器,接收资源管理器和聚合器。

        # 将资源管理器和设备对象聚合        device = PDFPageAggregator(rsrcmagr, laparams=laparams)        # 创建一个PDF解释器对象        interpreter = PDFPageInterpreter(rsrcmagr, device)

然后使用get_pages()去获取所有的页面,用一个for循环遍历每一个页面,使用interperter页面解释器对页面进行逐一聚合,然后调用聚合器的get_result()获取到layout,layout中的每一个内容,只有文本内容才会被提取出来。

        # 循环遍历列表,每次处理一个page内容        # doc.get_pages()获取page列表        for page in doc.get_pages():            interpreter.process_page(page)            # 接收该页面的LTPage对象            layout = device.get_result()            # 这里的layout是一个LTPage对象 里面存放着page解析出来的各种对象            # 一般包括LTTextBox,LTFigure,LTImage,LTTextBoxHorizontal等等一些对像            # 想要获取文本就得获取对象的text属性            for x in layout:                try:                    if (isinstance(x, LTTextBoxHorizontal)):                        with open('%s' % (save_path), 'a') as f:                            result = x.get_text()                            print(result)                            f.write(result + "\n")                except:                    print("Failed")

最新实现效果

 

原始的PDF文档

转化后的word文档

缺陷

当前的代码仅能实现文字的提取,无法提取图片。后面我们再看看能否将图片也一起提取出来,有厉害的小伙伴也可以私信我。


最后我把这个从程序打包成了一个exe文件,只需要将你想要转化的PDF文档和exe文件放在同一个文件夹内就可以双击执行转化了。有需要的小伙伴可以私信菜鸟小白"PDFtoWORD"获取下载链接。

随机推荐

  1. 基础拾遗---委托,匿名函数,lambda

    前言: C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针.委托是存有对某个方法的引用的一种引用类型变量.引用可在运行时被改变.委托(Delegate)特别用于实现事件和回调方法. ...

  2. SpringMVC整合mybaitis

    目录 一.新建一个基于Maven的Web项目 二.创建数据库与表 三.添加依赖包 四.新建POJO实体层 五.新建MyBatis SQL映射层 六.完成Spring整合MyBatis配置 七.创建服务 ...

  3. shellcode 免杀(一)

    工具免杀 选择了几个简单或者近期还有更新的免杀工具进行学习 ShellcodeWrapper https://github.com/Arno0x/ShellcodeWrapper 该工具的原理是使用异 ...

  4. jmeter在Windows下安装(含插件安装)

    [准备环境] jdk1.8 jmeter的安装包下载 [步骤] 1 把下载下来的压缩包解压,点击jmeter.bat 启动,启动后是英文界面 2 修改默认的英文界面,打开jmeter.properti ...

  5. PHP利用FTP上传文件连接超时之开启被动模式解决方法

    初始代码: <?php $conn = ftp_connect("localhost") or die("Could not connect"); ftp ...

  6. 腾讯IEG--2020春招实习

    笔试 正常批就五道编程题,可以跳出使用本地IDE,题目很好理解,基本都能写出来,但是要过全部用例不容易.具体题目和题解可以看看这位大佬的牛客帖子,我的就不献丑了,有两题都只过了40%,我当时是用C#做 ...

  7. keras训练函数fit和fit_generator对比,图像生成器ImageDataGenerator数据增强

    1. [深度学习] Keras 如何使用fit和fit_generator https://blog.csdn.net/zwqjoy/article/details/88356094 ps:解决样本数 ...

  8. 懂了!VMware/KVM/Docker原来是这么回事儿

    云计算时代,计算资源如同小马哥当年所言,已经成为了互联网上的水和电. 虚拟主机.web服务器.数据库.对象存储等等各种服务我们都可以通过各种各样的云平台来完成. 而在云计算欣欣向荣的背后,有一个重要的 ...

  9. python 类中方法总结 --- 实例方法、类方法、静态方法

    在python的类语法中,可以出现三种方法,具体如下: (1)实例方法 1)第一个参数必须是实例本身,一般使用[self]表示. 2)在实例方法中,可以通过[self]来操作实例属性,[类名]来操作类 ...

  10. Feign拦截器应用 (F版)

    Spring Cloud 为开发者提供了在分布式系统中的一些常用的组件(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁定,决策竞选,分布式会话集群状态).使用Sprin ...