标签 Gemini Business 下的文章

首先上github链接:

这个项目本质上是一个把图片的一部分剪下来,经过api/手动处理后回填到原图片的项目。

我们都知道banana可以翻译正常漫画,但是合理利用这个项目也可以轻松把涩图漫画也翻译成毫无P图痕迹的漫画哦。

原理很简单,banana拒绝翻译涩图的原因是,你把涩图发给了banana!

这好像是一句废话,但我们反过来思考就能发现,如果我们不把完整的涩图发给,而是把有台词的部分切片发给它,它就不会拒绝~

(这么一想,我其实是不是不用加nsfw标签?)

那么通往真理的大道就打开了:

  1. 上传你的图片到本项目

  2. 圈出台词所在的图片(我看到其他漫画翻译项目可以自动检测文本框,使用comic text detector之类的工具实现的,先摆烂一会,等一个pr~)

  3. 使用nano banana pro的api发起翻译请求(当然也提供了不使用api手动替换的途径)

  4. 翻译后的对话自动回填到涩图中!

还有一些注意事项:

  1. gemini-business2api项目可以白嫖banana pro,但是通过2api的生图成功率比较低,因为图片虽然生成了,但url好像经常没有被项目返回。可能需要看看项目能不能二开一下修复这个问题才能爽嫖?使用纯banana api就不会有问题,成功率99.99%。实在没有纯api的话也可以用手动模式,在gemini-business一张一张翻译再复制回项目ww

    gemini-business2api生图问题解决了,现在可以稳定生图,等我给这个项目提pr

    更新:pr已经提交了,如果2api项目的佬友还没合并的话,你们可以参考我pr的内容改两句代码后直接运行。

  2. 圈出图片所在的台词时,不要圈太小了,尽量圈大点,比如这样:

除了文本框,还要多截一些周围的景色。

因为结果测试,如果不截一些景色的话,就会导致banan喜欢偷懒不嵌字,把日文原图发回来。

  1. 推荐提示词,可以自行修改:

    0. 使用banana pro
    
    1. 请用banana中文翻译替换掉图片里的日文。是的,生成一张只有中文的图!
    
    3. 这句台词的大意是:[]
    

📌 转载信息
转载时间: 2026/1/25 08:07:06

闲着无聊让 codex 糊了个小工具,顺便混点赞(小白开发,各位佬轻喷~)

主要作用:
1、自动批量获取 Gemini Business 账号相关信息
2、将获取的信息整理转换,同步给 Business Gemini Pool
3、当同步数量少于设定数量时,自动创建新的账户补齐

ps:由于 Business token 有效期只有 12 小时,系统会每 6 小时自动执行 token 刷新、同步等,达到 token 保活的目的

使用到的项目(感谢~!):
Gemini Business2api:

Gemini Business 账号管理系统(使用 cf 邮件系统自动创建)

邮件系统搭建参考教程:

最后是中间件同步工具:
sync.zip
启动方式:
填写好.env 后
pip install -r requirements.txt
python app.py


📌 转载信息
转载时间:
2026/1/24 10:34:57

久等了。
恰逢 L 站两周年!

一定要更新!!!
刚刚更新了登录浏览器数据清理、微软验证码优化、无痕登录、浏览器引擎 DP/UC 等等

首先感谢以下大佬和相关项目(可能有漏,联系补上)

SnapSheep 【Gemini Business 注册机】
dasfsa sa 【微软邮箱注册机】
又笨又坏Zooo1 【DuckMail 邮箱注册】
gemini business 究极缝合怪
F 佬 Linux.do 讨论
heixxin/gemini | Linux.do 讨论
Gemini-Link-System | Linux.do 讨论
DuckMail 邮箱
kitwing

非常感谢每一位佬友的付出。
终于,2api 项目解决了最后一个痛点: 无法自动刷新账号
一开始也是自己有点需求,随便弄了弄了,以为没什么人看,没想到后续项目越来越多大佬加入、各种完善,现在,几乎每个人都可以实现 Gemini 全系、香蕉画图自由!且上手门槛极低!

一定注意更新!!!

主要功能:

  • 全新优雅现代的管理面板
  • 多账号负载均衡 - 轮询与故障自动切换
  • 自动化账号管理 - 支持自动注册与登录,集成 DuckMail 和 Microsoft 邮箱,支持无头浏览器模式
  • 多模态输入 - 100+ 文件类型(图片、PDF、文档、音频、视频、代码等)(未经测试)
  • 图片生成 & 图生图 - 模型可配置,Base64 或 URL 输入 / 输出
  • 日志与监控 - 实时状态与统计信息
  • 可选 PostgreSQL 后端 - 支持账户 / 设置 / 统计持久化

页面截图

