基于Selenium的ChatGPT非官方API实现原理与实战指南
1. 项目概述当官方API不可用时我们如何与ChatGPT对话最近在折腾一些自动化流程需要集成大语言模型的对话能力。OpenAI的官方API自然是首选但无论是出于成本、网络环境还是账号可用性的考虑有时候我们就是需要一个能绕过官方API、直接与ChatGPT网页版交互的方案。这就是我注意到Priyanshu-hawk/ChatGPT-unofficial-api-selenium这个项目的契机。本质上它是一个利用Selenium WebDriver自动化浏览器模拟真实用户操作从而与ChatGPT网页版进行交互的“非官方API”封装。简单来说这个项目解决了一个核心痛点在无法或不愿使用官方API的情况下如何以编程方式稳定、可靠地调用ChatGPT的对话能力。它把在浏览器里手动输入问题、点击发送、等待回复、提取答案这一系列操作全部用代码自动化了。听起来好像就是写个爬虫但实际做起来你会发现这里面坑多得超乎想象——动态加载的元素、反机器人检测、会话状态维持、网络延迟处理每一个都是拦路虎。这个项目相当于一个先行者帮你把这些坑都踩了一遍并封装成了相对易用的Python类。它适合谁呢我觉得有几类朋友可能会需要一是个人开发者或研究者想低成本实验ChatGPT的各种能力又不想频繁充值API额度二是需要构建一些内部自动化工具但公司政策或预算限制无法使用官方接口三是学习Web自动化和反反爬技术的极客想看看如何与一个复杂的现代Web应用进行交互。当然我必须强调使用这类方案需要你拥有合法的ChatGPT账号并严格遵守其服务条款任何用于批量营销、垃圾信息生成或绕过付费限制的滥用行为都是不可取的。2. 核心原理与架构拆解Selenium如何“扮演”一个真实用户这个项目的核心全在于“模拟”二字。它没有去破解任何通信协议也没有调用任何未公开的内部接口而是选择了一条“笨”但有效的路用程序控制一个真实的浏览器像人一样去操作网页。2.1 为什么是Selenium首先得理解为什么选Selenium。市面上Web自动化工具不少比如PuppeteerNode.js、Playwright跨语言都很强大。但这个项目选择了经典的Selenium我认为有几个考量一是生态成熟Python社区对Selenium的支持非常完善资料多遇到问题容易找到解决方案二是控制粒度Selenium提供了对浏览器近乎原生的控制能力对于需要精细操作如等待特定元素出现、处理复杂事件的场景很合适三是稳定性经过多年工业级应用的考验在长时间运行的自动化任务中相对可靠。当然Selenium也有缺点比如资源占用大、启动慢但对于“模拟用户对话”这个间歇性任务来说尚在可接受范围内。项目的核心架构可以理解为三层驱动层由Selenium WebDriver如ChromeDriver和实际浏览器如Chrome/Edge构成。这是执行所有操作的“手和眼睛”。操作封装层项目提供的Python类通常命名为ChatGPT或Chatbot。这一层封装了所有与ChatGPT网页交互的细节例如打开登录页、输入凭证、定位对话输入框、发送消息、轮询等待回复、提取回复文本、处理上下文新会话/继续会话等。业务调用层用户自己的脚本。调用封装层提供的简单方法如send_message(“Hello”)就能得到回复无需关心底层是如何点击和等待的。2.2 模拟登录与会话维持的挑战这是第一个技术难点。ChatGPT的登录页面不是简单的表单提交它可能涉及OAuth流程如通过Google、Microsoft账号登录、邮箱验证码、甚至人机验证Cloudflare Turnstile或reCAPTCHA。纯Selenium脚本很难自动处理所有这些情况尤其是人机验证几乎是自动化程序的死敌。因此常见的实践也是这个项目可能采用的策略是“半自动”或“Cookie复用”方案半自动登录脚本打开浏览器导航到登录页然后暂停等待用户手动完成登录操作包括处理可能的验证码。登录成功后脚本获取并保存浏览器当前的Cookies特别是包含认证令牌的__Secure-next-auth.session-token等。下次运行时可以直接注入保存的Cookies来恢复会话避免重复登录。Cookie持久化这是关键。项目需要实现Cookie的保存到文件如cookies.json和加载功能。通过driver.get_cookies()和driver.add_cookie()这两个Selenium API可以轻松实现。加载Cookie后访问ChatGPT主页如果Cookie有效就会直接跳转到聊天界面。注意Cookie有有效期。OpenAI的会话Cookie可能几天或几周后失效届时需要重新手动登录。自动化脚本必须包含对“登录状态失效”的检测逻辑比如检查页面是否跳转回了登录页并给出明确的提示。2.3 对话交互的核心逻辑登录成功后就进入了聊天界面。自动化对话的核心步骤是定位元素找到网页上的对话输入框一个textarea或div[contenteditable”true″]元素和发送按钮可能是一个按钮也可能是监听Enter键。现代前端框架如React生成的元素ID和类名经常变化所以不能依赖固定的选择器。更稳健的方法是使用XPath或CSS选择器结合部分文本、属性特征来定位例如//textarea[contains(placeholder, ‘Send a message’)]。发送消息使用Selenium的send_keys()方法向输入框输入文本然后模拟点击发送按钮或按下Enter键send_keys(Keys.RETURN)。等待回复这是最需要技巧的部分。发送消息后ChatGPT开始“思考”生成回复。页面会动态出现一个不断闪烁的光标或“正在输入”的提示最后才渲染出完整的回复。错误做法使用固定的time.sleep(10)。这要么等太久效率低要么等不够回复没生成完。正确做法使用“显式等待”。Selenium的WebDriverWait配合expected_conditions可以等待特定条件成立。例如等待“正在回复”的指示器出现表示开始生成。等待最后一个消息气泡代表ChatGPT的回复的类名或属性停止变化表示生成完毕。等待回复区域中出现一个特定的“结束标记”元素比如复制按钮。 项目需要精心设计这个等待条件以确保能准确捕获到完整的回复。提取回复回复生成后需要从正确的HTML元素中提取文本。同样不能依赖固定类名。通常需要定位到最后一个属于“助手”角色的消息容器然后获取其内部文本。要注意的是回复可能包含代码块有特殊样式项目可能需要处理是提取纯文本还是保留部分格式。2.4 处理流式输出与网络中断更高级的挑战是处理“流式输出”。ChatGPT网页版是逐词显示回复的。我们的自动化脚本是等全部生成完再提取这没问题。但如果想实时获取流式输出就需要监听页面DOM的细微变化这复杂度会指数级上升。另一个现实问题是网络不稳定。在长时间对话或生成长文时可能遇到网络错误。健壮的脚本需要包含重试机制。例如如果在等待回复时超时可以尝试刷新页面并恢复上下文如果项目实现了上下文管理或者至少抛出清晰的错误信息让调用者处理。3. 项目实战从零开始使用与核心代码剖析假设我们现在拿到了Priyanshu-hawk/ChatGPT-unofficial-api-selenium的代码该如何使用它它内部又是如何工作的我们来一步步拆解。3.1 环境准备与初始化首先你需要一个Python环境3.7并安装依赖。通常项目的requirements.txt会包含selenium4.0.0 webdriver-managerwebdriver-manager是个非常实用的库它能自动下载和匹配对应浏览器版本的WebDriver省去了手动管理的麻烦。初始化一个聊天机器人的代码可能长这样from chatgpt_selenium import ChatGPT # 初始化指定浏览器和Cookie文件路径 bot ChatGPT(browser’chrome’, cookie_path’./cookies.json’)在__init__函数里项目大概做了以下几件事使用webdriver-manager设置ChromeDriver路径。配置Chrome选项。这里至关重要因为默认的Selenium浏览器很容易被网站检测到是自动化工具。常见的反检测配置包括from selenium.webdriver.chrome.options import Options options Options() options.add_argument(‘–disable-blink-featuresAutomationControlled’) options.add_experimental_option(“excludeSwitches”, [“enable-automation”]) options.add_experimental_option(‘useAutomationExtension’, False) # 可能还会添加用户代理(User-Agent)字符串让它更像普通浏览器创建WebDriver实例。如果提供了cookie_path则尝试加载Cookies并导航到聊天页面验证登录状态如果没有或失效则可能打开登录页等待手动操作。3.2 核心方法send_message的幕后最核心的方法无疑是send_message(prompt)。我们来看看一个健壮的实现可能包含哪些步骤def send_message(self, prompt): # 1. 确保当前在聊天页面 if not self._is_on_chat_page(): self._go_to_chat_page() # 2. 定位输入框 input_box self._wait_for_element(‘//textarea[contains(placeholder, “Send a message”)]’, timeout10) # 先清空避免残留内容某些情况下可能有 input_box.clear() # 输入我们的提示词 input_box.send_keys(prompt) # 3. 定位并点击发送按钮或者模拟按Enter键 # 方法A找按钮 # send_button self.driver.find_element(By.XPATH, ‘//button[.//svg]’) # 通过内部图标找 # send_button.click() # 方法B更通用直接按Enter键 from selenium.webdriver.common.keys import Keys input_box.send_keys(Keys.RETURN) # 4. 等待“正在输入”指示器出现可选但能提升体验 try: WebDriverWait(self.driver, 5).until( EC.presence_of_element_located((By.CSS_SELECTOR, ‘[data-testid”in-progress”]’)) ) except TimeoutException: pass # 可能没有这个指示器继续 # 5. 等待回复完成 # 关键等待最后一个助手消息的“完整”状态 # 假设回复完成后消息容器会有一个特定的类或者会出现“复制按钮” reply_element WebDriverWait(self.driver, 120).until( # 设置一个较长的超时用于长文生成 EC.presence_of_element_located((By.XPATH, ‘//div[contains(class, “group final-completion”)]//div[class”markdown”]’)) # 或者等待“停止生成”按钮消失复制按钮出现 # EC.presence_of_element_located((By.XPATH, ‘//div[last()]//button[aria-label”Copy code”]’)) ) # 6. 提取文本 full_response reply_element.text # 可能需要处理换行和空格 # 如果回复中有代码块可能需要特殊处理 # 7. 返回回复 return full_response这段伪代码揭示了核心流程。其中_wait_for_element、_is_on_chat_page等都是项目内部封装的辅助函数用于提高代码复用性和健壮性。3.3 会话管理与上下文保持ChatGPT网页版支持多轮对话上下文长度有限例如GPT-3.5是4096个token。一个好的封装库应该能管理会话。新建会话调用类似bot.new_chat()的方法其实现可能是点击网页侧边栏的“New chat”按钮。切换会话更复杂需要操作网页的会话历史列表。通常这类非官方API不提供此功能因为UI操作复杂且易变。上下文长度库本身无法突破模型本身的上下文窗口限制。当对话轮次太多模型开始遗忘开头内容时用户需要主动新建会话来清空上下文。4. 深入进阶反反爬策略、稳定性优化与扩展思考直接用Selenium操作被目标网站识别并封禁的风险是存在的。ChatGPT虽然主要防滥用但过于频繁或不自然的请求也可能触发安全机制。4.1 规避自动化检测的实战技巧禁用WebDriver属性最基础的一步。如前所述通过options.add_experimental_option(“excludeSwitches”, [“enable-automation”])和options.add_argument(‘–disable-blink-featuresAutomationControlled’)来隐藏Selenium的自动化特征。修改navigator.webdriver属性在页面加载前执行JavaScript将navigator.webdriver设置为undefined。driver.execute_script(“Object.defineProperty(navigator, ‘webdriver’, {get: () undefined})”)使用真实用户配置文件不要每次都打开一个全新的、无缓存、无Cookie的浏览器实例。指定一个真实的用户数据目录user-data-dir让浏览器看起来像一个长期使用的正常用户。options.add_argument(f”user-data-dir{os.path.expanduser(‘~’)}/chrome_profile_for_chatgpt”)警告请确保这个配置文件只用于此自动化任务不要和你日常使用的浏览器混用以免冲突。模拟人类行为在操作中加入随机延迟time.sleep(random.uniform(0.5, 2.0))、随机的鼠标移动轨迹可通过ActionChains实现等。不要以固定的、机器般的速度连续操作。代理IP与用户代理轮换如果请求量非常大可以考虑使用代理池和轮换User-Agent字符串但这对于个人小规模使用通常不是必须的反而可能增加复杂度。4.2 提升稳定性的工程化考虑异常处理与重试网络请求、元素定位都可能失败。必须用try…except包裹核心操作并实现指数退避的重试逻辑。def send_message_with_retry(self, prompt, max_retries3): for attempt in range(max_retries): try: return self.send_message(prompt) except (TimeoutException, NoSuchElementException, WebDriverException) as e: if attempt max_retries – 1: raise wait_time 2 ** attempt random.random() print(f”Attempt {attempt1} failed, retrying in {wait_time:.1f}s…”) time.sleep(wait_time) # 可选刷新页面或重新初始化驱动 self.driver.refresh()心跳与保活如果需要长时间挂机需要处理会话超时。ChatGPT网页可能在一段时间无操作后自动登出。可以定期如每30分钟执行一个无害操作比如获取当前页面标题来保持会话活跃。资源清理确保在程序结束时或发生不可恢复错误时调用driver.quit()来关闭浏览器进程防止产生僵尸进程占用内存。4.3 功能扩展的可能性基于这个Selenium框架我们可以扩展出更多实用功能多模态支持ChatGPT网页版支持上传图片、文件。可以扩展send_message方法支持传入文件路径然后自动化点击上传按钮、选择文件的操作。模型切换在网页上切换GPT-3.5和GPT-4。可以通过模拟点击模型选择器来实现但这同样受限于UI的变化。对话记录导出自动将一段对话的历史记录导出为Markdown或文本文件。这需要遍历聊天记录DOM并解析。与官方API混合使用设计一个Fallback策略。优先使用官方API稳定、快速当达到速率限制或余额不足时自动切换到Selenium方案作为备份。5. 常见问题、故障排查与伦理边界在实际使用中你肯定会遇到各种各样的问题。下面是我总结的一些常见坑点和解决思路。5.1 典型错误与解决方案速查表问题现象可能原因排查步骤与解决方案NoSuchElementException(找不到元素)1. 页面未加载完成。2. ChatGPT前端UI更新选择器失效。3. 不在正确的页面如还在登录页。1. 增加显式等待时间确保元素加载。2.最重要使用浏览器开发者工具F12重新检查元素更新XPath或CSS选择器。优先使用相对稳定属性如>TimeoutException(等待回复超时)1. 网络慢或中断。2. ChatGPT生成长回复时间超过预设等待时间。3. 模型“卡住”不响应。1. 检查网络连接适当增加超时时间如从60秒加到120秒。2. 实现更智能的等待条件如等待“停止生成”按钮消失。3. 手动在浏览器中查看是否正常必要时刷新页面并重发消息。登录状态失效反复跳转登录页1. Cookie已过期。2. 保存的Cookie文件损坏或格式错误。3. IP或环境变化导致会话失效。1. 删除旧的cookies.json文件重新运行脚本进行手动登录。2. 检查Cookie文件内容是否为有效的JSON格式。3. 尝试在稳定的网络环境下操作。浏览器被检测为自动化工具浏览器指纹被识别。应用更完整的反检测配置见4.1节特别是使用user-data-dir和修改navigator.webdriver属性。回复内容截断或不完整提取回复文本时定位到了错误元素或元素内容未完全渲染。1. 在提取前增加一个短暂的固定延迟如time.sleep(0.5)。2. 改进选择器确保定位到包含完整回复文本的最外层元素。3. 尝试使用element.get_attribute(‘innerText’)代替element.text。5.2 伦理、合规与风险提示在使用此类非官方API时必须时刻保持清醒违反服务条款的风险OpenAI的用户协议明确禁止未经授权地抓取或自动化访问其服务。使用此方法可能导致你的账号被警告、限制甚至封禁。绝对不要用于生产环境或任何关键业务仅建议用于个人学习、研究和低频率的测试。对服务的压力自动化脚本的请求频率如果控制不当会对ChatGPT的服务器造成不必要的压力影响其他正常用户。务必在请求间添加合理的、随机的延迟模拟人类操作速度。隐私与安全你的对话数据通过自动化脚本发送需要信任代码不会泄露你的隐私。切勿使用来源不明的第三方封装库。自己审查代码或使用可信的开源实现。技术过时ChatGPT的网页界面变化频繁。今天能用的脚本明天可能就因为一个前端更新而完全失效。你需要有维护和更新选择器代码的心理准备和技术能力。最后一点个人体会Priyanshu-hawk/ChatGPT-unofficial-api-selenium这类项目是特定环境下的技术探索产物它展示了Web自动化技术的强大和脆弱。它最大的价值在于提供了一个清晰的思路和可参考的实现让我们理解如何与一个复杂的单页应用交互。但在实际需求面前如果条件允许官方API永远是更稳定、更高效、更合规的选择。这个项目更像是一个“技术备胎”或“学习样板”帮助我们理解当没有“正路”可走时如何利用现有工具小心翼翼地开辟一条“小路”。在使用的过程中保持对技术的敬畏和对规则的遵守才能走得更远。