
在实际工作中我们经常会遇到需要批量处理图片或PDF文档的场景。无论是产品图片统一尺寸、添加水印还是将多个PDF合并、拆分或转换格式手动操作不仅效率低下还容易出错。虽然Photoshop等专业工具提供了批量处理功能但对于非设计人员来说学习成本较高且需要付费使用。本文将介绍如何使用Python和开源工具构建一套完整的图片批量处理和PDF处理流程实现从图片预处理到PDF生成的全自动化。这套方案特别适合需要定期处理大量图片和文档的运营人员、内容创作者和办公人员无需编程基础也能快速上手。1. 环境准备与工具选择1.1 核心工具介绍图片批量处理主要使用Pillow库这是Python图像处理的标准库支持多种图像格式的读写和基本操作。PDF处理使用PyPDF2和reportlab库前者用于PDF的拆分、合并等操作后者用于将图片转换为PDF。对于更复杂的PDF处理需求还可以考虑pdfplumber库它能够提取PDF中的文本、表格等结构化信息。如果需要进行OCR识别可以集成pytesseract库。1.2 环境配置步骤首先确保系统已安装Python 3.7及以上版本。然后通过pip安装所需依赖pip install Pillow PyPDF2 reportlab pdfplumber pytesseract如果是Windows系统还需要安装Tesseract OCR引擎# 通过chocolatey安装 choco install tesseract # 或手动下载安装包 # 下载地址https://github.com/UB-Mannheim/tesseract/wikiLinux系统可以通过包管理器安装# Ubuntu/Debian sudo apt-get install tesseract-ocr # CentOS/RHEL sudo yum install tesseract1.3 项目目录结构建议按以下结构组织项目文件image-pdf-processor/ ├── src/ │ ├── image_processor.py # 图片处理核心模块 │ ├── pdf_processor.py # PDF处理核心模块 │ └── utils.py # 工具函数 ├── input/ # 输入文件目录 │ ├── images/ # 待处理图片 │ └── pdfs/ # 待处理PDF ├── output/ # 输出文件目录 ├── config/ # 配置文件目录 └── requirements.txt # 依赖列表2. 图片批量处理实现2.1 基本图片操作函数首先实现图片处理的基础功能包括尺寸调整、格式转换、水印添加等from PIL import Image, ImageDraw, ImageFont import os class ImageProcessor: def __init__(self, input_dir, output_dir): self.input_dir input_dir self.output_dir output_dir os.makedirs(output_dir, exist_okTrue) def resize_images(self, target_size(800, 600), keep_aspectTrue): 批量调整图片尺寸 for filename in os.listdir(self.input_dir): if filename.lower().endswith((.png, .jpg, .jpeg)): input_path os.path.join(self.input_dir, filename) output_path os.path.join(self.output_dir, filename) with Image.open(input_path) as img: if keep_aspect: img.thumbnail(target_size, Image.Resampling.LANCZOS) else: img img.resize(target_size, Image.Resampling.LANCZOS) img.save(output_path) print(f已处理: {filename}) def convert_format(self, target_formatJPEG, quality85): 批量转换图片格式 for filename in os.listdir(self.input_dir): if filename.lower().endswith((.png, .jpg, .jpeg, .bmp)): input_path os.path.join(self.input_dir, filename) name_without_ext os.path.splitext(filename)[0] output_filename f{name_without_ext}.{target_format.lower()} output_path os.path.join(self.output_dir, output_filename) with Image.open(input_path) as img: if img.mode in (RGBA, P): img img.convert(RGB) img.save(output_path, formattarget_format, qualityquality) print(f已转换: {filename} - {output_filename})2.2 高级图片处理功能除了基本操作还可以实现更复杂的功能如批量添加水印、图片压缩优化等def add_watermark(self, watermark_text, font_size36, opacity128): 批量添加文字水印 try: font ImageFont.truetype(arial.ttf, font_size) except: font ImageFont.load_default() for filename in os.listdir(self.input_dir): if filename.lower().endswith((.png, .jpg, .jpeg)): input_path os.path.join(self.input_dir, filename) output_path os.path.join(self.output_dir, filename) with Image.open(input_path) as img: # 创建水印层 watermark Image.new(RGBA, img.size, (0, 0, 0, 0)) draw ImageDraw.Draw(watermark) # 计算水印位置右下角 bbox draw.textbbox((0, 0), watermark_text, fontfont) text_width bbox[2] - bbox[0] text_height bbox[3] - bbox[1] position (img.width - text_width - 20, img.height - text_height - 20) # 绘制水印 draw.text(position, watermark_text, fontfont, fill(255, 255, 255, opacity)) # 合并图片和水印 if img.mode ! RGBA: img img.convert(RGBA) result Image.alpha_composite(img, watermark) if output_path.lower().endswith(.jpg) or output_path.lower().endswith(.jpeg): result result.convert(RGB) result.save(output_path) print(f已添加水印: {filename}) def optimize_images(self, quality85, optimizeTrue): 批量优化图片质量 for filename in os.listdir(self.input_dir): if filename.lower().endswith((.png, .jpg, .jpeg)): input_path os.path.join(self.input_dir, filename) output_path os.path.join(self.output_dir, filename) with Image.open(input_path) as img: # 转换为RGB模式JPEG不支持透明度 if img.mode in (RGBA, P): img img.convert(RGB) save_kwargs {quality: quality, optimize: optimize} if filename.lower().endswith(.png): # PNG优化参数 img.save(output_path, optimizeoptimize) else: # JPEG优化参数 img.save(output_path, **save_kwargs) original_size os.path.getsize(input_path) new_size os.path.getsize(output_path) reduction (original_size - new_size) / original_size * 100 print(f优化完成: {filename} - 大小减少: {reduction:.1f}%)3. PDF处理功能实现3.1 PDF基本操作PDF处理主要包括合并、拆分、旋转页面等基础功能import PyPDF2 from reportlab.lib.pagesizes import letter, A4 from reportlab.pdfgen import canvas import io class PDFProcessor: def __init__(self, input_dir, output_dir): self.input_dir input_dir self.output_dir output_dir os.makedirs(output_dir, exist_okTrue) def merge_pdfs(self, output_filenamemerged.pdf): 合并多个PDF文件 merger PyPDF2.PdfMerger() pdf_files [f for f in os.listdir(self.input_dir) if f.lower().endswith(.pdf)] pdf_files.sort() # 按文件名排序 for pdf_file in pdf_files: pdf_path os.path.join(self.input_dir, pdf_file) merger.append(pdf_path) print(f已添加: {pdf_file}) output_path os.path.join(self.output_dir, output_filename) with open(output_path, wb) as output_file: merger.write(output_file) merger.close() print(fPDF合并完成: {output_filename}) def split_pdf(self, filename, pages_per_split1): 按页拆分PDF文件 input_path os.path.join(self.input_dir, filename) with open(input_path, rb) as file: pdf_reader PyPDF2.PdfReader(file) total_pages len(pdf_reader.pages) for start_page in range(0, total_pages, pages_per_split): end_page min(start_page pages_per_split, total_pages) pdf_writer PyPDF2.PdfWriter() for page_num in range(start_page, end_page): pdf_writer.add_page(pdf_reader.pages[page_num]) output_filename f{os.path.splitext(filename)[0]}_pages_{start_page1}-{end_page}.pdf output_path os.path.join(self.output_dir, output_filename) with open(output_path, wb) as output_file: pdf_writer.write(output_file) print(f已生成: {output_filename})3.2 图片转PDF功能将处理好的图片批量转换为PDF文档def images_to_pdf(self, pdf_filenameimages.pdf, page_sizeA4): 将图片批量转换为PDF image_files [f for f in os.listdir(self.input_dir) if f.lower().endswith((.png, .jpg, .jpeg))] image_files.sort() if not image_files: print(未找到图片文件) return output_path os.path.join(self.output_dir, pdf_filename) # 创建PDF c canvas.Canvas(output_path, pagesizepage_size) page_width, page_height page_size for image_file in image_files: image_path os.path.join(self.input_dir, image_file) try: with Image.open(image_path) as img: # 计算图片在页面中的合适尺寸 img_width, img_height img.size scale min((page_width - 100) / img_width, (page_height - 100) / img_height) new_width img_width * scale new_height img_height * scale # 居中显示 x (page_width - new_width) / 2 y (page_height - new_height) / 2 # 添加新页面并绘制图片 c.showPage() c.drawImage(image_path, x, y, new_width, new_height) print(f已添加图片: {image_file}) except Exception as e: print(f处理图片 {image_file} 时出错: {e}) c.save() print(fPDF生成完成: {pdf_filename}) def extract_images_from_pdf(self, pdf_filename): 从PDF中提取图片 import fitz # PyMuPDF input_path os.path.join(self.input_dir, pdf_filename) doc fitz.open(input_path) for page_num in range(len(doc)): page doc.load_page(page_num) image_list page.get_images() for img_index, img in enumerate(image_list): xref img[0] base_image doc.extract_image(xref) image_bytes base_image[image] image_ext base_image[ext] output_filename f{os.path.splitext(pdf_filename)[0]}_page{page_num1}_img{img_index1}.{image_ext} output_path os.path.join(self.output_dir, output_filename) with open(output_path, wb) as image_file: image_file.write(image_bytes) print(f已提取图片: {output_filename}) doc.close()4. 完整工作流整合4.1 配置文件管理使用JSON配置文件来管理处理参数便于重复使用和修改{ image_processing: { input_dir: ./input/images, output_dir: ./output/images, resize: { enabled: true, width: 800, height: 600, keep_aspect: true }, watermark: { enabled: true, text: Confidential, font_size: 36, opacity: 128 }, optimize: { enabled: true, quality: 85 } }, pdf_processing: { input_dir: ./input/pdfs, output_dir: ./output/pdfs, merge_enabled: false, split_enabled: true, pages_per_split: 1 } }4.2 主程序实现创建主程序来协调整个处理流程import json from src.image_processor import ImageProcessor from src.pdf_processor import PDFProcessor class BatchProcessor: def __init__(self, config_fileconfig/settings.json): with open(config_file, r, encodingutf-8) as f: self.config json.load(f) def process_images(self): 执行图片批量处理 img_config self.config[image_processing] processor ImageProcessor(img_config[input_dir], img_config[output_dir]) if img_config[resize][enabled]: size (img_config[resize][width], img_config[resize][height]) processor.resize_images(size, img_config[resize][keep_aspect]) if img_config[watermark][enabled]: watermark_config img_config[watermark] processor.add_watermark( watermark_config[text], watermark_config[font_size], watermark_config[opacity] ) if img_config[optimize][enabled]: processor.optimize_images(img_config[optimize][quality]) def process_pdfs(self): 执行PDF处理 pdf_config self.config[pdf_processing] processor PDFProcessor(pdf_config[input_dir], pdf_config[output_dir]) if pdf_config[merge_enabled]: processor.merge_pdfs() if pdf_config[split_enabled]: pdf_files [f for f in os.listdir(pdf_config[input_dir]) if f.lower().endswith(.pdf)] for pdf_file in pdf_files: processor.split_pdf(pdf_file, pdf_config[pages_per_split]) def run_full_workflow(self): 执行完整工作流 print(开始图片处理...) self.process_images() print(开始PDF处理...) self.process_pdfs() print(所有处理完成) if __name__ __main__: processor BatchProcessor() processor.run_full_workflow()5. 常见问题与解决方案5.1 图片处理常见问题问题1处理大图片时内存不足现象处理高分辨率图片时程序崩溃或报内存错误。解决方案使用流式处理分块读取图片数据from PIL import ImageFile ImageFile.LOAD_TRUNCATED_IMAGES True # 设置最大图像像素限制 Image.MAX_IMAGE_PIXELS None # 或设置一个合理的上限问题2图片格式兼容性问题现象某些特殊格式的图片无法打开或处理。解决方案添加格式验证和异常处理def safe_image_open(image_path): try: with Image.open(image_path) as img: img.verify() # 验证图片完整性 return True except Exception as e: print(f图片 {image_path} 损坏或不支持: {e}) return False5.2 PDF处理常见问题问题1PDF加密无法读取现象处理加密PDF时出现权限错误。解决方案尝试使用空密码或提供密码参数def read_encrypted_pdf(pdf_path, passwordNone): try: with open(pdf_path, rb) as file: pdf_reader PyPDF2.PdfReader(file) if pdf_reader.is_encrypted: if password: pdf_reader.decrypt(password) else: # 尝试空密码 pdf_reader.decrypt() return pdf_reader except Exception as e: print(f读取PDF失败: {e}) return None问题2中文字体显示问题现象生成PDF时中文显示为乱码。解决方案使用支持中文的字体文件from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont # 注册中文字体 pdfmetrics.registerFont(TTFont(SimSun, simsun.ttc)) # 使用中文字体 c.setFont(SimSun, 12)5.3 性能优化建议批量处理优化使用多进程处理大量文件合理设置批处理大小避免内存溢出使用缓存机制减少重复计算内存管理及时关闭文件句柄使用生成器处理大文件定期清理临时文件6. 高级功能扩展6.1 OCR文字识别集成为图片和PDF添加文字识别功能import pytesseract from pdf2image import convert_from_path def extract_text_from_image(image_path, langchi_simeng): 从图片中提取文字 try: text pytesseract.image_to_string(Image.open(image_path), langlang) return text.strip() except Exception as e: print(fOCR识别失败: {e}) return def extract_text_from_pdf(pdf_path, langchi_simeng): 从PDF中提取文字 try: # 将PDF转换为图片 images convert_from_path(pdf_path) all_text for i, image in enumerate(images): text pytesseract.image_to_string(image, langlang) all_text f--- 第 {i1} 页 ---\n{text}\n\n return all_text except Exception as e: print(fPDF文字提取失败: {e}) return 6.2 自动化脚本调度使用计划任务实现定时批量处理Windows任务计划程序# 创建批处理文件 run_processor.bat echo off cd /d C:\path\to\your\project python main.pyLinux crontab# 每天凌晨2点执行 0 2 * * * cd /path/to/your/project python main.py6.3 Web界面集成使用Flask创建简单的Web界面from flask import Flask, request, render_template, send_file import os app Flask(__name__) app.route(/) def index(): return render_template(index.html) app.route(/process, methods[POST]) def process_files(): # 处理上传的文件 uploaded_files request.files.getlist(files) config request.form.to_dict() # 调用处理逻辑 # ... return send_file(output.zip, as_attachmentTrue) if __name__ __main__: app.run(debugTrue)这套图片批量处理和PDF处理方案提供了从基础到高级的完整功能可以根据实际需求灵活配置。对于常规的办公自动化需求使用基础功能即可满足大部分场景。对于更复杂的需求可以通过扩展高级功能来实现定制化处理。在实际项目中建议先从简单的功能开始测试逐步增加复杂度。同时要注意文件备份避免处理过程中造成原始文件损坏。对于生产环境的使用还需要考虑错误日志记录、处理进度监控等运维方面的需求。