页面截图


项目地址(求 Star)

Dreamy-rain/gemini-business2api: OpenAI-compatible API for Gemini Business with multi-account load balancing and image generation | 将 Gemini Business 转为 OpenAI 兼容接口,支持多账户负载均衡与图像生成

重要:

  1. 注册失败建议关闭无头浏览器可以直接看到问题
  2. 邮箱用微软邮箱最佳。
  3. 另外建议有域名条件的佬友,尽量用自己的域名邮箱注册,保活时间更长,教程参考项目中的文档中心里面的使用教程。

未来计划:

  • 修复 Docker 部署
  • 多模态 URL 失效 500 报错问题
  • 同一 IP 风控问题(http 或 socks 代理解决)
  • Gemini 回复截断问题
  • 更多计划

欢迎更多佬友 PR

注意,抱脸不支持自动注册刷新账号等功能!!!

另外,预告一下本项目的本人公益站,注册赠送 100​,Gemini3PP 按次计费 1​/ 次
目的:想赚点 LDC、用来购买站内大佬的 CC,方便更快更新程序!
用的香港的小鸡,不知道抗不扛得住,不知道运营多久。
之后可能更新主贴,先给三级佬友测试,抱脸部署的,画图不稳定。
暂时先这样,测试运营。

主站:https://free.nanohajimi.mom/

打赏 66 建议购买公益站 Gemini 额度

也可直接打赏 LINUX DO Credit

感谢各位!


📌 转载信息
原作者:
Dreamy-rain
转载时间:
2026/1/18 09:10:56

混了这么久社区我也是终于三级了啊 (凌晨四点升级)!这几天用 AI 糊出来了一个小玩具,可以配合站里大佬
@F-droid 的项目🎉Gemini Business 2API 来了 | 支持 Docker 一键启动! 使用 Gemini Business 的各个 gemini 模型(大香蕉随便用说是)。

所有需要用到的项目我会在帖子最后给出地址,这里需要搭建的项目为 API 反代Hugging Face 镜像(也可以换成别的,例如 zeabur)和域名邮箱

这里先给出 github 地址,具体的配置详情都在 github 中可自行查阅 希望大家可以帮我点点 star,我在这里感激不尽

GeminiForge

现在来说说项目的具体功能:
通过 github 工作流使用配置的代理节点,域名邮箱和凭证上传地址来自动注册 Gemini Business 账号,获取凭证并上传至 2api 中,可以说是相当方便了。

代理除了常见的 HTTP/SOCKS5 代理,还额外支持 VLESS 代理(塞了个 singbox,这里建议节点用好一点,不然可能打不开网页或者接不到验证码,GitHub 的 ip 无法注册)

vless 支持两种格式,一种是正常的 VLESS URL,另一种就是 YAML 配置

格式一:VLESS URL(推荐)

vless://uuid@server:port?type=tcp&security=reality&sni=example.com&fp=chrome&pbk=xxx

格式二:YAML 配置

{ server: example.com, port: 443, uuid: xxx-xxx, flow: xtls-rprx-vision, ... }

项目设定为每 6 小时自动运行一次,一次注册两个账号并上传凭证,并且支持并发注册,最多 5 并发,这些设置可以通过修改 workflows 中的 register.yml 文件修改。

最后是用到的几位大佬的帖子和项目链接,大家可以自行查看与搭建。

注册机逻辑

API 反代

Hugging Face 镜像

域名邮箱搭建


📌 转载信息
原作者:
starsdream
转载时间:
2026/1/15 18:23:41

原贴地址。 Gemini Business/Team 一键注册,可无限循环,拉人 半自动化脚本

后续更新都委托

进行更新了。会在这位佬的项目上集成批量注册批量账号管理 + 刷新 json。后续可能会增加生态。

(如破甲,酒馆,有这方面研究的佬可以分享一下吗?)

注意更新在旁边发行包更新下载,一键配置不打算更新了。

注意更新在旁边发行包更新,一键配置不打算更新了。
注意更新在旁边发行包更新,一键配置不打算更新了。

首先哭一下穷,麻烦 LDC 富足的佬友支持一下。那么多天只有 50LDC 收入看得出来这位同志还是犹豫了很久的。可以看出心路历程。求求大家支持一下,这对一个新手小白来说真的很重要。后续项目也会接着造福大家!

这次主要是讲一下更新内容和你可以用来干嘛,增加一下生态。

因为大家都瞧不上这个模型,因为的确垃圾,而且甲很厚。(本人稍微研究了一下破甲,如某馆很麻烦,经常中断,导致突然兴致全无。有破甲高手可以私信我 ovo)

