做电商或给小程序商城上架商品时,最繁琐的往往不是写文案,而是处理图片:几十上百张原图尺寸不一、体积过大、格式混乱,平台又要求主图统一为 800×800、详情页宽度固定,还得加上自己的 Logo。手工一张张改既慢又容易出错。
这类高度重复的工作适合交给脚本。本文用 Python 的 Pillow 库,给出一套可直接运行的批量处理方案,覆盖统一尺寸(不变形)、压缩到指定体积、添加水印、多规格导出、格式转换五个常见需求。
环境准备
bash
pip install Pillow
建议使用 9.x 以上版本。下面所有示例基于 Pillow 的 Image 模块。
一、统一主图尺寸:等比缩放 + 白底填充
直接 resize 到 800×800 会把长方形商品图拉变形。正确做法是先等比缩放,再居中贴到正方形白底画布上:
python
from PIL import Image
def fit_square(im, size=800, bg=(255, 255, 255)):
im = im.convert("RGB")
im.thumbnail((size, size), Image.LANCZOS) # 等比缩放,不超过目标尺寸
canvas = Image.new("RGB", (size, size), bg)
x = (size - im.width) // 2
y = (size - im.height) // 2
canvas.paste(im, (x, y))
return canvas
thumbnail 是原地等比缩放,LANCZOS 重采样在缩小时画质较好。需要透明背景的 PNG 场景,可把 bg 换成透明并使用 RGBA 模式。
二、批量压缩并控制体积
商品图过大不仅上传慢,也会拖慢商城页面加载。下面的函数通过循环降低质量,把文件压到目标体积以内,同时设了质量下限避免糊图:
python
import os
def save_under(im, path, limit_kb=300, quality=90):
while quality >= 55:
im.save(path, "JPEG", quality=quality, optimize=True)
if os.path.getsize(path) <= limit_kb * 1024:
return quality
quality -= 10
return quality
照片类用 JPEG;含大量文字、Logo 或需要透明的图用 PNG。两者不要混用:照片存成 PNG 体积会明显变大。
三、添加 Logo 水印
把 Logo 等比缩放到画面宽度的约 18%,贴在右下角并留边距:
python
def add_watermark(base, logo_path, margin=24):
base = base.convert("RGBA")
logo = Image.open(logo_path).convert("RGBA")
logo.thumbnail((int(base.width * 0.18), int(base.height * 0.18)))
layer = Image.new("RGBA", base.size, (0, 0, 0, 0))
x = base.width - logo.width - margin
y = base.height - logo.height - margin
layer.paste(logo, (x, y), logo) # 第三个参数做透明遮罩
return Image.alpha_composite(base, layer).convert("RGB")
四、一次输出多种规格
同一张原图常需同时产出主图、详情页首图、朋友圈图等。用"规格表"驱动,避免为每个尺寸写一遍逻辑:
python
SPECS = {
"main": (800, 800),
"detail": (790, 790),
"feed": (1080, 1080),
}
def export_specs(im, out_dir, name):
for tag, (w, h) in SPECS.items():
out = fit_square(im, max(w, h))
out = out.resize((w, h)) if (w, h) == (h, w) else out
out.save(os.path.join(out_dir, f"{name}_{tag}.jpg"),
"JPEG", quality=85, optimize=True)
五、批量遍历整个目录
把上面的能力串起来,遍历源目录、跳过非图片、按原文件名输出:
python
SRC = "products"
DST = "out"
os.makedirs(DST, exist_ok=True)
for fn in os.listdir(SRC):
if fn.lower().endswith((".jpg", ".jpeg", ".png", ".webp", ".bmp")):
im = Image.open(os.path.join(SRC, fn))
name = os.path.splitext(fn)[0]
main_img = fit_square(im) # 统一主图
# main_img = add_watermark(main_img, "logo.png") # 需要水印时打开
save_under(main_img, os.path.join(DST, name + ".jpg"), limit_kb=300)
print("done:", fn)
图片量很大(上千张)时,可用 concurrent.futures.ThreadPoolExecutor 把每张图的处理放进线程池, Pillow 释放 GIL 的环节能获得一定加速;注意控制并发数避免磁盘 IO 打满。
小结
整个流程的关键是三点:用"等比缩放 + 画布填充"而不是硬拉伸来保证不变形;用质量递减循环把体积压到平台要求内;用规格表 + 目录遍历实现一次配置、批量产出。把脚本保存下来,每次上新直接跑一遍即可,比手工处理稳定得多。
常见问题
电商主图尺寸一般是多少?
淘宝、京东、抖音小店多为 800×800(1:1),拼多多常见 750×750,具体以各平台当年的规则为准。
图片压缩后会不会变模糊?
照片用 JPEG、质量不低于约 75~80 通常肉眼差异很小;文字和 Logo 多的图建议用 PNG,避免出现锯齿。
批量处理时 PNG 透明背景怎么保留?
全程使用 RGBA 模式并导出为 PNG,不要转成 RGB/JPEG,否则透明区域会被填成实色。