基于Python实现PDF区域文本提取工具

目录
  • 功能简介
  • 开发代码

功能简介

打开软件后界面如下:

点击打开文件按钮打开之前的PDF文件后效果如下:

框选区域后,标题栏会自动显示当前框选的区域提取到的文字,还可以左右按钮切换:

实际我们需要提取文字的区域可能不止这一个,所以程序支持多区域框选:

完成区域框选后就可以点击保存文件,将PDF每页提取到的文本保存到一个csv文件中,当前选区的保存结果如下:

可以看到已经按框选顺序依次保存了每一个区域的字符串。

如果选择区域时发现提取结果不准确,可以撤销后重新选择:

保存图片则会将PDF的每页的整体保存为一张图片,未选择区域时,以页码为文件名保存图片:

选择区域时,会自动提取最后一个区域提取的文本作为当前页的文件名:

开发代码

当然这个项目由于本人是一次使用wxpython,功能非常简约,现在将完整代码开源出来期待各位大佬的改进。

源码和已编译工具下载地址:

https://codechina.csdn.net/as604049322/python_gui

完整代码:

"""
小小明的代码
CSDN主页:https://blog.csdn.net/as604049322
"""
__author__ = '小小明'
__time__ = '2021/11/24'

import csv

import wx
import os
import fitz

