设计实践

用 Adobe Express 的批量创建(Bulk create)一次生成整套商品促销图

用 Adobe Express 的批量创建(Bulk create)一次生成整套商品促销图:Python 脚本先把商品表算好折后价、查出超长标题和错误折扣,再导入 Express 自动套模板,每张图对应一个商品。

BINBHO · 图文教程

用 Adobe Express 的批量创建(Bulk create)一次生成整套商品促销图:Python 脚本先把商品表算好折后价、查出超长标题和错误折扣,再导入 Express 自动套模板,每张图对应一个商品。

先看清成品

prep_promo.py 已在本机运行,3 个测试通过(含 500 行自动拆成 249/249/2 三批),样例商品表输出 3 行、4 个问题。本文环境没有登录 Adobe 账号,Express 中的批量创建没有实际执行,步骤按 Adobe 帮助中心编写。

注意:只使用你有权使用的照片、音乐、字体和标志。Adobe Stock 素材与 Firefly 生成内容的商用范围以 Adobe 条款和产品内标注为准(标为 beta 的生成功能可能只限个人用途)。不要共享账号,也不要用代理或改地区的方式绕过 Adobe 的服务地区限制。

价格提示:促销图上的原价、折后价必须真实,符合当地广告和价格标示规定。脚本只做计算,不替你决定价格。

做完之后你会得到什么?

成果 说明
一个促销图模板 标题、原价、到手价、立省、商品图五个可替换元素
整理好的 CSV 价格统一两位小数,每批不超过 249 行
问题清单 超长标题、错误折扣、重复 SKU、缺图片
一批成图 每行一页,可整体下载

需要准备哪些环境?

项目 要求 说明
Adobe Express 网页版 批量创建单次最多 249 个变体
商品表 CSV,UTF-8 列:SKU、标题、原价、折扣、图片
商品图 JPG/PNG 等 图片在 Express 里逐页上传,CSV 里只记文件名方便对照
Python 3.9 以上 标准库即可

另有一个“Bulk Create and Generate”加载项,最多 99 个变体,且必须用它下载的 CSV 模板。本文用的是编辑器自带的 Edit page → Bulk create。

文件结构

18-adobe-express-B-src/
├── prep_promo.py        # 整理商品表
├── test_prep_promo.py   # 3 个测试
└── 商品表.csv            # 样例(故意含错误)

第 1 步:做模板

  1. 新建 1080×1080 方形设计。
  2. 放五个元素:商品图、标题文本框、原价(加删除线)、到手价(大号)、“省 X 元”角标。
  3. 文本框先填最长的示例内容(如 14 个汉字的标题),确认不会溢出。

检查结果:模板里每个要替换的元素都是独立图层。

第 2 步:准备商品表

SKU,标题,原价,折扣,图片
A01,冷萃咖啡液 12 颗装,59.9,0.8,coffee.jpg
A02,挂耳咖啡 精品拼配 30 包超值家庭装,89,0.75,drip.jpg
A03,手冲壶 600ml,129,1.2,kettle.jpg
A01,冷萃咖啡液 12 颗装,59.9,0.8,coffee.jpg
A04,咖啡滤纸 100 张,15,0.9,

折扣用小数:0.8 表示八折。

第 3 步:运行整理脚本

prep_promo.py:

"""把商品表整理成 Adobe Express 批量创建(Bulk create)可用的 CSV。
- 单次最多 249 个变体,超出自动分批
- 计算折后价与“省 X 元”,价格保留两位小数,不做四舍五入以外的改写
- 标题超长、缺图片文件名、折扣不合理时报问题
"""
import csv, sys
from decimal import Decimal, ROUND_HALF_UP
from pathlib import Path

MAX_ROWS = 249
TITLE_MAX = 14  # 按全角宽度计

def width(s): return sum(1 if ord(c) > 127 else 0.5 for c in s)
def money(d): return str(d.quantize(Decimal("0.01"), ROUND_HALF_UP))

def prepare(rows):
    out, problems, seen = [], [], set()
    for i, r in enumerate(rows, start=2):
        sku = r["SKU"].strip()
        if sku in seen: problems.append(f"第{i}行 SKU {sku} 重复,已跳过"); continue
        seen.add(sku)
        try:
            price = Decimal(r["原价"]); off = Decimal(r["折扣"])
        except Exception:
            problems.append(f"第{i}行 价格或折扣不是数字"); continue
        if not (Decimal("0") < off < Decimal("1")):
            problems.append(f"第{i}行 折扣 {off} 应在 0~1 之间(如 0.8 表示八折)"); continue
        title = r["标题"].strip()
        if width(title) > TITLE_MAX: problems.append(f"第{i}行 标题宽度 {width(title)} 超过 {TITLE_MAX}")
        if not r.get("图片", "").strip(): problems.append(f"第{i}行 缺图片文件名")
        sale = (price * off)
        out.append({"标题": title, "原价": "¥" + money(price), "到手价": "¥" + money(sale),
                    "立省": f"省{money(price - sale)}元", "图片": r.get("图片", "").strip()})
    return out, problems