我通常是用来翻译。而且一次配置,可以一直使用 【开源】Gemini Nexus V4.2.0:开箱即用的 Chrome 浏览器控制插件,更新支持 OpenAI 兼容 API

然后是接入 Cherry Studio, 用大香蕉和他支持的模型。


修复的问题

| 问题 | 说明 |

首先是改为无头浏览器了,不能弹出来烦你。
现在只有一个命令行在那运行,注册速度大大加快了。

| 按钮匹配不正确 | 有大概率触发点击验证和重发验证码两个按钮,但是不影响功能
已修复,现在会精准点击

| 页面加载慢 | 网络不稳定时页面加载较慢,可能导致超时
已修复

| 存在僵尸进程 clash.exe| 在后台会占用资源,可自己手动进任务管理器结束 |
在命令行按 CTRL+C 然后 YES 会杀进程

然后虽然这个模型和套餐索然无味,大佬都看不上。本人都用在边边角角。

首先是 2API 的反代。

然后是你要部署好佬的项目

部署成功长这样子

然后看到他有一个过期时限 12h,不然会过期。
这个佬给出了方案

佬的方案是登录账号一键获取前面佬的 json 相关数据。

如果你打算只白嫖一两个号,然后丢进去反代是不是太容易满足了,毕竟我们可以做到批量注册。我是用了 22 个号,有人问为什么那么多。

22 个号一个个更新太慢了,然后 D 佬支持批量导入,于是我折腾了一个批量更新这些数据的 Web,
你可以一键更新这些账号。

这部分见最前面那位佬,由他更新。


📌 转载信息
原作者:
Zooo1
转载时间:
2026/1/15 10:19:30

看了很多佬们对 gemini business 的注册和 2api 的开发。但是始终没有发现一个能够同时满足标题全部需求的东东。
于是乎我选择把下面各位大佬的东西直接缝合起来弄成一个平台:
【Gemini-Business2api】支持多账户轮询、账户监控日志、画图(返回 url)、HuggingFace 部署
Gemini Business 注册机

合并实现了以下功能:

  • 自动批量注册 gemini business 账号

  • 定时轮询自动刷新 gemini 凭证
  • 接入 cloudflare_temp_email 自动接码,支持多个域名邮箱配置。
  • 多账号 2API 使用
  • 可使用 docker 部署,接入了 Xvfb 显示规避无头浏览器的注册审查

邮箱配置需要额外使用 GitHub - dreamhunter2333/cloudflare_temp_email: CloudFlare free temp domain email 免费收发 临时域名邮箱 支持附件 IMAP SMTP TelegramBot
需要配置 AI 提取验证码、ADMIN 凭证来提取邮箱密码。

关于部署,目前还没有测试过能否在 huggingface 来部署,因为包含了 chrome 的镜像略大不确定能不能布上去。

项目地址:

最后的最后,再次感谢各位大佬提供的方案和思路:CooooooKKSnapSheep


📌 转载信息
原作者:
linlee
转载时间:
2026/1/14 18:35:16

直接产出 Dreamy-rain/gemini-business2api 所需 json 注册效率~60s 一个
日抛 直接每日重新注册即可

刚刚那个版本有点问题 已修复
已经生成的佬记得把 config_id 后缀的?csesidx=.* 清理掉重新导入

import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
from urllib.parse import urlparse, parse_qs
from datetime import datetime
import time, random, json, os, requests

# 配置
TOTAL_ACCOUNTS = 20
MAIL_API = "https://mail.chatgpt.org.uk"
MAIL_KEY = "gpt-test"
OUTPUT_DIR = "gemini_accounts"
LOGIN_URL = "https://auth.business.gemini.google/login?continueUrl=https:%2F%2Fbusiness.gemini.google%2F&wiffid=CAoSJDIwNTlhYzBjLTVlMmMtNGUxZC1hY2JkLThmOGY2ZDE0ODM1Mg" # XPath
XPATH = {
    "email_input": "/html/body/c-wiz/div/div/div[1]/div/div/div/form/div[1]/div[1]/div/span[2]/input",
    "continue_btn": "/html/body/c-wiz/div/div/div[1]/div/div/div/form/div[2]/div/button",
    "verify_btn": "/html/body/c-wiz/div/div/div[1]/div/div/div/form/div[2]/div/div[1]/span/div[1]/button",
}

NAMES = ["James Smith", "John Johnson", "Robert Williams", "Michael Brown", "William Jones",
         "David Garcia", "Mary Miller", "Patricia Davis", "Jennifer Rodriguez", "Linda Martinez"]

def log(msg, level="INFO"): print(f"[{level}] {msg}")

