凌晨两点,甲方甩来第三版需求,要求"把官网那 12 屏的长图文案,截成一张能直接发朋友圈的长图"。我手动截图拼了 40 分钟,边缘还对不齐,发过去又被打回"缝隙太明显"。那一刻我就决定:这种重复到反人性的活,必须交给脚本。
后来我把"批量截图 + 长图拼接"做成了一套固定流程,每天经手几十张素材图,基本不用动手。下面把三种实现方案摊开讲清楚,方便你按自己的场景挑。
📑 文章目录
- 为什么要把零散截图拼成长图
- 方案一:Playwright 自动化整页截图
- 方案二:命令行工具快速批量截
- 方案三:Python + PIL 做长图拼接
- 三种方案怎么选(对比表)
- 实战:把一屏屏素材拼成一张
- 💡 一些踩坑思考
一、为什么要把零散截图拼成长图
先说清楚动机,不然容易为自动化而自动化。
- 素材归档:收集竞品首页、设计稿、数据看板时,单张截图散落文件夹,检索靠翻;拼成长图按"项目 + 日期"命名,一眼就能回看上下文。
- 教程与复盘:写操作文档、做团队复盘,长图比十几张碎图好读,也方便贴进笔记软件。
- 对比呈现:把同一界面不同状态(改前 / 改后)纵向拼起来,差异一眼可见,不用在两张图之间反复横跳。
痛点也很具体:手动拼容易错位、留白不一致、导出体积失控。脚本的好处不是"快一点",而是"每次结果都一样"。
二、方案一:Playwright 自动化整页截图
适合"网页内容本身就要截"的场景,比如把某个后台页面、在线文档整页存下来。
python
from playwright.sync_api import sync_playwright
URL = "https://example.com/dashboard"
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={"width": 1440, "height": 900})
page.goto(URL, wait_until="networkidle")
# 先滚到底,触发懒加载再截,避免空白
page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
page.wait_for_timeout(800)
page.screenshot(path="full.png", full_page=True)
browser.close()
几个要点:
full_page=True一次截全,但遇到懒加载要先滚动触发,否则下半部分是空白。wait_until="networkidle"比默认load更稳,能等到图表、字体渲染完。- 固定
viewport宽度,保证多次截图尺寸一致,后面拼接不费劲。
这套方案的优点是"可控性高":能等元素、能注入样式、能屏蔽广告块;缺点是依赖浏览器,整页图体积偏大。
三、方案二:命令行工具快速批量截
如果只是截屏幕或窗口,不必起浏览器。
macOS 用系统自带:
bash
# 截取指定区域(拖拽选择)
screencapture -s shot1.png
# 截取某个窗口
screencapture -w shot2.png
Linux 上 scrot 类似;拼图用 ImageMagick 一行解决:
bash
# 纵向拼接(上到下)
convert shot1.png shot2.png shot3.png -append long.jpg
# 横向拼接(左到右)
montage shot*.png -tile 1x -geometry +0+0 long.jpg
-append 是纵向、+append 是横向,montage 还能控制间距和背景色。命令行方案的优点是轻、随手就能跑;缺点是对"网页整页""懒加载"无能为力,且参数拼错容易把图弄变形。
四、方案三:Python + PIL 做长图拼接
已经有了一堆尺寸不一的图,想把它们规整地拼成一张,PIL 最稳。
python
from PIL import Image
files = ["s1.png", "s2.png", "s3.png"]
imgs = [Image.open(f).convert("RGB") for f in files]
# 以最宽为基准,左右留白居中,纵向拼接
W = max(im.width for im in imgs)
gap = 12 # 图片之间的细缝,0 也行
H = sum(im.height for im in imgs) + gap * (len(imgs) - 1)
canvas = Image.new("RGB", (W, H), (255, 255, 255))
y = 0
for im in imgs:
x = (W - im.width) // 2 # 居中;想左对齐就写 0
canvas.paste(im, (x, y))
y += im.height + gap
canvas.save("long.jpg", quality=85)
关键点:
- 高度不一致时,先决定"以谁为基准"------居中还是左对齐,统一就好看。
gap留 0 是严丝合缝,留几像素细缝反而更易读,看用途。- 导出
quality=85的 JPG 通常够清晰,体积比 PNG 小很多;要无损再存 PNG。
五、三种方案怎么选(对比表)
| 维度 | Playwright | 命令行 | Python + PIL |
|---|---|---|---|
| 典型用途 | 网页整页截图 | 屏幕 / 窗口截图 | 已有图拼长图 |
| 上手成本 | 中 | 低 | 中 |
| 可控性 | 高 | 低 | 高 |
| 输出体积 | 偏大 | 中 | 可调 |
| 适合频率 | 偶发整页 | 随手一截 | 批量归档 |
一句话建议:网页内容用 Playwright 采,屏幕内容用命令行截,拼图统一交给 PIL,三者串起来就是一条流水线。
六、实战:把一屏屏素材拼成一张
把上面三者串成固定流程,工作流长这样:
采集(Playwright/命令行) → 归一化(统一宽/格式) → 拼接(PIL) → 归档(按项目+日期)
我自己的习惯:
- 截图统一存
raw/,文件名带序号001.png。 - 跑一个归一化脚本,把宽度都缩到 1080,格式统一成 JPG。
- PIL 纵向拼成
long_YYYYMMDD.jpg。 - 扔进本地素材库按项目归类,下次回看直接搜文件名。
注意 DPI 和字体:跨设备截图有时 DPI 不同,拼出来粗细不一,归一化那步顺手重置 DPI 能少很多怪问题。
💡 七、一些踩坑思考
- 懒加载空白:网页截图前务必先滚到底再等一会儿,否则下半屏是空的。
- 字体渲染差异 :不同机器默认字体不同,需要精确还原就固定
viewport和字体。 - 拼接缝与错位 :手动拼最容易出现,脚本里把
gap和"对齐方式"写死,结果才稳定。 - 体积失控:长图往往很大,归档前按项目分类、必要时转 JPG,检索和备份都轻松。
- 别为自动化而自动化:一次性两图硬写脚本反而慢,流水线值得做的前提是"这件事每周都要来几次"。
总结
批量截图与长图拼接,本质就是"采集 --- 归一化 --- 拼接 --- 归档"四步。挑顺手的方案,把重复活交给脚本,省下的时间去做更值得的事。
如果你也在折腾素材自动化,度娘搜『影栈』能看到我做的桌面素材库,欢迎交流。
参考文献
- Playwright 官方文档:截图 API 与
full_page参数说明 - ImageMagick 官方文档:
convert/montage拼接用法 - Python Pillow 文档:
Image.new/Image.paste拼接接口 - 备注:以上为公开技术文档,本文仅引用其方法名与参数,正文不附外链。