Appearance
surreal-pop-collage(超现实波普拼贴 · Gemini 网页端自动生图)
把照片变成超现实波普拼贴画,并通过 nekoro-browser 自动化在 Gemini 网页端完成 「上传原图 → 填提示词 → 发送 → 生成 → 零确认下载 → 归档」的全流程。
本 skill 是工作流型:核心不是"自己画图",而是驱动 Gemini 网页端生图。 生图提示词模板见同目录
prompt_template.md。
0. 触发与适用
触发条件(满足任一即启用本 skill):
- 用户上传照片并要求"超现实波普拼贴 / 不可能巨物海报 / 撞色拼贴 / Gemini 生图"。
- 用户指定处理某个目录(如
originals/)里的照片为波普拼贴风格。 - 用户提到"用 Gemini 画图 / 固定会话 e6bbee6b131ceda6 生图"。
环境依赖(前置自检):
- 已连接
nekoro-browserMCP(提供reload_extension/ensure_tab/page_info/js/click/upload_file/fill_input/sleep等工具)。 - Chrome 已关闭「下载前询问每个文件的保存位置」(一次性永久设置;见 §3)。
- 目标会话固定为
https://gemini.google.com/app/e6bbee6b131ceda6(严禁新开窗口)。
1. 关键结论速查
| 事项 | 正确做法 |
|---|---|
| 进入对话 | 固定会话里连续传图:不开新对话,当前输入框直接传下一张 |
| 上传图片 | 点 上传和工具(aria-label) → 上传文件(文本按钮) 触发真实 file input,再 upload_file |
| 分析+写词 | 先分析原图、生成完整英文提示词并确认(步骤 A0),再上传 |
| 粘贴提示词 | fill_input(sel=".ql-editor.textarea.new-input-ui", text=完整英文提示词) |
| 验证图已挂 | 查 img.gem-attachment / .gem-attachment img(class 含 gem-attachment gds-label-l gem) |
| 发送 | 找 发送 按钮 aria-label="发送" 用 .click()(contenteditable 内按 Enter 只换行) |
| 保存图片 | 关闭下载询问位置 → 点下载完整尺寸的图片 → 图直接落盘 Downloads → 取最新 *.jpg 复制成品 |
| 卡死恢复 | daemon 超时先 reload_extension() 自愈,再用 ensure_real_tab() 重连 |
2. 端到端 SOP(批次循环外壳)
批次主循环(处理 originals/ 内全部待处理图):
WHILE originals/ 中还有未处理原图:
1. 取"下一张"原图(逐张,见规则 §6.5)
2. 执行 步骤 A0 → B → C → D → E(单张完整流程)
3. 校验:成品已落盘 processed_outputs/ + 原图已移至 handled/
4. 若失败:进入 §5 异常分支,重试或标记待重传
5. 写/更新 当日任务记录 md(见 §7)
循环结束 → 输出成品汇总步骤 A — 固定会话连续传图(不开新对话)
无需"发起新对话"。固定地址 e6bbee6b131ceda6 一直复用,上一张生成下载完后,
直接在当前输入框传下一张即可。每轮开始先确认 editor.innerText.length≈1(已清空)。步骤 A0 — 分析原图并生成完整提示词(先写词,再执行,强制)
⚠️ 严格逐一处理,禁止一次性批量预读:每轮只针对"当前这张即将上传的原图" 做图分析 + 写提示词,不要在开工时把
originals/里所有图一次性全读出来分析。
在上传图片之前,必须先完成"看图→写词"这一步,且要把写好的完整英文提示词
真正填进浏览器输入框(步骤 C),不能跳过。本轮只处理这一张。
1) 分析原图(仅当前这张):识别照片主体、动作/姿态、环境、背景人物,
以及可保留/可处理的细节。
- 当前模型不直接支持图片视觉识别,可用以下任一方式读取:
a. 把图片用 Python(PIL) 缩放到 ~900px 后,再用 read_file 读取;
b. 或在浏览器里 file:// 打开原图截图查看。
- 每次只压缩/读取"即将上传的那一张",处理完即可删掉该临时文件。
2) 写出完整英文提示词:基于 `prompt_template.md` 模板,
仅把唯一占位符 [照片内容的真实描述] 替换为对当前照片的一句话英文描述,
其余段落(REALITY ANCHOR / FLAT PAINTED WORLD / THE ONE IMPOSSIBLE GIANT /
SMALL ELEMENTS & DOODLES / STYLE)原样保留。
- 替换好后整段暂存,下一步上传图片后直接填进输入框。
3) ⚠️ 必须先把提示词写出来并确认,再去点上传/发送;禁止"先传图后补词"或"无词直接发"。
4) ⚠️ 当前这张完成全流程(下载落盘 + 原图移 handled/)后,才进入下一张的步骤 A0。步骤 B — 上传图片(关键)
1) js: button[aria-label="上传和工具"] → .click()
2) 等 2 秒(菜单项需渲染,首次可能空,多等)
3) js: button[aria-label^="上传文件"] 或 文本="上传文件" → .click() // 触发真实 file input
4) 等 1 秒
5) upload_file(sel="input[type=file]", path="<绝对路径,双反斜杠>")
6) 验证:js 查 img.gem-attachment, .gem-attachment img 数量 ≥1
= 当前待发送消息的附件缩略图已挂上(class 形如 gem-attachment gds-label-l gem)。
⚠️ 不要查 editor 内的 img(contenteditable 内永远是 0,会误判"没挂上")。步骤 C — 粘贴提示词(已填好的完整英文提示词)
用 fill_input 工具最稳(走原生 value setter + input/change 事件,contenteditable 可用):
fill_input(sel=".ql-editor.textarea.new-input-ui", text=<步骤 A0 生成好的完整英文提示词>)
- 即 prompt_template.md 那种"占位符已替换好"的完整文本(约 1100~1300 字符,含换行 \n),
Gemini 正常识别。不要贴本 SKILL.md 的全文(含中文规则/注释),只贴纯英文 prompt。
- 验证:editor.innerText.length ≈ 所填完整提示词的字符数。
> 注意 Gemini 用 TrustedHTML,绝不能 innerHTML=...。步骤 D — 发送
1) 发送前再确认:attCount≥1(图挂着) + editorLen≈所填完整提示词字符数(词在)
2) js: button[aria-label="发送"] → .click()
3) 验证:发送后 editor.innerText.length 变回 ~1(被清空)= 真正发出⚠️ 在
.ql-editorcontenteditable 里按 Enter 只会换行,不会发送。 ⚠️ 若发送后 editor 仍保留完整提示词字符数,说明发送没触发(图可能没真正挂上),需重传。
步骤 E — 等待生成 + 零确认下载(最终版)
前置(一次性,永久生效):在 Chrome 设置里关闭
「下载前询问每个文件的保存位置」(Ask where to save each file before downloading)。
1) 等 30 秒(Gemini 出 1 张生成图;第1张还会带原图附件,blob 数+2)
2) 验证:img[src^="blob:"] 数量比发送前 +2(原图附件 + 生成图)
3) 点【最后一张】生成图的 `下载完整尺寸的图片` 按钮:
js: const dl=[...document.querySelectorAll('button[aria-label="下载完整尺寸的图片"]')];
dl[dl.length-1].click();
4) 等 3~5 秒,检查 Downloads 最新 .jpg(文件名形如 Gemini_Generated_Image_xxxx.jpg)
5) 取该 jpg,copy 为成品(见 §4 PowerShell 片段)
6) 复制完成后删掉 Downloads 里的源 jpg,保持目录整洁。
7) 归档原图:把本次处理过的原图从 originals/ 移动到 handled/ 目录(不存在则先创建)。3. 下载机制(零确认的关键)
- Gemini 生成图是
blob:URL,无标准<a download>直接可点;点击下载完整尺寸的图片按钮触发浏览器下载。 - 关键前置:必须在 Chrome 设置里关闭「下载前询问每个文件的保存位置」。关闭后:
- 点下载按钮 → 图直接以
.jpg完整尺寸落盘到默认 Downloads 目录; - 不再弹原生"另存为"框 → 不会阻塞后续下载;
- 不再产生
.tmp中转文件;文件名形如Gemini_Generated_Image_xxxx.jpg。
- 点下载按钮 → 图直接以
- ⚠️ 禁用
dialog_off:开启 dialog_off 后 nekoro 会download canceled取消下载。 - ⚠️
wait_for_download不可用:会报download canceled。改用"点按钮 + 等 3~5 秒 + 查 Downloads 最新.jpg+ copy"这套。 - 落盘的
.jpg已是完整 JPEG(头ff d8尾ff d9),直接copy /b重命名即可。
4. 可复用代码片段(nekoro-browser js 工具)
js
// ① 清空输入框
const e=document.querySelector('.ql-editor.textarea.new-input-ui');
e.focus(); while(e.firstChild) e.removeChild(e.firstChild);
e.dispatchEvent(new InputEvent('input',{bubbles:true}));
// ② 逐行填入(把 text 换成你的完整英文 prompt)
const text=`...你的完整英文提示词...`;
const lines=text.split('\n');
lines.forEach(ln=>{const p=document.createElement('p');p.textContent=ln;e.appendChild(p);});
e.dispatchEvent(new InputEvent('input',{bubbles:true}));
// ③ 验证图片缩略图已进对话
!!document.querySelector('img[src*="blob:"]')
// ④ 发送
[...document.querySelectorAll('button')].find(b=>b.getAttribute('aria-label')==='发送').click();
// ⑤ 找生成图的下载按钮
const im=[...document.querySelectorAll('img')].filter(i=>i.src.startsWith('blob:'))[0];
let p=im.closest('div');
for(let k=0;k<6;k++){p=p.parentElement; const b=[...p.querySelectorAll('button')].find(x=>(x.getAttribute('aria-label')||'').includes('下载完整尺寸')); if(b){b.click();break;}}浏览器命令(PowerShell,建议写成 .ps1 文件用 powershell -ExecutionPolicy Bypass -File xxx.ps1 执行):
powershell
# 取 Downloads 最新的一张 Gemini 生成图,复制到成品目录并删除源文件
$src = Get-ChildItem "$env:USERPROFILE\Downloads\Gemini_Generated_Image_*.jpg" |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
$dest = "C:\Users\mashaobo\CodeBuddy\20260814135857\processed_outputs\目标名.jpg"
Copy-Item $src.FullName $dest
Remove-Item $src.FullName -Force
Write-Host "saved -> $dest"PowerShell 内联变量
$易被 shell 转义吞掉,务必写成.ps1文件执行。文件名含随机 GUID, 一律用通配Gemini_Generated_Image_*.jpg+ 取最新,不要写死。
5. 异常分支(自愈与重试)
| 异常现象 | 诊断 | 处理 |
|---|---|---|
| attached tab 跑偏(停在别的页如 127.0.0.1:3080) | nekoro attached tab 切错页 | page_info() 确认 url;不对则用 switch_tab({tab_id}) 或 ensure_tab({url:"https://gemini.google.com/app/e6bbee6b131ceda6"}) 切回;list_tabs 辅助定位 |
| daemon 超时 / 卡死 | CDP 偶发卡死 | 先 reload_extension() 自愈 → ensure_real_tab() 重连 → ensure_tab 回固定会话;重连后 page_info() 确认 url |
| 发送后 editor 仍保留完整提示词字符数 | 图没真正挂上 / 发送未触发 | 查 img.gem-attachment 数量;若=0 回步骤 B 重传;重传前先清空 editor |
| 下载文件不落盘 / download canceled | 开了 dialog_off 或用了 wait_for_download | 关闭 dialog_off,改用"点按钮+等+查最新";确认 Chrome 已关下载询问位置 |
| 生成中误点下载(blob 数+2 未稳定) | 时机过早 | 等 blob 数稳定(≥发送前+2)再点下载按钮 |
| 成品大小为 0 / 不完整 | 复制时机过早 | 等 3~5 秒确认文件写入完成再 copy;copy 后校验文件头 ff d8 尾 ff d9 |
重试纪律:单张最多重试 2 次;仍失败则把原图保留在 originals/,在任务记录 md 备注"未处理/待重传",继续下一张,不阻塞批次。
6. 注意事项 / 强制规则
- 固定会话
e6bbee6b131ceda6连续传图不开新对话;每轮开始前确认editor.innerText.length≈1(已清空),避免旧上下文残留。 - 发送前必须做三项验证:缩略图存在(
img.gem-attachment)+ 输入框有文本 + 发送后输入框清空。 - Gemini 页面 CDP 偶发卡死,优先
reload_extension()自愈,不要暴力反复导航。 - 模型当前不支持截图视觉确认(
capture_screenshot被过滤),所有验证靠 DOM 文本/属性判断。 - 路径用双反斜杠;含中文的文件名在 node 命令里会乱码,尽量用 cmd/certutil 或通配处理。
- 保存环节前置条件(一次性永久):Chrome 关闭「下载前询问每个文件的保存位置」。
- 保存环节不要开启
dialog_off、不要调用wait_for_download:二者都会让 nekoro 判定download canceled导致文件不落盘。 - 每次完成任务后,新建一个日期命名的 md 文档(见 §7),记录本次生成结果及文件位置。
- 归档已处理原图:每张原图处理完成(成品已落盘
processed_outputs/)后,立即把originals/下的该文件移动到handled/目录(不存在则新建)。 - 先分析写词、再执行上传(强制):处理每张原图前,必须先完成步骤 A0。禁止"先传图后补词"。
- 逐张即时分析,禁止一次性批量预读(强制):必须逐张处理——每轮只对"即将上传的当前这张" 做图分析 + 写词,这张完成全流程后才进入下一张。
7. 任务完成记录文档规范(强制)
规则:每次完成一批/一次生图任务后,必须新建一个以日期命名的 md 文档, 记录本次生成的结果及文件位置。
- 路径:工作区根目录
c:\Users\mashaobo\CodeBuddy\20260814135857\ - 文件名:
YYYY-MM-DD_任务记录.md(同日多次可追加或加序号_序号) - 必须包含:
任务时间(日期与时段)
任务说明(处理几张、来源目录、模板)
生成结果表(原图已移至 handled/):
原图(已移至 handled/) 成品路径 大小 备注 handled/xxx.jpgprocessed_outputs/xxx.jpgx.xx MB 是否一次成功 处理失败未移动的原图保留在
originals/,备注"未处理/待重传"。关键环境/前置(如"Chrome 已关闭下载询问位置""固定会话 e6bbee6b131ceda6")
问题与解决(如有)
成品文件位置汇总(绝对路径)
原图归档汇总(从 originals/ 移到 handled/ 的文件)
8. 设计约束(与 prompt_template.md 联动)
生图提示词必须保证以下风格纪律(详见 prompt_template.md):
- 现实锚:照片主体去色保留,人物脸不扭曲/不换脸;背景路人可简化处理。
- 平涂世界:背景替换为 2–3 个高饱和撞色平涂色形,无渐变、无立体阴影。
- 唯一巨物:只选一个普通元素放大到荒诞尺度,不能有第二个巨物。
- 小元素与涂鸦:3–5 个成群小元素沿弧线分布 + 2–3 条白色手绘涂鸦线,禁孤立装饰。
- 硬禁忌:第二个巨物、色形渐变、立体阴影、相框包围、满版纹理、中文进 prompt、水印。
9. 安装
将本目录(surreal-pop-collage/)整体放入 skills 目录即可,结构应为:
surreal-pop-collage/
├── SKILL.md # 本文件:触发 + SOP + 异常分支 + 规则
└── prompt_template.md # 生图提示词纯模板(唯一占位符)