使用Python开发一个图片OCR管理和文章下载工具

 更新时间:2025年12月26日 08:56:27   作者:winfredzhang  
在日常工作中,我们经常面临两个零碎但繁琐的需求,一是管理大量的OCR(文字识别)图片素材,二是看到优质的公众号文章,想把里面的图片批量下载下来保存素材,下面我们就来看看如何使用Python将这两个功能整合到一个工具中吧

在日常工作中,我们经常面临两个零碎但繁琐的需求:一是管理大量的OCR(文字识别)图片素材,需要频繁查看、缩放图片并保存识别结果;二是看到优质的公众号文章,想把里面的图片批量下载下来保存素材。

今天,我将通过一个完整的 Python GUI 项目,分享如何使用 wxPython 将这两个功能整合到一个工具中。我们将重点分析如何自定义支持缩放/拖拽的图片控件、实现“智能保存”逻辑以及编写多线程爬虫。

技术栈概览

GUI 框架: wxPython (主要用于界面构建)

图像处理: Pillow (PIL) (用于图片加载和预处理)

网络爬虫: requests + BeautifulSoup4 (用于抓取微信文章)

系统交互: subprocess (调用外部OCR程序), threading (防界面卡死)

架构设计

程序的主体结构采用 wx.Notebook(选项卡)布局,将应用分为两个独立的 Panel:

OCRPanel: 负责图片导入、预览、调用外部OCR工具以及工程文件的保存(JSON格式)。

DownloaderPanel: 负责解析微信文章URL,批量下载图片。

核心亮点一:自定义可缩放、拖拽的图片画布 (ImageCanvas)

在早期的 wxPython 开发中,我们常用 wx.StaticBitmap 显示图片,但它不支持缩放和移动,查看大图细节非常不便。为了解决这个问题,我重写了一个 ImageCanvas 类。

1. 原理分析

这个控件继承自 wx.Panel,核心在于绑定 EVT_PAINT 事件,使用 wx.GraphicsContext 进行高性能绘图。

平移(Pan): 监听 EVT_MOTION 和鼠标点击事件,计算鼠标移动的 dx 和 dy,更新图片的绘制偏移量 offset_x 和 offset_y。

缩放(Zoom): 监听 EVT_MOUSEWHEEL。当滚轮滚动时,更新 self.scale 变量。

2. 代码解析

def on_paint(self, event):
    dc = wx.BufferedPaintDC(self) # 使用双缓冲防止闪烁
    dc.Clear()
    
    if self.image:
        gc = wx.GraphicsContext.Create(dc)
        if gc:
            gc.PushState()
            # 核心变换逻辑:先平移,再缩放
            gc.Translate(self.offset_x, self.offset_y)
            gc.Scale(self.scale, self.scale)
            
            bmp = wx.Bitmap(self.image)
            gc.DrawBitmap(bmp, 0, 0, self.image.GetWidth(), self.image.GetHeight())
            gc.PopState()

这段代码的精髓在于 wx.GraphicsContext,它让我们不需要手动计算每个像素的位置,而是通过矩阵变换(Translate/Scale)轻松实现视图操作。

核心亮点二:工程文件的“智能保存”逻辑

在许多工具软件中,每次点击保存都弹出“另存为”对话框是非常糟糕的体验。我们在 OCRPanel 中实现了类似 Word 的保存逻辑。

1. 状态管理

我们在类中增加了一个变量 self.current_project_file 来记录当前工程是否已经关联了磁盘上的文件。

2. 逻辑流

新建/清空时:将 self.current_project_file 置为 None。

点击保存时:

Case A (已有文件): 如果 current_project_file 存在,直接写入 JSON,不弹窗。

Case B (新文件): 弹出 wx.TextEntryDialog 询问工程名,保存成功后更新 current_project_file。

def on_save_project(self, event):
    # ... 省略数据收集代码 ...

    # 智能判断:是“保存”还是“另存为”
    if self.current_project_file and os.path.exists(self.current_project_file):
        # === 直接保存 ===
        with open(self.current_project_file, 'w', encoding='utf-8') as f:
            json.dump(self.current_project, f, ...)
    else:
        # === 新建工程,询问名称 ===
        dlg = wx.TextEntryDialog(self, "请输入工程名称:", "保存新工程")
        if dlg.ShowModal() == wx.ID_OK:
            # ... 保存并更新 self.current_project_file ...