def create_email():
    """创建临时邮箱""" try:
        r = requests.get(f"{MAIL_API}/api/generate-email",
            headers={"X-API-Key": MAIL_KEY}, timeout=30)
        if r.status_code == 200 and r.json().get('success'):
            email = r.json()['data']['email']
            log(f"邮箱创建: {email}")
            return email
    except Exception as e:
        log(f"创建邮箱失败: {e}", "ERR")
    return None def get_code(email, timeout=30):
    """获取验证码"""
    log(f"等待验证码 (最多{timeout}s)...")
    start = time.time()
    while time.time() - start < timeout:
        try:
            r = requests.get(f"{MAIL_API}/api/emails", params={"email": email},
                headers={"X-API-Key": MAIL_KEY}, timeout=30)
            if r.status_code == 200:
                emails = r.json().get('data', {}).get('emails', [])
                if emails:
                    html = emails[0].get('html_content') or emails[0].get('content', '')
                    soup = BeautifulSoup(html, 'html.parser')
                    span = soup.find('span', class_='verification-code')
                    if span:
                        code = span.get_text().strip()
                        if len(code) == 6:
                            log(f"验证码: {code}")
                            return code
        except: pass print(f"  等待中... ({int(time.time()-start)}s)", end='\r')
        time.sleep(3)
    log("验证码超时", "ERR")
    return None def save_config(email, cookies, url):
    """保存配置"""
    os.makedirs(OUTPUT_DIR, exist_ok=True)
    parsed = urlparse(url)
    path_parts = url.split('/')
    config_id = None for i, p in enumerate(path_parts):
        if p == 'cid' and i+1 < len(path_parts):
            config_id = path_parts[i+1]
            # 清理 config_id 结尾的 ?csesidx=xxx if config_id and '?' in config_id:
                config_id = config_id.split('?')[0]
            break

    cookie_dict = {c['name']: c for c in cookies}
    ses_cookie = cookie_dict.get('__Secure-C_SES', {})

    data = {
        "id": email,
        "csesidx": parse_qs(parsed.query).get('csesidx', [None])[0],
        "config_id": config_id,
        "secure_c_ses": ses_cookie.get('value'),
        "host_c_oses": cookie_dict.get('__Host-C_OSES', {}).get('value'),
        "expires_at": datetime.fromtimestamp(ses_cookie.get('expiry', 0) - 43200).strftime('%Y-%m-%d %H:%M:%S') if ses_cookie.get('expiry') else None
    }

    with open(f"{OUTPUT_DIR}/{email}.json", 'w') as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    log(f"配置已保存: {email}.json")
    return data

def register(driver):
    """注册单个账号"""
    email = create_email()
    if not email: return None, False, None

    wait = WebDriverWait(driver, 60)

    # 1. 访问登录页
    driver.get(LOGIN_URL)
    time.sleep(5)

    # 2. 输入邮箱
    log("输入邮箱...")
    inp = wait.until(EC.visibility_of_element_located((By.XPATH, XPATH["email_input"])))
    inp.click(); time.sleep(0.3); inp.clear(); time.sleep(0.3)
    for c in email: inp.send_keys(c); time.sleep(0.05)
    log(f"邮箱: {email}, 实际值: {inp.get_attribute('value')}")
    time.sleep(1)

    # 3. 点击继续
    btn = wait.until(EC.element_to_be_clickable((By.XPATH, XPATH["continue_btn"])))
    driver.execute_script("arguments[0].click();", btn)
    log("点击继续")
    time.sleep(3)

    # 4. 获取验证码
    code = get_code(email)
    if not code: return email, False, None # 5. 输入验证码
    time.sleep(2)
    log(f"输入验证码: {code}")
    try:
        pin = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "input[name='pinInput']")))
        pin.click(); time.sleep(0.2)
        for c in code: pin.send_keys(c); time.sleep(0.1)
    except:
        try:
            span = driver.find_element(By.CSS_SELECTOR, "span[data-index='0']")
            span.click(); time.sleep(0.3)
            driver.switch_to.active_element.send_keys(code)
        except Exception as e:
            log(f"验证码输入失败: {e}", "ERR")
            return email, False, None # 6. 点击验证
    time.sleep(1)
    try:
        vbtn = driver.find_element(By.XPATH, XPATH["verify_btn"])
        driver.execute_script("arguments[0].click();", vbtn)
    except:
        for btn in driver.find_elements(By.TAG_NAME, "button"):
            if '验证' in btn.text: driver.execute_script("arguments[0].click();", btn); break
    log("点击验证")
    time.sleep(5)

    # 7. 输入姓名 try:
        name_inp = WebDriverWait(driver, 30).until(EC.visibility_of_element_located(
            (By.CSS_SELECTOR, "input[formcontrolname='fullName'], input[placeholder='全名'], input#mat-input-0")))
        name = random.choice(NAMES)
        name_inp.clear(); time.sleep(0.3)
        for c in name: name_inp.send_keys(c); time.sleep(0.03)
        log(f"姓名: {name}")
        from selenium.webdriver.common.keys import Keys
        name_inp.send_keys(Keys.ENTER)
    except Exception as e:
        log(f"姓名输入异常: {e}", "WARN")

    # 8. 等待进入工作台
    log("等待工作台...")
    time.sleep(6)
    for _ in range(30):
        if 'business.gemini.google' in driver.current_url and 'auth' not in driver.current_url:
            break
        time.sleep(2)
    time.sleep(3)

    # 9. 保存配置
    config = save_config(email, driver.get_cookies(), driver.current_url)
    log(f"注册成功: {email}")
    return email, True, config

