- import os
- import sys
- from PIL import Image
- from tqdm import tqdm
- import traceback
- # 配置项(可根据需要修改)
- TARGET_QUALITY = 50 # 压缩质量(1-100,数值越小压缩率越高)
- MAX_WIDTH = 1024 # 最大宽度,超过则等比例缩放
- SUPPORT_FORMATS = ('.jpg', '.jpeg', '.png', '.bmp') # 支持的图片格式
- def compress_image(file_path):
- """
- 处理单张图片:缩放+压缩
- :param file_path: 图片文件的绝对路径
- :return: (是否成功, 原大小/KB, 新大小/KB, 错误信息)
- """
- try:
- # 获取文件原始大小
- original_size = os.path.getsize(file_path) / 1024 # 转KB
- # 打开图片(处理PNG透明通道问题)
- with Image.open(file_path) as img:
- # 1. 处理尺寸:宽度超过MAX_WIDTH则等比例缩放
- width, height = img.size
- if width > MAX_WIDTH:
- ratio = MAX_WIDTH / width
- new_height = int(height * ratio)
- # 缩放图片(保留原图质量的缩放算法)
- img = img.resize((MAX_WIDTH, new_height), Image.Resampling.LANCZOS)
- # 2. 处理压缩并保存(覆盖原文件,保持原格式)
- # 区分JPEG和PNG/BMP的保存参数
- file_ext = os.path.splitext(file_path)[1].lower()
- save_kwargs = {}
- if file_ext in ('.jpg', '.jpeg'):
- # JPEG压缩:设置质量,关闭渐进式(加快加载)
- save_kwargs['quality'] = TARGET_QUALITY
- save_kwargs['optimize'] = True
- save_kwargs['progressive'] = False
- elif file_ext == '.png':
- # PNG压缩:优化压缩
- save_kwargs['optimize'] = True
- elif file_ext == '.bmp':
- # BMP无质量参数,仅缩放
- pass
- # 保存图片(覆盖原文件)
- img.save(file_path, **save_kwargs)
- # 获取处理后文件大小
- new_size = os.path.getsize(file_path) / 1024
- return (True, original_size, new_size, "")
-
- except Exception as e:
- # 捕获异常并返回错误信息
- error_info = traceback.format_exc()[:200] # 截取前200字符,避免信息过长
- return (False, 0, 0, error_info)
- def batch_compress(root_dir):
- """
- 批量处理指定目录下的所有图片(递归遍历子目录)
- :param root_dir: 目标根目录
- """
- # 第一步:收集所有符合条件的图片文件路径
- image_files = []
- for root, dirs, files in os.walk(root_dir):
- for file in files:
- file_ext = os.path.splitext(file)[1].lower()
- if file_ext in SUPPORT_FORMATS:
- file_path = os.path.join(root, file)
- image_files.append(file_path)
-
- if not image_files:
- print(f"⚠️ 在目录 {root_dir} 下未找到任何支持的图片文件({SUPPORT_FORMATS})")
- return
- # 第二步:批量处理图片,显示进度条
- success_count = 0
- fail_count = 0
- total_original_size = 0 # 总原始大小(KB)
- total_new_size = 0 # 总处理后大小(KB)
- print(f"\n📌 共发现 {len(image_files)} 张待处理图片,开始批量压缩...\n")
- # 进度条配置:显示当前文件、进度、速度
- pbar = tqdm(image_files, desc="处理进度", unit="张", ncols=100)
- for file_path in pbar:
- # 更新进度条的当前文件提示
- pbar.set_postfix(file=os.path.basename(file_path))
-
- # 处理单张图片
- success, ori_size, new_size, error = compress_image(file_path)
-
- # 统计数据
- if success:
- success_count += 1
- total_original_size += ori_size
- total_new_size += new_size
- else:
- fail_count += 1
- # 失败时在进度条后标注错误
- tqdm.write(f"❌ 处理失败 {file_path}:{error}")
-
- # 第三步:输出统计结果
- pbar.close()
- print(f"\n✅ 处理完成!")
- print(f" 成功:{success_count} 张 | 失败:{fail_count} 张")
- print(f" 原始总大小:{total_original_size:.2f} KB | 压缩后总大小:{total_new_size:.2f} KB")
- if total_original_size > 0:
- compression_rate = (1 - total_new_size / total_original_size) * 100
- print(f" 整体压缩率:{compression_rate:.2f}%")
- if __name__ == "__main__":
- # 检查命令行参数:需要传入目标目录路径
- if len(sys.argv) != 2:
- print("🔧 使用方法:python image_compress.py 目标目录路径")
- print(" 示例:python image_compress.py /www/wwwroot/your_site/images")
- sys.exit(1)
-
- target_dir = sys.argv[1]
- # 验证目录是否存在
- if not os.path.isdir(target_dir):
- print(f"❌ 错误:目录 {target_dir} 不存在!")
- sys.exit(1)
-
- # 开始批量处理
- batch_compress(target_dir)
复制代码
使用说明:
打开宝塔的「终端」(或通过 SSH 连接服务器),执行以下命令安装依赖库:
pip install pillow tqdm
执行脚本:
执行以下命令(替换为你的图片目录路径):
# 示例:处理 /www/wwwroot/你的网站域名/images 目录下的所有图片
python /www/image_compress.py /www/wwwroot/your_site/images
|