我網站就因爲圖片很大,所以打開超級慢。
於是就想到了用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()