1. 项目概述:一个能“遥控”Gemini的自动化利器
如果你和我一样,经常需要和Gemini打交道,无论是用它生成设计灵感图、创作文案,还是进行一些复杂的多轮对话,那你肯定体会过手动操作的繁琐。每次都要打开浏览器、登录、输入提示词、等待生成、再手动保存图片……这个过程不仅耗时,而且难以集成到自动化流程中。今天要聊的这个项目gemini-skill,就是来解决这个痛点的。它本质上是一个通过浏览器自动化技术(CDP)来远程操控Gemini网页版的工具集,让你能用代码的方式,一键完成AI生图、对话、图片提取等一系列操作。
简单来说,它把Gemini网页版变成了一个可以通过编程调用的API。更酷的是,它遵循MCP(Model Context Protocol)协议,这意味着它不仅能被你的Node.js脚本调用,还能直接被Claude Desktop、Cursor等支持MCP的AI助手调用,让AI助手自己学会使用Gemini来画图、分析图片。项目的核心用户是开发者、自动化脚本爱好者、以及任何希望将Gemini能力无缝嵌入到自己工作流中的人。无论你是想批量生成营销素材,还是搭建一个智能创作机器人,这个工具都能为你省下大量重复劳动的时间。
2. 核心架构与设计哲学拆解
2.1 为什么选择CDP而非官方API?
看到这个项目,你可能会第一个问题:Google不是提供了Gemini的官方API吗?为什么还要绕道用浏览器自动化这种“黑科技”?
这里有几个非常实际的考量。首先,也是最重要的一点,图像生成功能。在我写这篇文章时,Gemini的官方API(Gemini API)主要侧重于文本和多模态对话,其图像生成能力要么未开放,要么有严格的限制和审核流程。而Gemini网页版上的图像生成功能(Gemini Advanced订阅用户可用)则强大且直观。通过CDP操控浏览器,我们就能“借用”这个尚未完全开放给API的尖端能力。
其次,是成本与认证。官方API通常涉及API密钥、配额和费用。而通过浏览器模拟用户操作,你使用的是自己的Google账户和Gemini Advanced订阅(如果需要生图),没有额外的调用费用,只有订阅成本。这对于个人开发者或小规模应用来说,门槛和可控性都更好。
最后,是功能的完整性与同步性。网页版永远是功能最全、更新最快的前沿。任何新推出的实验性功能(比如新的模型、交互方式),都会先在网页端上线。通过CDP,我们能几乎实时地“蹭到”这些新功能,而不必等待官方SDK的更新。
当然,这种方式也有其代价,主要是稳定性和性能。浏览器自动化受网络、页面结构变化的影响更大,且操作耗时通常比直接调用API要长。这就需要项目在架构设计上格外注重鲁棒性和错误处理。
2.2 核心架构:三层分离与守护进程模式
项目的架构图清晰地展示了一个分层、解耦的设计思想,这是保证其稳定和易用的关键。
第一层:MCP协议层 (mcp-server.js)这是对外的标准接口。它负责按照MCP协议的规范,注册所有可用的工具(比如gemini_generate_image,gemini_send_message),并处理来自MCP客户端(如Claude)的JSON-RPC请求。这一层只关心协议本身,不涉及具体的业务逻辑,确保了工具定义的清晰和可扩展性。
第二层:业务操作层 (gemini-ops.js,operator.js)这是核心逻辑所在。gemini-ops.js封装了所有与Gemini页面交互的高级操作,例如“生成图片”、“发送消息”、“切换模型”。而operator.js则提供了更底层的、稳定的DOM元素查找和操作函数(比如等待元素出现、安全地点击按钮、获取元素属性)。这种分离使得高层业务逻辑更清晰,底层操作更可复用和易于维护。
第三层:连接与进程管理层 (browser.js,daemon/)这是项目的“基础设施”层,也是最精妙的部分。它解决了浏览器自动化中最头疼的问题之一:浏览器实例的生命周期管理。
传统的脚本方式是:脚本启动 -> 打开浏览器 -> 执行操作 -> 关闭浏览器。如果频繁调用,反复启动关闭浏览器的开销巨大,用户体验也差(窗口闪烁)。gemini-skill引入了Daemon(守护进程)模式。
daemon/目录:这是一个独立的HTTP微服务进程。它的唯一职责就是管理一个“长寿”的浏览器实例。browser.js:作为技能(Skill)与Daemon交互的客户端。当需要操作浏览器时,它向Daemon的GET /browser/acquire端点发起请求。Daemon会检查是否已有浏览器在运行,如果没有则启动一个(并注入反爬插件),如果有则直接复用。然后返回CDP连接信息(WebSocket URL)给browser.js。- 惰性销毁:Daemon内部有一个30分钟(可配置)的倒计时。每次有技能通过
acquire端点连接浏览器,这个倒计时就会被重置。如果30分钟内没有任何连接,Daemon才会优雅地关闭浏览器并退出自身。这完美实现了“按需保持,闲置释放”,既避免了资源浪费,又保证了多次调用的极速响应。
这种设计带来的直接好处是:当你第一次通过Claude调用Gemini画图时,会等待十几秒启动浏览器并登录。但在此之后的半小时内,无论你让Claude画多少次图,感觉上都是“秒开”,因为浏览器一直在后台待命。这极大地提升了交互的流畅度。
2.3 反爬策略:以“隐身”对抗检测
直接使用puppeteer或playwright打开的浏览器,会被网站通过一些JavaScript属性(如navigator.webdriver)轻易检测出来,从而导致功能受限甚至被屏蔽。gemini-skill使用了puppeteer-extra-plugin-stealth这个强大的插件来对抗检测。
这个插件做了大量工作来让自动化浏览器看起来像一个真实的人类用户浏览器:
- 隐藏WebDriver标志:清除或重写
navigator.webdriver等属性。 - 模拟真实指纹:修改WebGL、Canvas、AudioContext等硬件指纹信息,使其具有唯一性且不像自动化工具。
- 伪装用户代理和语言:使用常见的、真实的浏览器UA和语言设置。
- 修改插件和MIME类型列表:使其与普通Chrome保持一致。
注意:项目文档中特别提到了与OpenClaw的兼容性。你可以配置复用OpenClaw的浏览器实例(端口18800),但OpenClaw的实例默认没有集成Stealth插件。这意味着在反检测能力上会打折扣。对于需要稳定、长期运行的任务,强烈建议使用项目默认的独立实例(端口40821),以获得完整的反爬保护。
3. 从零开始的详细配置与实操指南
3.1 环境准备:避坑指南
开始之前,确保你的环境满足以下条件,可以避免90%的初期问题:
- Node.js版本:必须 ≥ 18。建议使用LTS版本(如18.x, 20.x)。你可以通过
node -v检查。版本过低会导致一些新的JavaScript API无法使用。 - 浏览器安装:系统里需要安装Chrome、Edge或Chromium。项目会按这个顺序自动检测。一个常见的坑是只安装了“Chrome内核”的某款国产浏览器,这可能无法被正确识别。最稳妥的方法是安装官方Chrome。
- Google账户登录:这是最关键的一步。你需要一个已经登录到Gemini网页版(gemini.google.com)且功能正常的Google账户。如果是新账户,可能需要先手动在网页上完成一次Gemini的访问和 consent。对于需要图像生成的用户,请确保你的账户已订阅Gemini Advanced。
3.2 项目安装与初始化
安装过程很标准,但有几个细节需要注意:
# 克隆项目 git clone https://github.com/WJZ-P/gemini-skill.git cd gemini-skill # 安装依赖 npm install依赖安装可能遇到的问题:
- 网络问题:
puppeteer包会下载一个特定版本的Chromium。如果网络不畅,可能会失败或极慢。你可以设置环境变量跳过下载,使用系统已安装的Chrome(后续配置BROWSER_PATH)。
然后再执行# Linux/macOS export PUPPETEER_SKIP_DOWNLOAD=true # Windows (PowerShell) $env:PUPPETEER_SKIP_DOWNLOAD="true"npm install。 - Sharp编译错误:
sharp是一个高性能图片处理库,安装时可能需要编译。如果遇到问题,可以尝试先更新你的系统构建工具(如Windows的Build Tools,macOS的Xcode Command Line Tools)。
3.3 深度配置解析:让项目贴合你的环境
项目根目录下有一个.env.example文件(或你需要创建.env文件)。复制它并重命名为.env,然后开始配置。理解每个配置项的作用,能让你更好地驾驭这个工具。
浏览器核心配置:
# .env 文件示例 BROWSER_PATH=C:\Program Files\Google\Chrome\Application\chrome.exe BROWSER_DEBUG_PORT=40821 BROWSER_HEADLESS=false BROWSER_USER_DATA_DIR=C:\Users\YourName\.gemini_automation_data BROWSER_PROTOCOL_TIMEOUT=120000BROWSER_PATH:指定浏览器可执行文件的绝对路径。如果留空,项目会尝试自动查找。在Windows Server或某些Linux桌面环境下,自动查找可能失败,明确指定路径是最稳妥的。BROWSER_HEADLESS:首次运行,务必设为false。这样浏览器会以图形界面打开,方便你完成首次登录。登录成功后,后续运行可以改为true以节省资源并在无界面的服务器上运行。BROWSER_USER_DATA_DIR:这是保存登录状态的关键目录。指定一个专属目录(如示例中的.gemini_automation_data)可以隔离自动化浏览器的cookies、历史记录,避免与你日常使用的浏览器冲突。一旦在这个目录下完成登录,后续所有会话都将保持登录状态。BROWSER_PROTOCOL_TIMEOUT:CDP命令超时时间。生成图片是耗时操作,默认的60秒可能不够,建议首次尝试时设置为120000(2分钟)或更长。
Daemon进程配置:
DAEMON_PORT=40225 DAEMON_TTL_MS=1800000DAEMON_TTL_MS:守护进程的闲置销毁时间,默认30分钟(1,800,000毫秒)。如果你使用频率很高,可以适当延长。如果是在内存紧张的服务器上,可以缩短以更快释放资源。
输出目录配置:
OUTPUT_DIR=./my_gemini_output所有生成的图片、下载的图片都会保存在这个目录下。确保运行脚本的用户对该目录有读写权限。
3.4 首次运行与登录认证
配置完成后,我们来触发第一次运行,完成登录。
方法一:通过Demo脚本(推荐)运行npm run demo。这会执行src/demo.js,尝试进行一些基本操作。因为BROWSER_HEADLESS=false,你会看到一个Chrome窗口打开,并导航到gemini.google.com。
此时,你需要手动完成登录:
- 如果页面提示登录,输入你的Google账号密码。
- 完成两步验证(如果开启了)。
- 可能会遇到Gemini的欢迎页面或条款同意,全部点击接受/继续。
- 最终页面应停留在Gemini的聊天主界面。
登录状态保存:一旦登录成功,你的会话信息(cookies, localStorage)就会被保存在BROWSER_USER_DATA_DIR指定的目录中。关闭浏览器窗口,但不要终止Node.js进程。Demo脚本执行完毕后,Daemon会在后台继续运行30分钟。
验证登录状态:你可以通过MCP工具gemini_check_login来验证,或者再次运行Demo。第二次及以后的运行,应该无需再登录,浏览器会直接打开已登录的Gemini页面。
重要提示:请确保在登录过程中,浏览器页面没有被其他自动化操作打断。最好等页面完全加载、登录流程彻底结束后,再让脚本继续执行。
demo.js中有适当的等待逻辑,但网络慢时可能需要你手动观察。
4. 核心功能实操:以AI生成为例
一切就绪后,我们就可以深入核心功能了。这里以最复杂的“AI生图”流程为例,拆解其内部运作和你的操作要点。
4.1 生图工具gemini_generate_image详解
这是最强大的工具。调用它时,背后发生了一系列精密的自动化操作:
- 会话环境准备:工具首先会检查当前是否在一个干净的对话中。如果
newSession参数为true,或者当前页面不是聊天页,它会点击“New Chat”按钮。 - 模型确认:确保当前模型是支持图像生成的(通常是“Gemini Advanced”相关的模型)。如果不是,它会自动切换。
- 输入提示词:将你的
prompt文本输入到聊天框。 - 上传参考图(可选):如果提供了
referenceImages(本地图片路径数组),它会逐个点击上传按钮,选择文件,并等待图片在输入框内预览成功。这实现了“图生图”或“图片+文字描述生图”。 - 发送并等待:点击发送按钮。然后进入最耗时的阶段——等待AI生成。脚本会持续监听页面变化,等待代表“正在生成”的动画消失,并出现新的消息气泡。
- 结果提取与下载:
- 识别新消息中的图片。
- 如果
fullSize为true,它会执行一个关键操作:右键点击图片 -> 选择“在新标签页中打开图片”。这是通过CDP获取无水印高清原图的唯一可靠方式。 - 通过CDP捕获新标签页的加载事件,获取图片的原始网络数据,直接保存为文件。
- 如果
fullSize为false,则直接从聊天DOM中提取Base64格式的缩略图。
- 水印移除:无论哪种方式下载的图片,都会经过
watermark-remover.js处理,利用sharp库识别并抹除Gemini添加的角标水印。 - 返回结果:工具最终返回图片的本地保存路径、尺寸等信息。
实操调用示例(作为库使用):
// 在你的脚本中 import { createGeminiSession, disconnect } from './src/index.js'; (async () => { try { const { ops } = await createGeminiSession(); // 场景1:纯文本生图 const result1 = await ops.generateImage('一只穿着宇航服、在太空漂浮的柯基犬,卡通风格,明亮色彩', { fullSize: true, // 下载高清原图 timeout: 180000 // 等待3分钟 }); console.log(`高清图片已保存: ${result1.filePath}, 尺寸: ${result1.width}x${result1.height}`); // 场景2:图生图(风格参考) const result2 = await ops.generateImage('将这张图的风格应用到一座未来主义城市的设计上', { referenceImages: ['./input/reference_style.jpg'], // 上传风格参考图 fullSize: true }); // 场景3:多图混合生成(需Gemini支持) // const result3 = await ops.generateImage('结合这两张图的元素,创造一个新角色', { // referenceImages: ['./input/charA.jpg', './input/charB.jpg'] // }); } catch (error) { console.error('生成失败:', error); } finally { // 断开CDP连接,但浏览器由Daemon管理,不会关闭 disconnect(); } })();4.2 与AI助手集成:MCP模式实战
这才是项目的精髓所在。以Claude Desktop为例,让Claude直接调用Gemini来画图。
定位Claude配置:找到Claude Desktop的配置文件位置。
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
- macOS:
编辑配置文件:在配置文件中添加
gemini-skill作为MCP服务器。你需要将<项目绝对路径>替换为你电脑上gemini-skill文件夹的真实路径。{ "mcpServers": { "gemini": { "command": "node", "args": ["<项目绝对路径>/src/mcp-server.js"], "env": { "BROWSER_HEADLESS": "true" // 登录后可设为无头模式 } } } }例如,在Windows上可能是:
"args": ["C:\\Users\\YourName\\Projects\\gemini-skill\\src\\mcp-server.js"]重启Claude Desktop:保存配置文件并完全重启Claude Desktop应用。
开始使用:重启后,在Claude的聊天框中,你应该能看到一个“齿轮”或“连接”图标,提示已连接MCP服务器。现在,你可以直接对Claude说:
- “请用Gemini帮我画一张夏日海滩的风景图。”
- “我想生成一个Logo,主题是科技与自然融合,让Gemini生成几个方案看看。”
- “上传这张草图(你可以附加图片文件),让Gemini把它变成精美的插画。”
Claude会理解你的意图,自动调用gemini_generate_image工具,并将生成的图片结果返回给你。整个过程,你无需离开Claude的界面,也无需手动操作浏览器。
4.3 其他实用工具场景示例
除了生图,其他工具也能组合出强大工作流:
自动化内容灵感生成:结合
gemini_new_chat和gemini_send_message,你可以让脚本定期向Gemini询问某个领域的最新趋势或内容创意,并将文本回复保存下来。await ops.newChat(); const response = await ops.sendMessage('为我的科技博客生成5个关于AI伦理的标题创意'); console.log(response);批量下载对话历史图片:如果你在Gemini网页版的历史对话里有很多生成的图片,可以用
gemini_navigate_to导航到那个会话,然后用gemini_get_images获取所有图片信息,再循环调用gemini_download_full_size_image批量下载。// 假设你有一个历史会话的URL await ops.navigateTo('https://gemini.google.com/chat/xxxxxxxxxxxx'); const images = await ops.getImages(); for (let i = 0; i < images.length; i++) { await ops.downloadFullSizeImage(i); // 按索引下载 }创建图片分享链接:
gemini_share_latest_image工具可以自动点击图片的“分享”按钮,创建一个公开链接。这对于需要快速将AI生成的图片分享给他人预览非常有用。const shareUrl = await ops.shareLatestImage(0, { copyToClipboard: false }); console.log(`图片分享链接: ${shareUrl}`);
5. 故障排查与实战经验分享
即使设计再完善,浏览器自动化也难免遇到各种意外。下面是我在深度使用过程中总结的常见问题与解决方案。
5.1 问题排查清单
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 启动失败,提示无法找到浏览器 | 1. 未安装Chrome/Edge。 2. BROWSER_PATH配置错误。3. 系统权限问题。 | 1. 运行npm run demo观察详细错误。2. 检查 BROWSER_PATH路径是否存在、可执行。3. 尝试在命令行中直接运行该路径下的浏览器。 |
| 页面打开,但一直卡在登录页或白屏 | 1. 网络问题(如需要特殊网络环境)。 2. Google账户需要额外验证。 3. 页面加载超时。 | 1. 确保你的网络可以正常访问gemini.google.com。2. 首次运行时,将 BROWSER_HEADLESS设为false,手动观察登录过程,完成所有验证。3. 在 browser.js或启动配置中增加defaultViewport: null并调大timeout。 |
生图或对话超时 (TimeoutError) | 1. AI生成时间过长。 2. 网络延迟高。 3. 页面元素未按预期出现。 | 1. 增加BROWSER_PROTOCOL_TIMEOUT和工具调用时的timeout参数(如设为300000,即5分钟)。2. 检查 operator.js中的等待选择器是否因Gemini页面更新而失效。可以临时增加await page.waitForTimeout(5000)观察。3. 使用 gemini_probe工具检查页面关键元素状态。 |
| 提示“未登录”或功能不可用 | 1. Cookies失效。 2. userDataDir被污染或路径错误。3. 账户未订阅Gemini Advanced(仅限生图)。 | 1. 删除BROWSER_USER_DATA_DIR指定的目录,重新运行并手动登录。2. 确认配置的路径是绝对路径且有权写入。 3. 手动在浏览器中访问Gemini,确认生图功能可用。 |
| MCP客户端无法连接或找不到工具 | 1.mcp-server.js路径错误。2. Node.js环境问题。 3. 端口冲突。 | 1. 在终端直接运行node /path/to/mcp-server.js,看是否有错误输出。2. 确认Claude配置中的路径使用了正确的斜杠(Windows用双反斜杠或正斜杠)。 3. 检查 DAEMON_PORT(40225) 和BROWSER_DEBUG_PORT(40821) 是否被其他程序占用。 |
| 下载的图片有水印或尺寸小 | fullSize参数未设置为true,或高清图下载流程失败。 | 1. 调用生图工具时务必指定{ fullSize: true }。2. 检查 watermark-remover.js是否正常工作,可能是水印位置变化导致识别失败。可以暂时注释掉水印移除逻辑测试。 |
| 操作过程中浏览器页面崩溃 | 内存不足,或页面JavaScript异常。 | 1. 增加Daemon的闲置销毁时间,减少频繁启动。 2. 在 engine.js的launch参数中增加args: ['--disable-dev-shm-usage', '--no-sandbox'](Linux服务器常见)。3. 在操作步骤间增加更多 waitForSelector和waitForTimeout,降低操作频率。 |
5.2 实战经验与优化技巧
为长任务设置独立超时:生图 (
generateImage) 和复杂对话 (sendMessage) 的默认超时可能不够。最佳实践是在每次调用时都显式传递一个较长的timeout参数,而不是完全依赖全局配置。await ops.generateImage('复杂的场景描述...', { fullSize: true, timeout: 240000 // 4分钟专用于此次生图 });管理好用户数据目录:
BROWSER_USER_DATA_DIR是你的“身份”。建议为不同项目或不同Google账户创建不同的目录。定期清理此目录下的Cache等子文件夹可以解决一些奇怪的页面加载问题。利用“临时会话”保护隐私:
gemini_temp_chat工具会开启一个不保存到历史记录的临时对话。如果你处理敏感信息或不想污染聊天历史,优先使用此模式。监控Daemon状态:Daemon提供了简单的HTTP API。你可以通过
curl http://localhost:40225/health检查其是否存活,通过curl http://localhost:40225/browser/status查看浏览器状态。这在编写监控脚本时很有用。应对页面更新:Gemini的网页界面可能会更新,导致CSS选择器失效。如果某个工具突然不工作了,首先使用
gemini_probe工具。它会输出当前页面关键按钮和区域的状态,帮助你快速定位是哪个选择器失效了。修复通常只需要更新operator.js或gemini-ops.js中对应的选择器字符串。在服务器上运行:在无图形界面的Linux服务器上运行,务必设置
BROWSER_HEADLESS=true和BROWSER_USER_DATA_DIR为一个绝对路径。此外,可能需要安装一些额外的系统库来支持Chrome运行(如xvfb虚拟帧缓冲)。
这个项目的强大之处在于它将一个复杂的图形界面操作,封装成了一组可靠的、可编程的指令。虽然它依赖于浏览器自动化这条稍显“脆弱”的道路,但其精良的Daemon设计、反爬策略和全面的工具覆盖,为我们在官方API之外打开了一扇灵活运用Gemini能力的大门。无论是集成到你的AI工作流中,还是作为探索Gemini前沿功能的实验平台,它都是一个极具价值的工具。