def main():
    print(f"\n{'='*50}\nGemini Business 批量注册 - 共 {TOTAL_ACCOUNTS} 个\n{'='*50}\n")

    driver = uc.Chrome(options=uc.ChromeOptions(), use_subprocess=True)
    success, fail, accounts = 0, 0, []

    for i in range(TOTAL_ACCOUNTS):
        print(f"\n{'#'*40}\n注册 {i+1}/{TOTAL_ACCOUNTS}\n{'#'*40}\n")

        try:
            driver.current_url  # 检查driver是否有效 except:
            driver = uc.Chrome(options=uc.ChromeOptions(), use_subprocess=True)

        try:
            email, ok, cfg = register(driver)
            if ok: success += 1; accounts.append((email, cfg))
            else: fail += 1 except Exception as e:
            log(f"异常: {e}", "ERR"); fail += 1 try: driver.quit()
            except: pass
            driver = uc.Chrome(options=uc.ChromeOptions(), use_subprocess=True)

        print(f"\n进度: {i+1}/{TOTAL_ACCOUNTS} | 成功: {success} | 失败: {fail}")

        if i < TOTAL_ACCOUNTS - 1:
            try: driver.delete_all_cookies()
            except: pass
            time.sleep(random.randint(3, 5))

    try: driver.quit()
    except: pass print(f"\n{'='*50}\n完成! 成功: {success}, 失败: {fail}\n配置保存在: {OUTPUT_DIR}/\n{'='*50}")

if __name__ == "__main__":
    main()


感谢佬友的临时邮箱 gptmail 也感谢谷大善人不限域名大赦天下

特别感谢 2api 作者 大家也别忘了给他的帖子和仓库 star 一下~


📌 转载信息
原作者:
SnapSheep
转载时间:
2026/1/12 10:33:02

Git Hub

有空可以帮忙支持一下小白新人
** 有能力的老板可以资助一下 LDC,球球辣 **
50LDC 即可鼓励新人

半自动化是因为 API 化失败了,所以采用开浏览器半自动化的模式了。

欢迎有实力的佬友进行调优,本人是小白,用哈基米和 Codex 写的。写得很粗糙,不要见怪。

使用方法看 README

自备一个订阅机场,clash 核心自下。配置我个人是通过 clash 右键订阅机场,打开文件,复制到 local.yaml 覆盖全部使用。运行后,本地的 clash(或者其他代理)可以关了,或者切换为规则。不要开全局,系统代理。否则两个 clash 会冲突。

邮箱注册功能来自: DuckMail


@ 个人资料 - Syferie - LINUX DO

Business 登录地址:

后续登录也靠佬的前端:

运行界面:

账号密码保存在 csv 文件下:

待完善功能

| 功能 | 状态 | 说明 |

| 纯 API 注册 | 未实现 | Google 使用 reCAPTCHA Enterprise,纯 API 无法绕过

已知问题

| 问题 | 说明 |

| IP 封锁 | 部分代理节点被 Google 封禁,程序会自动切换节点 |

| 按钮匹配不正确 | 有大概率触发点击验证和重发验证码两个按钮,但是不影响功能 |

| 页面加载慢 | 网络不稳定时页面加载较慢,可能导致超时 |

| 存在僵尸进程 clash.exe| 在后台会占用资源,可自己手动进任务管理器结束 |

更新预告
大兵自助验证 API 已完成,完全全自动,使用方法参考市面上的 BOT,输入验证 URL 即可完成验证。这几天活动关了,等稳定了可能考虑开源给大家。


📌 转载信息
原作者:
Zooo1
转载时间:
2026/1/12 10:03:20

Gemini bussiness 自动刷新逻辑,接入 yescapture 打码服务,做到了基本 100% 的成功率

【回顾】 在之前的自动化注册或者刷新中会出现验证码发送错误的情况,原因在于获取的谷歌验证分数太低导致发送接口错误

【探索】通过抓包发现,以下接口就是发送邮件的接口

