我网站就因为图片很大,所以打开超级慢。
于是就想到了用python来压缩图片。
png压缩成webp格式,直接瘦身88%!

压缩率很高,但却很清晰,1.4G的png直接压缩到120M,而且很高清,请问还有谁?!
Python 脚本的功能:
-
递归遍历
uploads目录下的所有文件。 -
跳过 小于等于 300KB 的文件。
-
检测真实图片格式(通过文件头,而非扩展名),如果已经是 WebP 格式则跳过。
-
将 PNG、JPG、JPEG、BMP、TIFF 等图片压缩为 WebP,质量设为 85(可调)。
-
保持原文件名和扩展名不变(例如
example.png仍为example.png,但内容是 WebP)。 -
备份原文件 到指定的备份目录(保留完整相对路径)。
-
跳过非图片文件(如
.zip、.pdf、.txt等)。
python代码:
import os
import shutil
from PIL import Image
# ---------- 配置 ----------
SOURCE_DIR = r"Z:\path\to\your\uploads" # 替换为你的 uploads 目录路径
BACKUP_DIR = r"Z:\path\to\backup\uploads" # 备份目录(原文件移动到这里)
QUALITY = 85 # WebP 压缩质量 (1-100)
SIZE_THRESHOLD = 300 * 1024 # 300KB
# 支持的图片扩展名(即使扩展名不对,也会通过文件头检测)
IMAGE_EXTS = {'.png', '.jpg', '.jpeg', '.bmp', '.tiff', '.tif', '.webp'}
# ---------- 核心函数 ----------
def is_webp(filepath):
"""通过文件头判断是否为 WebP 格式"""
with open(filepath, 'rb') as f:
header = f.read(12)
return header[:4] == b'RIFF' and header[8:12] == b'WEBP'
def compress_to_webp(src_path, dst_path, quality):
"""将图片压缩为 WebP 并保存到 dst_path(保持扩展名不变)"""
with Image.open(src_path) as img:
# 处理透明度:RGBA 保留,其他转 RGB
if img.mode in ('RGBA', 'LA', 'P'):
img = img.convert('RGBA')
else:
img = img.convert('RGB')
# 保存为 WebP,但文件名扩展名不变(浏览器根据文件头识别)
img.save(dst_path, 'WEBP', quality=quality, method=6)
# ---------- 主程序 ----------
def main():
if not os.path.exists(SOURCE_DIR):
print(f"❌ 源目录不存在:{SOURCE_DIR}")
return
os.makedirs(BACKUP_DIR, exist_ok=True)
total_files = 0
processed = 0
skipped_webp = 0
skipped_small = 0
skipped_nonimage = 0
errors = []
for root, dirs, files in os.walk(SOURCE_DIR):
for filename in files:
filepath = os.path.join(root, filename)
total_files += 1
# 1. 检查文件大小
if os.path.getsize(filepath) <= SIZE_THRESHOLD:
skipped_small += 1
continue
# 2. 检查是否为支持的图片格式(扩展名初步过滤)
ext = os.path.splitext(filename)[1].lower()
if ext not in IMAGE_EXTS:
skipped_nonimage += 1
continue
# 3. 真实格式检测(优先检测是否为 WebP)
try:
real_format = Image.open(filepath).format
except Exception:
# 无法打开则跳过
skipped_nonimage += 1
continue
# 如果已经是 WebP,跳过
if real_format == 'WEBP':
skipped_webp += 1
continue
# 4. 准备备份路径(保留相对路径)
rel_path = os.path.relpath(filepath, SOURCE_DIR)
backup_path = os.path.join(BACKUP_DIR, rel_path)
os.makedirs(os.path.dirname(backup_path), exist_ok=True)
# 5. 备份原文件(移动,而非复制,节省空间)
try:
shutil.move(filepath, backup_path)
except Exception as e:
errors.append(f"备份失败 {rel_path}: {e}")
continue
# 6. 压缩并保存到原位置(文件名不变)
try:
compress_to_webp(backup_path, filepath, QUALITY)
processed += 1
old_size = os.path.getsize(backup_path)
new_size = os.path.getsize(filepath)
print(f"✅ {rel_path} {old_size//1024}KB → {new_size//1024}KB ({new_size/old_size*100:.1f}%)")
except Exception as e:
# 压缩失败,尝试恢复原文件
shutil.move(backup_path, filepath)
errors.append(f"压缩失败 {rel_path}: {e}")
continue
# 统计报告
print("\n" + "="*60)
print(f"📊 处理完成!")
print(f" 总文件数:{total_files}")
print(f" 跳过(≤300KB):{skipped_small}")
print(f" 跳过(已是WebP):{skipped_webp}")
print(f" 跳过(非图片):{skipped_nonimage}")
print(f" 成功压缩:{processed}")
if errors:
print(f" 错误数量:{len(errors)}")
for err in errors:
print(f" ⚠️ {err}")
print("="*60)
if __name__ == "__main__":
main()
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END





![表情[aoman]-红穆笔记](https://www.4s5.cn/wp-content/themes/zibll/img/smilies/aoman.gif)



暂无评论内容