def main(src, outdir="out"):
    with open(src, encoding="utf-8-sig", newline="") as f:
        rows, problems = prepare(list(csv.DictReader(f)))
    Path(outdir).mkdir(exist_ok=True)
    for b in range(0, len(rows), MAX_ROWS):
        p = Path(outdir) / f"bulk_{b // MAX_ROWS + 1:02d}.csv"
        with open(p, "w", encoding="utf-8-sig", newline="") as f:
            w = csv.DictWriter(f, fieldnames=list(rows[0])); w.writeheader(); w.writerows(rows[b:b + MAX_ROWS])
        print(f"写出 {p}:{len(rows[b:b + MAX_ROWS])} 行")
    for p in problems: print("⚠", p)
    return 1 if problems else 0

if __name__ == "__main__":
    sys.exit(main(*sys.argv[1:]))
python3 prep_promo.py 商品表.csv

样例的实际输出:

写出 out/bulk_01.csv:3 行
⚠ 第3行 标题宽度 16.5 超过 14
⚠ 第4行 折扣 1.2 应在 0~1 之间(如 0.8 表示八折)
⚠ 第5行 SKU A01 重复,已跳过
⚠ 第6行 缺图片文件名

out/bulk_01.csv 内容:

标题,原价,到手价,立省,图片
冷萃咖啡液 12 颗装,¥59.90,¥47.92,省11.98元,coffee.jpg
挂耳咖啡 精品拼配 30 包超值家庭装,¥89.00,¥66.75,省22.25元,drip.jpg
咖啡滤纸 100 张,¥15.00,¥13.50,省1.50元,

标题超长的行仍会写出(提醒你改),折扣错误和重复的行会被跳过。改完源表再跑,直到没有 ⚠。测试:python3 -m pytest -q → 3 passed。

第 4 步:在 Express 里批量创建

  1. 打开模板,点 Edit page(编辑页面)→ Bulk create。
  2. 上传 out/bulk_01.csv。
  3. 选中标题文本框 → Connect Element,在 Choose Column 下拉里选“标题”;原价、到手价、立省同理。
  4. 选中商品图 → Connect Element,并改名为“商品图”方便后面识别。
  5. 点 Next,在 Manage & preview 里对照 CSV 的“图片”列,为每一页上传对应商品图。
  6. 点 Create pages。

检查结果:生成的页数等于 CSV 行数;随机抽 3 页,价格与 CSV 一致。

第 5 步:抽检并导出

  • 逐页看标题是否溢出、到手价是否和角标一致。
  • 有 out/bulk_02.csv 时,在模板副本里重复第 4 步。
  • 下载为 PNG(多页会打包)。

出错了怎么办?

现象 原因 解决
中文变成乱码 CSV 编码不对 脚本输出的是带 BOM 的 UTF-8;用 Excel 另存时选“CSV UTF-8”
下拉里找不到列名 表头有空格或改过名 用脚本输出的文件,不要手改表头
超过 249 页报错 单次上限 249 用脚本拆出的分批文件
图片张冠李戴 上传时顺序错 按 Manage & preview 的行号对照“图片”列
价格差 1 分钱 自己算时四舍五入方式不同 统一用脚本的 ROUND_HALF_UP 结果

模板规则

  • 价格只在源表里改,脚本算,模板不手填。
  • 每批 ≤ 249 行,标题 ≤ 14 个汉字宽度。
  • 导出前抽检至少 3 页。

项目资源

用途 地址
Bulk create 帮助(249 个变体) https://helpx.adobe.com/express/web/bulk-create-and-automate/bulk-create.html
Bulk Create and Generate 加载项(99 个变体) https://helpx.adobe.com/express/web/bulk-create-and-automate/bulk-create-generate.html
价格与计划 https://www.adobe.com/express/pricing
Python csv 模块 https://docs.python.org/3/library/csv.html
Python decimal 模块 https://docs.python.org/3/library/decimal.html

链接说明:helpx.adobe.com 对命令行 curl 返回 403(反爬),通过搜索工具读取到了页面正文,地址有效。

批量出图最怕的不是排版,而是价格错。把计算和检查放在脚本里,Express 只负责套版,几百张图也能放心发出去。