核心亮点三:健壮的微信文章图片获取

微信公众号文章的图片下载有两个难点:懒加载(Lazy Load)和防盗链参数。

1. 对抗懒加载

微信文章的 HTML 中,真实的图片 URL 通常不在 src 属性中(src 往往是一个占位图),而是藏在 data-src 中。我们的爬虫采用了多重策略提取 URL:

BeautifulSoup 解析: 优先查找 data-src、data-original 等属性。

正则兜底: 如果 HTML 解析遗漏,使用正则表达式 re.findall 直接从源码中暴力匹配 https://mmbiz.qpic.cn/... 格式的链接。

2. URL 清洗

微信图片 URL 往往带有大量的参数(如 tp=webp),直接下载可能导致格式混乱。代码中实现了 clean_image_url 方法,提取基础 URL,并根据 Content-Type 智能判断文件后缀(.jpg, .png, .gif)。

3. 多线程防卡死

GUI 程序最忌讳在主线程进行网络请求。我们在 DownloaderPanel 中使用了 threading:

# 错误做法:直接调用下载函数,界面会卡死直到下载完成
# self.download_images(url, save_path) 

# 正确做法:开启新线程
threading.Thread(target=self.run_download_task, args=(url, save_path)).start()

同时,为了在子线程中安全地更新 UI(如进度条),我们使用了 wx.CallAfter,确保 UI 操作回到主线程执行。

运行结果

到此这篇关于使用Python开发一个图片OCR管理和文章下载工具的文章就介绍到这了,更多相关Python图片OCR管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Pycharm中安装Pygal并使用Pygal模拟掷骰子(推荐)

    Pycharm中安装Pygal并使用Pygal模拟掷骰子(推荐)

    这篇文章主要介绍了Pycharm中安装Pygal并使用Pygal模拟掷骰子,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • Python数据可视化之在Excel中插入图表

    Python数据可视化之在Excel中插入图表

    在数据分析与展示的领域中,Python 凭借其强大的库支持,成为众多开发者与数据工作者的得力助手,今天就带大家深入探索如何利用 Python 在 Excel 中插入图表,实现数据可视化的进阶操作吧
    2025-04-04
  • 使用Python开发一个简单的本地图片服务器

    使用Python开发一个简单的本地图片服务器

    本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的 Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示例代码讲解详细,感兴趣的小伙伴可以尝试一下
    2025-04-04
  • Django Admin 上传文件到七牛云的示例代码

    Django Admin 上传文件到七牛云的示例代码

    这篇文章主要介绍了Django Admin 上传文件到七牛云的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • python代码 if not x: 和 if x is not None: 和 if not x is None:使用介绍

    python代码 if not x: 和 if x is not None: 和 if not x is None:使用

    这篇文章主要介绍了python代码 if not x: 和 if x is not None: 和 if not x is None:使用介绍,需要的朋友可以参考下
    2016-09-09
  • Python 快速把多个元素连接成一个字符串的操作方法

    Python 快速把多个元素连接成一个字符串的操作方法

    join() 方法一个用于将序列中的元素以指定的分隔符连接成一个字符串的方法,这个方法通常用于字符串操作,这篇文章主要介绍了Python 快速把多个元素连接成一个字符串的方法,需要的朋友可以参考下
    2024-06-06
  • python实现自动打卡小程序

    python实现自动打卡小程序

    这篇文章主要为大家详细介绍了python实现自动打卡小程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • Python读取Word文档中的Excel嵌入文件的方法详解

    Python读取Word文档中的Excel嵌入文件的方法详解

    这篇文章主要为大家详细介绍了Python读取Word文档中的Excel嵌入文件的方法,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2022-12-12
  • 简单实例带你了解Python的编译和执行全过程

    简单实例带你了解Python的编译和执行全过程

    python 是一种解释型的编程语言,所以不像编译型语言那样需要显式的编译过程。然而,在 Python 代码执行之前,它需要被解释器转换成字节码,这个过程就是 Python 的编译过程,还不知道的朋友快来看看吧
    2023-04-04
  • python发布模块的步骤分享

    python发布模块的步骤分享

    这篇文章主要介绍了python发布模块的步骤,需要的朋友可以参考下
    2014-02-02

最新评论