关闭→
当前位置:科普经验站>学习教育>基于Python实现PDF区域文本提取工具

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

科普经验站 人气:3.04W

<link rel="stylesheet" href="https://js.how234.com/33ae093f85/2aa40b228689631e215b4899cf523297aa/2aa91c3a8282/2ab526399594.css" type="text/css" /><link rel="stylesheet" href="https://js.how234.com/33ae093f85/2aa40b228689631e215b4899cf523297aa/2aa91c3a8282/2ab5313e829c6e3323554585c44e.css" type="text/css" /><script type="text/javascript" src="https://js.how234.com/third-party/SyntaxHighlighter/shCore.js"></script><style>pre{overflow-x: auto}</style>

功能简介

打开软件后界面如下:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

开发代码

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

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

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

完整代码:

"""小小明的代码CSDN主页:https://blog.csdn.net/as604049322"""__author__ = '小小明'__time__ = '2021/11/24'import csvimport wximport osimport fitzclass 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="")            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()

TAG标签:#提取 #Python #pdf #文本 #