https://accountverification.business.gemini.google/_/IdentityPlatformFrontendUI/data/batchexecute?rpcids=IjXaFf&source-path=%2Fv1%2Fverify-oob-code&bl=boq_cloud-identity-identityplatform-frontend_20251210.10_p1&hl=en&rt=c

请求体为
f.req:[[["IjXaFf",,null,"generic"]]]

里面的 0cAFcWe 就是开头的验证

因此,只需要接入打码服务即可完成再次发送,测试结果为成功率基本 100%

完整 nodejs 代码如下:

 const fs = require('fs');
const os = require('os');
const path = require('path');
const axios = require('axios');
const express = require('express');
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
const { ImapFlow } = require('imapflow');
const { simpleParser } = require('mailparser');

puppeteer.use(StealthPlugin());

const app = express();
const port = 3000;

// =============================== // 配置项 // =============================== const WEBSITE_KEY = '6Ld8dCcrAAAAAFVbDMVZy8aNRwCjakBVaDEdRUH8';
const WEBSITE_URL = 'https://accountverification.business.gemini.google';

const sleep = (ms) => new Promise(r => setTimeout(r, ms));

function createTempUserDataDir() {
  return fs.mkdtempSync(path.join(os.tmpdir(), 'pptr-profile-'));
}

/**
* 邮件获取类
*/
class GeminiFetcher { constructor(email, clientId, refreshToken) { this.email = email; this.clientId = clientId; this.refreshToken = refreshToken; } async getAccessToken() { const params = new URLSearchParams({ client_id: this.clientId, grant_type: 'refresh_token', refresh_token: this.refreshToken }); const res = await axios.post('https://login.microsoftonline.com/consumers/oauth2/v2.0/token', params.toString()); return res.data.access_token; } async tryFetchOnce() { const token = await this.getAccessToken(); const client = new ImapFlow({ host: 'outlook.office365.com', port: 993, secure: true, auth: { user: this.email, accessToken: token }, logger: false }); await client.connect(); let code = null; try { for (const mailbox of ['INBOX', 'Junk']) { let lock; try { lock = await client.getMailboxLock(mailbox); const messages = await client.search({ all: true }); const lastUids = messages.slice(-5).reverse(); const tenMinutesAgo = Date.now() - 10 * 60 * 1000; for (let uid of lastUids) { let msg = await client.fetchOne(uid, { source: true }); let parsed = await simpleParser(msg.source); if (parsed.date.getTime() > tenMinutesAgo && parsed.subject && (parsed.subject.includes('Gemini') || parsed.subject.includes('Google'))) { const content = parsed.text + (parsed.html || ""); const match = content.match(/[A-Z0-9]{6}/); if (match) { code = match[0]; break; } } } } catch (e) { } finally { if (lock) lock.release(); } if (code) break; } } finally { await client.logout(); } return code; } } async function startPollingForCode(email, clientId, refreshToken) { const fetcher = new GeminiFetcher(email, clientId, refreshToken); for (let i = 1; i <= 10; i++) { try { console.log(`[${email}] 尝试获取邮件验证码 (${i}/10)...`); const code = await fetcher.tryFetchOnce(); if (code) { console.log(`[${email}] 成功获取到验证码: ${code}`); return code; } } catch (err) { console.error(`[${email}] 获取验证码报错: ${err.message}`); } await sleep(4000); } return null; } async function getCaptchaToken(apiKey) { try { console.log('🤖 正在向 YesCaptcha 请求人机识别 Token...'); const createResp = await axios.post('https://api.yescaptcha.com/createTask', { clientKey: apiKey, task: { websiteURL: WEBSITE_URL, websiteKey: WEBSITE_KEY, pageAction: 'verify_oob_code', type: 'RecaptchaV3TaskProxylessM1' } }); const taskId = createResp.data.taskId; for (let i = 0; i < 20; i++) { await sleep(3000); const resultResp = await axios.post('https://api.yescaptcha.com/getTaskResult', { clientKey: apiKey, taskId: taskId }); if (resultResp.data.status === 'ready') { console.log('🤖 YesCaptcha Token 获取成功'); return resultResp.data.solution.gRecaptchaResponse; } } } catch (error) { console.error(`❌ YesCaptcha 错误: ${error.message}`); return null; } } function patchPayload(rawBody, newToken) { const params = new URLSearchParams(rawBody); let fReq = params.get('f.req'); if (!fReq) return rawBody; const tokenRegex = /0[3c]AFc[a-zA-Z0-9_\-]{50,}/g; if (tokenRegex.test(fReq)) { params.set('f.req', fReq.replace(tokenRegex, newToken)); } return params.toString(); } // =============================== // 核心任务逻辑 // =============================== async function runLoginTask(accountData, apiKey) { const parts = accountData.split('----'); const [email, password, clientId, refreshToken] = parts; const userDataDir = createTempUserDataDir(); console.log(`🚀 [任务开始] 账号: ${email}`); let resolveCodeSent; const codeSentBarrier = new Promise((resolve) => { resolveCodeSent = resolve; }); let resolveAuthBarrier; const authBarrier = new Promise((resolve) => { resolveAuthBarrier = resolve; }); console.log('🌐 正在启动浏览器...'); const browser = await puppeteer.launch({ headless: "new", userDataDir, args: ['--no-sandbox', '--disable-setuid-sandbox', '--window-size=1280,800'] }); try { const page = await browser.newPage(); await page.setRequestInterception(true); page.on('request', req => { if (['image', 'media', 'font'].includes(req.resourceType())) return req.abort().catch(() => {}); req.continue().catch(() => {}); }); page.on('response', async res => { const url = res.url(); if (url.includes('batchexecute')) { try { const text = await res.text(); // 监控验证码发送状态 if (text.includes('LookupVerifiedEmail') || text.includes('SendVerificationCode')) { console.log('✅ [网络监控] 监听到 SendVerificationCode 响应,服务器已发信!'); resolveCodeSent(); } // 监控验证码报错 if (text.includes('CAPTCHA_CHECK_FAILED')) { console.log('⚠️ [网络监控] 检测到人机验证码拦截,准备打码补丁...'); const newToken = await getCaptchaToken(apiKey); if (newToken) { const originalRequest = res.request(); const newPostData = patchPayload(originalRequest.postData(), newToken); console.log('🔄 [补丁] 正在重发带 Token 的 Payload...'); await page.evaluate(async (u, h, b) => { await fetch(u, { method: 'POST', headers: h, body: b }); }, url, originalRequest.headers(), newPostData); resolveAuthBarrier(); } } else if (text.includes('inner_api_status')) { resolveAuthBarrier(); } } catch (e) { } } }); console.log('🍪 正在设置初始 XSRF Cookie...'); await page.goto('https://auth.business.gemini.google/', { waitUntil: 'domcontentloaded' }); await page.setCookie( { name: '__Host-AP_SignInXsrf', value: 'KdLRzKwwBTD5wo8nUollAbY6cW0', domain: 'auth.business.gemini.google', path: '/', secure: true }, { name: '_GRECAPTCHA', value: '09ABCL...', domain: '.google.com', path: '/', secure: true } ); const targetUrl = `https://auth.business.gemini.google/login/email?continueUrl=https%3A%2F%2Fbusiness.gemini.google%2F&loginHint=${encodeURIComponent(email)}&xsrfToken=KdLRzKwwBTD5wo8nUollAbY6cW0`; console.log('🔗 正在加载登录页面...'); await page.goto(targetUrl, { waitUntil: 'domcontentloaded' }); console.log('🖱️ 正在点击 [通过电子邮件发送验证码] 按钮...'); await page.waitForSelector('#sign-in-with-email', { visible: true }); await page.click('#sign-in-with-email'); console.log('🔎 等待验证码输入框出现...'); const inputSelector = 'input[jsname="ovqh0b"]'; await page.waitForSelector(inputSelector, { timeout: 30000 }); console.log('⏳ [关键等待] 正在等待发信确认信号 (由网络响应触发)...'); const waitStart = Date.now(); await Promise.race([codeSentBarrier, sleep(12000)]); console.log(`⏱️ 等待结束,耗时: ${Date.now() - waitStart}ms`); console.log('📫 开始爬取邮箱验证码...'); const code = await startPollingForCode(email, clientId, refreshToken); if (!code) throw new Error("获取验证码超时"); console.log('⌨️ 正在输入验证码并提交...'); await page.type(inputSelector, code, { delay: 100 }); await page.click('button[jsname="XooR8e"]'); console.log('🔄 等待登录跳转...'); await sleep(4000); if (page.url().includes('/admin/create')) { console.log('📄 进入创建页面,检测是否有 [同意] 按钮...'); const btn = await page.waitForSelector('button.agree-button', { visible: true, timeout: 5000 }).catch(() => null); if (btn) { console.log('🖱️ 点击同意按钮'); await btn.click(); await sleep(2000); } } console.log('🍪 正在通过 CDP 协议提取全量 Cookie...'); let hostCoses = '', secureCSes = ''; for (let i = 0; i < 15; i++) { const client = await page.target().createCDPSession(); const { cookies } = await client.send('Network.getAllCookies'); await client.detach(); for (const c of cookies) { if (c.name === '__Host-C_OSES') hostCoses = c.value; if (c.name === '__Secure-C_SES') secureCSes = c.value; } if (hostCoses && secureCSes) { console.log('✨ 核心 Cookie 提取完毕'); break; } console.log(`📭 第 ${i+1} 次提取 Cookie 未果,继续轮询...`); await sleep(1000); if (i === 5) { console.log('🔄 提取超时,尝试跳转业务主域名促活 Cookie...'); await page.goto('https://business.gemini.google/', { waitUntil: 'networkidle2' }).catch(() => {}); } } if (!hostCoses || !secureCSes) throw new Error('Cookie 提取失败'); console.log('🏁 [任务成功] 正在返回结果'); return `${email}|${password}|${hostCoses.trim()}::${secureCSes.trim()}`; } finally { console.log('🧹 正在关闭浏览器并清理临时文件...'); await browser.close(); try { fs.rmSync(userDataDir, { recursive: true, force: true }); } catch (e) {} } } app.get('/login', async (req, res) => { const { data, apikey } = req.query; if (!data || !apikey) return res.status(400).send('Missing params'); try { const result = await runLoginTask(data, apikey); res.send(result); } catch (err) { console.error(`❌ 接口报错: ${err.message}`); res.status(500).send(`Error: ${err.message}`); } }); app.listen(port, () => { console.log(); console.log(`🚀 服务运行中: http://localhost:${port}`); console.log(`📝 请求示例: /login?data=email----pass----id----token&apikey=xxx`); console.log(); });