class MyCanvas(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.parent = parent
        self.rects = []
        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftButtonEvent)
        self.Bind(wx.EVT_LEFT_UP, self.OnLeftButtonEvent)
        self.Bind(wx.EVT_MOTION, self.OnLeftButtonEvent)
        self.Bind(wx.EVT_PAINT, self.DoDrawing)
        b = wx.Button(self, -1, "打开文件", (0, 0))
        self.Bind(wx.EVT_BUTTON, self.OnButton, b)
        b = wx.Button(self, -1, "保存文件", (75, 0))
        self.Bind(wx.EVT_BUTTON, self.save_file, b)
        b = wx.Button(self, -1, "保存图片", (150, 0))
        self.Bind(wx.EVT_BUTTON, self.save_img, b)
        b = wx.Button(self, -1, "撤销选区", (225, 0))
        self.Bind(wx.EVT_BUTTON, self.back_select, b)

        b = wx.Button(self, -1, "《", (300, 0), size=(25, 25))
        self.Bind(wx.EVT_BUTTON, self.previous, b)
        b = wx.Button(self, -1, "》", (325, 0), size=(25, 25))
        self.Bind(wx.EVT_BUTTON, self.next, b)

        self.g1 = wx.Gauge(self, -1, 100, (0, 30), (-1, 100), wx.GA_VERTICAL)

    def previous(self, evt):
        if not hasattr(self, "pdfDoc"):
            return
        if self.i > 0:
            self.i -= 1
            self.change_pdf_page(self.i, False)
            self.DoDrawing(-1)
            if self.rects:
                self.parent.SetTitle(self.path + "|" + self.extract_pdf_text())

    def next(self, evt):
        if not hasattr(self, "pdfDoc"):
            return
        if self.i < self.pageCount - 1:
            self.i += 1
            self.change_pdf_page(self.i, False)
            self.DoDrawing(-1)
            if self.rects:
                self.parent.SetTitle(self.path + "|" + self.extract_pdf_text())

    def back_select(self, evt):
        if self.rects:
            self.rects.pop()
            self.DoDrawing(-1)

    def OnButton(self, evt):
        dlg = wx.FileDialog(
            self, message="选择一个PDF文件",
            defaultDir=os.getcwd(),
            defaultFile="",
            wildcard="PDF文件(*.pdf)|*.pdf",
            style=wx.FD_OPEN | wx.FD_CHANGE_DIR |
                  wx.FD_FILE_MUST_EXIST | wx.FD_PREVIEW
        )
        if dlg.ShowModal() == wx.ID_OK:
            self.rects = []
            path = dlg.GetPath()
            self.pdfDoc = fitz.open(path)
            self.i = 0
            self.pageCount = self.pdfDoc.pageCount
            self.change_pdf_page(self.i)
            self.path = os.path.basename(path)
            self.parent.SetTitle(self.path)
            self.DoDrawing(-1)
        dlg.Destroy()

    def change_pdf_page(self, i, move=True):
        page = self.pdfDoc[i]
        rect = page.rect
        print("pdf范围:", rect)
        mat = fitz.Matrix(1, 1)
        pix = page.get_pixmap(matrix=mat, alpha=False, clip=rect)
        pix.save("tmp.png")
        self.change_img("tmp.png", move)

    def save_FileDialog(self, format="csv"):
        dlg = wx.FileDialog(
            self, message=f"保存一个{format}文件", defaultDir=os.getcwd(),
            defaultFile="", wildcard=f"{format}文件(*.{format})|*.{format}", style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT
        )
        path = None
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
        dlg.Destroy()
        return path

    def save_img(self, evt):
        if not hasattr(self, "pdfDoc"):
            return
        dlg = wx.DirDialog(self, "选择图片保存的文件夹:",
                           style=wx.DD_DEFAULT_STYLE
                           # | wx.DD_DIR_MUST_EXIST
                           # | wx.DD_CHANGE_DIR
                           )
        mat = fitz.Matrix(1, 1)
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            for i in range(self.pdfDoc.pageCount):
                page = self.pdfDoc[i]
                clip = page.rect
                pix = page.get_pixmap(matrix=mat, alpha=False, clip=clip)
                if self.rects:
                    name = self.extract_pdf_text(page=page, rect=self.rects[-1])
                else:
                    name = f"p{i:0>3d}"
                pix.save(f"{path}/{name}.png")
                self.g1.SetValue((i + 1) * 100 // self.pdfDoc.pageCount)
        dlg.Destroy()
        os.system(f"explorer {path}")

    def save_file(self, evt):
        if not hasattr(self, "pdfDoc"):
            return
        path = self.save_FileDialog()
        if path is None:
            return
        data = []
        for i in range(self.pdfDoc.pageCount):
            page = self.pdfDoc[i]
            row = [self.extract_pdf_text(page, rect)
                   for i, rect in enumerate(self.rects)]
            data.append(row)
        with open(path, "w") as f:
            writer = csv.writer(f, lineterminator="\n")
            row = [f"区域{i}" for i in range(1, len(row) + 1)]
            writer.writerow(row)
            for row in data:
                writer.writerow(row)
        os.system(f"cmd /c start {path}")

    def extract_pdf_text(self, page=None, rect=None):
        if page is None:
            page = self.pdfDoc[self.i]
        if rect is None:
            rect = self.rects[-1]
        a, b, c, d = rect
        clip = fitz.Rect(a, b, a + c, b + d)
        text = page.get_text(clip=clip).strip()
        return text

    def change_img(self, img_path, move=True):
        self.bmp = wx.Bitmap(img_path)
        self.SetSize(self.bmp.GetSize())
        self.parent.SetSize(self.parent.GetBestSize())
        if move:
            self.parent.Center()

    def DoDrawing(self, evt):
        if not hasattr(self, "bmp"):
            return
        dc = wx.ClientDC(self)
        dc.DrawBitmap(self.bmp, 0, 0, True)
        dc.SetPen(wx.Pen('blue'))
        dc.SetBrush(wx.Brush('white', wx.BRUSHSTYLE_TRANSPARENT))
        dc.DrawRectangleList(self.rects)

    def OnLeftButtonEvent(self, event):
        if event.LeftDown():
            self.x, self.y = event.GetPosition()
            self.rects.append([self.x, self.y, 0, 0])
        elif event.Dragging():
            x, y = event.GetPosition()
            self.rects[-1][2] = x - self.x
            self.rects[-1][3] = y - self.y
            self.DoDrawing(-1)
        elif event.LeftUp():
            print(self.rects)
            if self.rects[-1][2] < 5 or self.rects[-1][3] < 5:
                self.rects.pop()
            else:
                self.parent.SetTitle(self.path + "|" + self.extract_pdf_text())

app = wx.App()
frm = wx.Frame(None)
pnl = MyCanvas(frm)
frm.Center()
frm.Show()
frm.SetTitle("PDF文本提取器")
app.MainLoop() 

以上就是基于Python实现PDF区域文本提取工具的详细内容,更多关于Python PDF文本提取的资料请关注我们其它相关文章!

(0)

相关推荐

  • Python提取PDF内容的方法(文本、图像、线条等)

    1.安装PDFminer3k 使用pip 命令安装 pip install pdfminer3k 2.编写测试 你可以在这里获得官方参考:PDFMiner 如果你不喜欢看英文的官方文档,这里的翻译也许对你有帮助:中文PDFMiner文档 下面的程序,我拓展了官方给出的例子,你可以通过这个例子统计出来你的pdf文件一共包含哪些内容,比如文本框,曲线,图片等 #!/usr/bin/python # -*- coding: utf-8 -*- __author__ = 'yooongchun' imp

  • python 三种方法提取pdf中的图片

    有时我们需要将一份或者多份PDF文件中的图片提取出来,如果采取在线的网站实现的话又担心图片泄漏,手动操作又觉得麻烦,其实用Python也可以轻松搞定! 今天就跟大家系统分享几种Python提取 PDF 图片的方法.其实没有非常完美的方法,每种方法提取效率都不是百分之百,因此可以考虑用多种方法进行互补,主要将涉及: 基于 fitz 库和正则搜索提取图片 基于 pdf2image 库的两种方法提取图片 基于 fitz 库和正则搜索 fitz 是 pymupdf 的子模块,需要先用命令行安装 pymu

  • Python 用三行代码提取PDF表格数据

    从 PDF 表格中获取数据是一项痛苦的工作.不久前,一位开发者提供了一个名为 Camelot 的工具,使用三行代码就能从 PDF 文件中提取表格数据. PDF 文件是一种非常常用的文件格式,通常用于正式的电子版文件.它能够很好的将不同的排版格式固定下来,形成版面清晰且美观的展示效果.然而,对于想要从 PDF 中提取信息的人们来说,PDF 是个噩梦,尤其是表格. 大量的学术报告.论文.分析文章都使用 PDF 展示其中的表格数据,但是对于如果想要直接从表格中复制数据则会非常麻烦.不久前,有一位开发者

  • 用Python提取PDF表格的方法

    大家好,从PDF中提取信息是办公场景中经常需要用到的操作,也是经常又读者在后台问的一个操作. 内容少的话我们可以手动复制粘贴,但如果需要批量提取就可以考虑使用Python,之前我也转载过相关文章,提到主要就是使用pdfplumber库,今天我们再次举例讲解. 通常PDF里的表格分为图片型和文本型.文本型又分简单型和复杂型.本文就针对这三部分举例讲解. 提取简单型表格 提取较为复杂型表格 提取图片型表格 用到的模块主要有 pdfplumber pandas Tesseract PIL 文中出现的P

  • Python提取PDF指定内容并生成新文件

    在之前的Python办公自动化案专题中,我们已经介绍了如何有选择的提取某些页面进行合并. 但是很多时候,我们并不会预知希望提取的页号,而是希望将包含指定内容的页面提取合并为新PDF,本文就以两个真实需求为例进行讲解. 01需求描述 数据是一份有286页的上市公司公开年报PDF,大致如下 现在需要利用 Python 完成以下两个需求 " 需求一:提取所有包含 战略 二字的页面并合并新PDF 需求二:提取所有包含图片的页面,并分别保存为 PDF 文件 " 02前置知识和逻辑梳理 2.1 P

  • python实现从pdf文件中提取文本,并自动翻译的方法

    针对Python 3.5.2 测试 首先安装两个包: $ pip install googletrans $ pip install pdfminer3k googletrans会提供一个命令translate,这个命令会调用google translate api执行自动翻译: pdfminer3k会提供一个工具脚本pdf2txt.py: $ pdf2txt.py xxx.pdf 从stackoverflow搜索到可以去除页眉和页脚的命令(强烈推荐): 使用Ubuntu提供的pdftotext

  • Python批量提取PDF文件中文本的脚本

    本文实例为大家分享了Python批量提取PDF文件中文本的具体代码,供大家参考,具体内容如下 首先需要执行命令pip install pdfminer3k来安装处理PDF文件的扩展库. import os import sys import time pdfs = (pdfs for pdfs in os.listdir('.') if pdfs.endswith('.pdf')) for pdf1 in pdfs: pdf = pdf1.replace(' ', '_').replace('-

  • 基于Python实现PDF区域文本提取工具

    目录 功能简介 开发代码 功能简介 打开软件后界面如下: 点击打开文件按钮打开之前的PDF文件后效果如下: 框选区域后,标题栏会自动显示当前框选的区域提取到的文字,还可以左右按钮切换: 实际我们需要提取文字的区域可能不止这一个,所以程序支持多区域框选: 完成区域框选后就可以点击保存文件,将PDF每页提取到的文本保存到一个csv文件中,当前选区的保存结果如下: 可以看到已经按框选顺序依次保存了每一个区域的字符串. 如果选择区域时发现提取结果不准确,可以撤销后重新选择: 保存图片则会将PDF的每页的

  • 基于Python实现图像文字识别OCR工具

    目录 引言 功能列表 OCR部分 界面部分 软件代码 参考链接 引言 最近在技术交流群里聊到一个关于图像文字识别的需求,在工作.生活中常常会用到,比如票据.漫画.扫描件.照片的文本提取. 博主基于 PyQt + PaddleOCR 写了一个桌面端的OCR工具,用于快速实现图片中文本区域自动检测+文本自动识别. 识别效果如下图所示: 所有框选区域为OCR算法自动检测,右侧列表有每个框对应的文字内容: 点击右侧"识别结果"中的文本记录,然后点击"复制到剪贴板"即可复制该

  • Python实现PDF文字识别提取并写入CSV文件

    目录 1.前言 2.需求描述 3.开始动手动脑 3.1安装相关第三方包 3.2导入需要用到的第三方库 3.3读取pdf文件,并识别内容 3.4对识别的数据进行处理,写入csv文件 总结 1. 前言 扫描件一直受大众青睐,任何纸质资料在扫描之后进行存档,想使用时手机就能打开,省心省力.但是扫描件的优点也恰恰造成了它的一个缺点,因为是通过电子设备扫描,所以出来的是图像,如果想要处理文件上的内容,直接操作是无法实现的. 那要是想要引用其中的内容怎么办呢?别担心,Python帮你解决问题. 2. 需求描

  • 基于Python写一个番茄钟小工具

    目录 一.功能简述 二.使用到的主要模块 三.核心模块代码分析 1.番茄钟模块 2.音乐控制函数 3.main中的按钮部分 四.整体代码 一.功能简述 番茄钟即番茄工作法,番茄工作法是简单易行的时间管理工具,使用番茄工作法即一个番茄时间共30分钟,25分钟工作,5分钟休息: 特点一:番茄时长有三档 因为这个工具本人也是考虑到每个人情况不一样,不一定25分钟就适合自己,所以将番茄钟时长设为30min/45min/60min三档,自由选择 特点二:番茄统计功能 特点三:休息期间会自动播放放松音乐,当

  • 如何基于Python制作有道翻译小工具

    这篇文章主要介绍了如何基于Python制作有道翻译小工具,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 该工具主要是利用了爬虫,爬取web有道翻译的内容. 然后利用简易GUI来可视化结果. 首先我们进入有道词典的首页,并点击翻译结果的审查元素 之后request响应网页,并分析网页,定位到翻译结果. 使用tkinter来制作一个建议的GUI 期间遇到的一个问题则是如何刷新翻译的结果,否则的话会在text里一直累加翻译结果. 于是,在mainlo

  • 基于python实现MUI区域滚动

    目录 1.前言 2.问题描述 3.解决方案 4.结语 本文转自微信公众号:"算法与编程之美" Python用HBuilder创建交流社区APP 基于Python实现MUI侧滑菜单a标签跳转 基于Python 优化 MUI标题栏 基于python使MUI登录页面的美化 1.前言 MUI提供了区域滚动的组件,使用时遵循DOM结构就可以.若是需要使用区域滚动的组件,就需要初始化scroll控件.本次在制作页面时关于区域滚动遇到了一些问题将会在下文展开. 2.问题描述 在创建好区域滚动之后不能

  • 基于Python实现傻瓜式GIF制作工具

    目录 导语​ ​一.简单的GIF制作 1)准备中 2)小简介 3)代码演示 二.升级imageio的GIF制作 1)准备中 2)小简介 3)代码演示 三.总效果展示 导语​ ​嘿!大家好,我是木木子!今天给大家带来一个好玩儿的Python小程序,希望大家喜欢,记得点点关注啦~ 有没有什么内容形式,比小视频更小,比普通图片更丰富???? 有! GIF动态图就是其中一种形式,而且,必不可少. GIF动态图应该是早已充斥了互联网,被大家玩得不亦乐乎,大伙早就不能接受文章中的纯文字或 静态图片,这些早已

  • 基于Python制作一个文件去重小工具

    目录 前言 实现步骤 补充 前言 常常在下载网络素材时有很多的重复文件乱七八糟的,于是想实现一个去重的操作. 主要实现思路就是遍历出某个文件夹包括其子文件夹下面的所有文件,最后,将所有文件通过MD5函数的对比筛选出来,最后将重复的文件移除. 实现步骤 用到的第三方库都比较的常见,其中只有hashlib是用来对比文件的不是很常见.其他的都是一些比较常见的第三方库用来做辅助操作. import os # 应用文件操作 import hashlib # 文件对比操作 import logging #

  • Python实现PDF转换文本详解

    目录 一.前言 1.1.为什么不使用传统的pdf 转文本工具呢? 二.实现过程 2.1.基于深度学习的 OCR 将 pdf 为文本 2.1.1.将 pdf 转换为图像 2.1.2.检测和识别图像中的文本 2.1.3.示例输出 总结 一.前言 对很多人来说,将PDF转换为可编辑的文本是个刚需,却苦于没有简单的方法.发现 pdf 幻灯片,效果还不错. 传统的讲座通常伴随有很多pdf幻灯片.一般来说,想要对自己的讲座做笔记,需要从pdf复制.补充大量内容. 最近,来自 K1 Digital 的高级机器

  • 如何基于Python代码实现高精度免费OCR工具

    近期Github开源了一款基于Python开发.名为Textshot的截图工具,刚开源不到半个月已经500+Star. 这两天抽空看了一下Textshot的源码,的确是一个值得介绍的项目. 相对于大多数OCR工具复杂工程.差强人意的效果,Textshot具有明显的优势, 项目简单 技术点丰富 项目简单 Textshot整个项目只有1个Python文件.139行代码,没有复杂的第三方库应用,也不涉及过多后端算法的调用. 技术点丰富 Textshot这个项目虽然只有短短的139行代码,但是,却涉及P

随机推荐