python批量压缩网站图片,给网站实现瘦身!

我网站就因为图片很大,所以打开超级慢。

于是就想到了用python来压缩图片。

png压缩成webp格式,直接瘦身88%!

20260730211430809-image

压缩率很高,但却很清晰,1.4G的png直接压缩到120M,而且很高清,请问还有谁?!

Python 脚本的功能:

  1. 递归遍历 uploads 目录下的所有文件。

  2. 跳过 小于等于 300KB 的文件。

  3. 检测真实图片格式(通过文件头,而非扩展名),如果已经是 WebP 格式则跳过。

  4. 将 PNG、JPG、JPEG、BMP、TIFF 等图片压缩为 WebP,质量设为 85(可调)。

  5. 保持原文件名和扩展名不变(例如 example.png 仍为 example.png,但内容是 WebP)。

  6. 备份原文件 到指定的备份目录(保留完整相对路径)。

  7. 跳过非图片文件(如 .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
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容