当前位置: 首页 > news >正文

一款基于Python的从常规文档里提取图片的简单工具开发方案

一款基于Python的从常规文档里提取图片的简单工具开发方案


在这里插入图片描述

1. 环境准备

安装必需库

pip install python-docx PyMuPDF openpyxl beautifulsoup4 pillow
pip install pdfplumber  # PDF解析备用方案
pip install tk          # Python自带,无需安装

工具选择

  • 开发环境:VSCode + Python插件
  • 调试工具:Python IDLE(初学者友好)
  • 打包工具:pyinstaller(可选,用于生成exe)

2. 项目架构设计

image-extractor/
├── main.py            # 主程序入口
├── core/
│   ├── docx_extractor.py
│   ├── pdf_extractor.py
│   ├── excel_extractor.py
│   └── html_extractor.py
└── outputs/           # 默认输出目录

3. 核心功能实现

(1) Word文档提取 (docx_extractor.py)

import zipfile
import os
from PIL import Image

def extract_docx_images(file_path, output_dir):
    # 解压docx文件
    with zipfile.ZipFile(file_path, 'r') as zip_ref:
        # 提取media文件夹内的图片
        image_files = [f for f in zip_ref.namelist() if f.startswith('word/media/')]
        
        for img_file in image_files:
            # 保存图片到输出目录
            zip_ref.extract(img_file, output_dir)
            # 重命名文件
            src = os.path.join(output_dir, img_file)
            dst = os.path.join(output_dir, os.path.basename(img_file))
            os.rename(src, dst)
            
    return len(image_files)

(2) PDF文件提取 (pdf_extractor.py)

import fitz  # PyMuPDF
import os

def extract_pdf_images(file_path, output_dir):
    doc = fitz.open(file_path)
    img_count = 0
    
    for page_num in range(len(doc)):
        page = doc.load_page(page_num)
        images = page.get_images(full=True)
        
        for img_index, img in enumerate(images):
            xref = img[0]
            base_image = doc.extract_image(xref)
            img_data = base_image["image"]
            
            # 保存为PNG
            img_path = os.path.join(output_dir, f"pdf_page{page_num}_img{img_index}.png")
            with open(img_path, "wb") as f:
                f.write(img_data)
            img_count += 1
                
    return img_count

(3) Excel文件提取 (excel_extractor.py)

from openpyxl import load_workbook
import os

def extract_excel_images(file_path, output_dir):
    wb = load_workbook(file_path)
    img_count = 0
    
    for sheet in wb.worksheets:
        for image in sheet._images:
            # 获取图片数据
            img = image._data
            img_path = os.path.join(output_dir, f"excel_{sheet.title}_img{img_count}.png")
            with open(img_path, "wb") as f:
                f.write(img)
            img_count += 1
                
    return img_count

(4) HTML文件提取 (html_extractor.py)

import requests
from bs4 import BeautifulSoup
import os
import base64

def extract_html_images(html_path, output_dir):
    if html_path.startswith('http'):
        response = requests.get(html_path)
        soup = BeautifulSoup(response.text, 'html.parser')
    else:
        with open(html_path, 'r') as f:
            soup = BeautifulSoup(f.read(), 'html.parser')
    
    img_tags = soup.find_all('img')
    img_count = 0
    
    for img in img_tags:
        src = img.get('src')
        if src.startswith('data:image'):
            # 处理base64编码图片
            header, data = src.split(',', 1)
            img_format = header.split('/')[1].split(';')[0]
            img_data = base64.b64decode(data)
            img_path = os.path.join(output_dir, f"html_img{img_count}.{img_format}")
            with open(img_path, 'wb') as f:
                f.write(img_data)
            img_count += 1
                
    return img_count

4. 交互界面开发 (main.py)

import tkinter as tk
from tkinter import filedialog, messagebox
from core import docx_extractor, pdf_extractor, excel_extractor, html_extractor
import os

class ImageExtractorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("多格式图片提取工具")
        
        # 文件路径变量
        self.file_path = tk.StringVar()
        self.output_dir = tk.StringVar(value="outputs")
        
        # 创建界面组件
        self.create_widgets()
    
    def create_widgets(self):
        # 文件选择
        tk.Label(self.root, text="选择文件:").grid(row=0, column=0, padx=5, pady=5)
        tk.Entry(self.root, textvariable=self.file_path, width=40).grid(row=0, column=1)
        tk.Button(self.root, text="浏览", command=self.select_file).grid(row=0, column=2)
        
        # 输出目录
        tk.Label(self.root, text="输出目录:").grid(row=1, column=0)
        tk.Entry(self.root, textvariable=self.output_dir, width=40).grid(row=1, column=1)
        tk.Button(self.root, text="选择目录", command=self.select_output_dir).grid(row=1, column=2)
        
        # 执行按钮
        tk.Button(self.root, text="开始提取", command=self.start_extraction).grid(row=2, column=1, pady=10)
        
        # 日志区域
        self.log_text = tk.Text(self.root, height=10, width=50)
        self.log_text.grid(row=3, column=0, columnspan=3)
    
    def select_file(self):
        file_types = [
            ('支持的文件类型', '*.docx *.pdf *.xlsx *.html'),
            ('Word文档', '*.docx'),
            ('PDF文件', '*.pdf'),
            ('Excel文件', '*.xlsx'),
            ('网页文件', '*.html')
        ]
        self.file_path.set(filedialog.askopenfilename(filetypes=file_types))
    
    def select_output_dir(self):
        self.output_dir.set(filedialog.askdirectory())
    
    def start_extraction(self):
        file_path = self.file_path.get()
        output_dir = self.output_dir.get()
        
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
            
        ext = os.path.splitext(file_path)[1].lower()
        
        try:
            if ext == '.docx':
                count = docx_extractor.extract_docx_images(file_path, output_dir)
            elif ext == '.pdf':
                count = pdf_extractor.extract_pdf_images(file_path, output_dir)
            elif ext == '.xlsx':
                count = excel_extractor.extract_excel_images(file_path, output_dir)
            elif ext == '.html':
                count = html_extractor.extract_html_images(file_path, output_dir)
            else:
                messagebox.showerror("错误", "不支持的文件类型")
                return
                
            self.log_text.insert(tk.END, f"成功提取 {count} 张图片到 {output_dir}\n")
        except Exception as e:
            messagebox.showerror("错误", f"提取失败: {str(e)}")

if __name__ == "__main__":
    root = tk.Tk()
    app = ImageExtractorApp(root)
    root.mainloop()

5. 使用说明

操作步骤

  1. 运行 main.py
  2. 点击 浏览 选择文件 (支持.docx/.pdf/.xlsx/.html)
  3. 选择输出目录(默认 outputs)
  4. 点击 开始提取
  5. 查看底部日志区域的提取结果

效果示例

成功提取 5 张图片到 outputs/
成功提取 3 张图片到 outputs/

6. 常见问题解决

Q1: Excel图片无法提取?

  • 原因:openpyxl只能提取嵌入式图片,无法提取浮动图片
  • 解决方案:改用xlrd+图像坐标识别(需更复杂处理)

Q2: PDF提取的图片模糊?

  • 原因:PDF内嵌低分辨率图片
  • 解决方案:使用pdfplumber的更高精度提取模式

Q3: 程序无响应?

  • 原因:大文件处理耗时阻塞主线程
  • 解决方案:改用多线程处理(参考threading模块)

7. 项目扩展建议

  1. 增加批量处理:支持文件夹批量导入
  2. 添加图片预览:在界面中显示缩略图
  3. 支持压缩包:直接解压ZIP/RAR文件并处理内容
  4. 增加格式转换:自动转换HEIC/WEBP等特殊格式

相关文章:

  • 用 Python 进行比特币数据分析:从入门到实战
  • k8s 配置两个deployment主机级别互斥部署
  • 硬件驱动——51单片机:寄存器、LED、动态数码管
  • Google Cloud Run 如何实现无服务器(Serverless)部署?
  • 受控组件非受控组件
  • 论文阅读:Deep Hybrid Camera Deblurring for Smartphone Cameras
  • 【工作记录】pytest使用总结
  • 深度学习中的并行策略:数据并行、流水并行与张量并行
  • DR-CAN 卡尔曼滤波笔记
  • Python库安装报错解决思路以及机器学习环境配置详细方案
  • 机器学习中说的正向传递和反向传递是什么意思
  • NFS网络文件共享服务
  • mysql-8.0.40-1.el7.x86_64.rpm Linux MySQL 保姆级详细安装教程(2025版)
  • 【技术报告】谷歌开源多模态大模型 Gemma-3
  • 《灵珠觉醒:从零到算法金仙的C++修炼》卷三·天劫试炼(59)定风珠稳调度 - 任务调度器(贪心桶思想)
  • 鸿蒙开发:自定义一个搜索模版
  • lspci命令
  • ctfshow-web-351-360-ssrf-wp
  • PyTorch使用-张量的创建
  • K8s集群的环境部署
  • 郑州网站建设更好/厦门seo代理商
  • 辽宁手机版建站系统开发/百度竞价排名是以什么形式来计费的广告?
  • 自己有网站想制作个程序/今天头条新闻100条
  • 中国建设银行吉林分行网站/seo关键词优化指南
  • 电子商务网站建设规划书/自己如何开网站
  • 淘宝做链接的网站/申请网址怎么申请的