运行成功后请求示例为:
http://localhost:3000/login?data=CharlesHoward4117@outlook.com----rrom1652910----dbc8e03a-b00c-46bd-ae65-b683e7707cb0----M.C539_BL2.0.U.-Cn78r6PhJ0VI48KtRppemAxUI038pVKjd9Kyu*lxTsFW9cyZqou7zcWsKmg0DdlxCURrppr3paaCrZHMIY1gzBcD4p*p*TQHz4DqDF0xeUTOtkTlpy!B6leXglSy3O1Uj9hDUkq3f!75ha4A0VrC7agSXDzUaV!tPIJ7AA6fgdKeehLjzhNaHr5XqvTM39Gr1OR9H8VnYBB!K6yGDAhWWsYd5blEfhqVoAzG3TBDTcdrho3fwU2uR8V8oVtJfQ*aGyw9XwCj*gIRq1SdfWR5h!PSZ4TuFSJVqeLB7qbIOHLfWPtVkz*ya6jxMX4DqJASLQIIILno1lJznm1VAeQJPze!REpnD9L9F9t!dwRwpmd1235SbqnYAEG5rFXKSOqikRjSYSWeCVmZYBkWSWBLEuQ$&apikey=c169a2dbd972acac69b4f30c52c060bfbbe0854f84831

其中 data 就是邮箱的基本信息,这里只适配了微软邮箱
apikey 就是 yes 的 apikey

默认如果浏览器可以成功发送则不调用 yes 打码服务,返回示例

CharlesHoward4117@outlook.com|rrom1652910|COS.AW82PoFnmTPemeKaOLiqi59wSPBs5Q6mSkgqGsk2OwOP0c_vBgAo4L3k8IdN-La_tMrJbjbatQy9Uw6QllD2VL0xdhdbG8Ks2tlCGGEfxZgj3FhTP2fNSeEfk3ed1PL_l6oTfMiLL5ivKwKCYE5sbuI::CSE.AdwtfTBBmOWOWWkad3G32S_ut5NlmYWQhJCRohzHwevu9ZpYyKrRHpviThBTJNh8_KdlBLAUbSQT5zD6RGoggxO8air-J0l9qO_XtmbdLhXYDOCmMdNgDFq40G1HmpgeGfUtXEVB-cT2lf33J9xSx_F0w9ZmWrrI96KJk8ijQ_qc5T5nt3grRfI5B9YpHHOww_Uqo14z0Yg1899rHDdNpgg9y_X9xK3nDn8C3lYKerslcKak12VC_Rxq9JJDYNsysUjhfNmyt-tyU9xLaJV_vR_FG7nnkO7bmRL664yEpAzRD0dB9ZnxXrCb45q1Q7HRs3jjxoId1DVYw2aSbU5URDDY-q5bCDbHModdg36rRuICHmxQQRsz39YivNknIDe7kvOnubDYU1M9wmhX7bsLkKawILuj0jwsqNRb0jh-phY3D8DZhydEHROjjba99MAsIvkH8ZytY_x3Aw

COS 与 CSE 的 cookie 都有返回,一个账户大概 30s 左右,可并发,一分钟基本可以刷新或者注册 40 个账户(并发 20)

欢迎更多开发者去完善自动化注册和刷新的逻辑…


📌 转载信息
转载时间:
2026/1/3 12:07:27