如何使用Python WebDriver爬取ChatGPT内容(完整教程)
大背景
虽然我们能用网页版chatGPT来聊天、写文章,但是我们采集大量的内容,就得不断地手动输入提问来获取答案,并且将结果复制到数据库来保存。如果整个过程能使用程序来做自然要节省很多的人力,精力和时间。
Python webdirver 模拟浏览器的方式来实现,刚好能实现以上功能。
另外之所以不选择API 是因为以下原因:
-
普通开发者(国内)获取API KEY 是有困难的,需要海外手机号 + 信用卡等一系列条件,但是如果只是网页端,我们仅仅需要登录或者未登录的方式就可以直接聊天
-
网页端无需调整各项参数,可以直接交互获取内容,而且内容质量更高!
当然,如果你有条件用API 或者直接通过 wss交互获取内容的,到这儿可以直接结束了。
完整源码在文章末尾哦!
基本环境要求
准备自己的梯子
ChatGpt属于海外项目,国内的小伙伴,翻墙得找好自己的梯子(代理),这里自己有啥用啥即可。
安装Python 环境
Python要求:3.10 +
安装 Python Selenium
pip install selenium
其他扩展库说明:取决于自己电脑缺什么就安装什么。后面完整代码会提供完整的 requirements.txt
浏览器
这里以Chrome浏览器为准。也就是你本地必须要安装Chrome浏览器,并且获取其安装路径。
比如:C:Program FilesGoogleChromeApplicationchrome.exe
操作系统
这里以 windows 作为开发环境。
开发工具
自己什么顺手用什么。
这里讲个程序界的笑话:传说级别的开发者据说用的记事本来开发。
实现过程
这里只介绍主要的代码
浏览器控制
使用程序实现浏览器的控制,这包括浏览器的打开,关闭,以及代理配置。
创建 browser_manage.py
import subprocess, datetime
import os, signal, psutildef run_cmd(port=9200):cmd = [# chrome浏览器路径。 必须为首个参数'C:/Program Files/Google/Chrome/Application/chrome.exe',# 【必要】设置浏览器端口'--remote-debugging-port=%s' % port,# 【必要】设置浏览器数据存储路径'--user-data-dir=D:/data',# 隐藏一些弹窗之类的信息'--hide-crash-restore-bubble',# 设置浏览器分辨率。如果要跑多个浏览器可以将每个浏览器设置小一些'--force-device-scale-factor=1',# 假设代理地址为 http://127.0.0.1:10809'--proxy-server=http://127.0.0.1:10809',# 默认打开一个空白页面'about:blank']process = subprocess.Popen(cmd)# 返回pid 用于关闭浏览器杀死进程return process.piddef kill_process(parent_pid):try:# 获取父进程parent = psutil.Process(parent_pid)# 获取父进程的所有子进程(包括孙子进程等)children = parent.children(recursive=True)# 创建一个包含父进程PID的列表pids_to_kill = [parent_pid]# 将所有子进程的PID添加到列表中pids_to_kill.extend(child.pid for child in children)# 遍历列表,对每个PID发送SIGKILL信号for pid in pids_to_kill:try:os.kill(pid, signal.SIGILL)except PermissionError:# 忽略权限错误,可能我们没有权限杀死某个进程print("close browser PermissionError")passexcept ProcessLookupError:# 忽略进程查找错误,进程可能已经自然死亡print("close browser ProcessLookupError")passexcept (psutil.NoSuchProcess, PermissionError):# 忽略错误,如果进程不存在或者没有权限print("close browser PermissionError1")passreturn Truedef open_browser():"""打开浏览器"""# 打开指定端口的浏览器pid = run_cmd(9200)def close_borwser():"""关闭浏览器"""# pid 为打开浏览器获取到的进程idkill_process(pid)# 执行open_browser() 打开浏览器,执行 close_borwser() 关闭浏览器
初始化selenium
创建爬虫脚本 spider.py
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from fake_useragent import UserAgent
import subprocess, datetimechrome_options = Options()
ua = UserAgent()
# 浏览器端口信息,取决于启动浏览器设置的端口
browser_host = 9200
browser_host= "127.0.0.1"random_ua = ua.random
chrome_options.add_argument(f'user-agent={random_ua}')# 设置要连接的浏览器端口信息
chrome_options.add_experimental_option("debuggerAddress","%s:%s" % (browser_host, browser_port))
driver = webdriver.Chrome(options=chrome_options)
进入到目标页面
文件:spider.py
# 页面加载等待:最多10s
driver.implicitly_wait(10)
driver.get("https://chat.openai.com/")
页面等待除了以上的方案也可以用其他方法:
# 等待某个元素可见
try:element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//h1")))print(element.text)
finally:driver.quit()# 或者直接
time.sleep(10)
发起询问
发起新的提问
每次提问都应该是基于一个新窗口来提问。如果你的问题需要上下文的基础来回答,可以直接跳过这里。

新询问输入框可以根据 button data-testid=“create-new-chat-button” 来定位。
# 定位到新聊天元素
new_chat_dom = driver.find_element(By.CSS_SELECTOR, '[data-testid="create-new-chat-button"]')
# 发起点击,进入新界面
new_chat_dom.click()
定位到输入框

输入框使用的是div contentediable作为文本域。其id为 prompt-textarea
# 因为元素提供了id,则直接通过id获取最方便
textarea_dom = driver.find_element(By.ID, "prompt-textarea")
创建询问队列
因为我们的目标是自动化对问题列表发起询问,而不是一次性询问。所以需要创建一个问题队列。问题队列可以来源于数据库或者队列文件。这里为了演示,直接创建一个list
ask_list = ["请用Python写一个平均等分list的方案","请写一个关于小猪佩奇的笑话,要求:小猪佩奇可能不是猪,而是河马, 100字","称赞一个女生长得漂亮,如何不直接称赞也能看出来在形容她漂亮"
]
输入问题
这里我们按行来输入:一次输入一行。
for msg in ask_list:# 将字符串按换行分割开ask_msg_arr = msg.split('
')for msg_line in ask_msg_arr:textarea_dom.send_keys(ask_msg_item)# 发送textarea_dom.send_keys(Keys.ENTER)# TODO 这里是后续获取数据,存储到数据库环节
等待数据响应
可以根据回答结束后,出现的交互按钮来确认是否回答完毕

idx = 0
while True:idx = idx + 1# 请求超时if idx > 180:breaktime.sleep(1)try:driver.find_element(By.CSS_SELECTOR, '[data-testid="bad-response-turn-action-button"]') breakexcept:continue
也可以使用以下方法来校验:
# 设置最大等待时间
wait = WebDriverWait(driver, 180)
# 等待直到元素出现
element = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '[data-testid="bad-response-turn-action-button"]')))
获取响应数据
通过 class=“markdown” 来获取数据。

idx = 0
while True:idx = idx + 1# 请求超时if idx > 180:breaktime.sleep(1)try:html_dom = driver.find_element(By.CSS_SELECTOR, '.markdown') breakexcept:continuecontent = html_dom .get_attribute('innerHTML')
数据清洗
具体的清洗规则,看具体的业务需求。大多数清洗,需要将一些总结类的语句删除,不合法的返回内容删除。这里不提供相应的清洗的方案。
至此,一个完整的数据链就已经完结。
完整源码
browser.py
import subprocess, datetime
import os, signal, psutildef run_cmd(port=9200):cmd = [# chrome浏览器路径。'C:/Program Files/Google/Chrome/Application/chrome.exe',# 【必要】设置浏览器端口'--remote-debugging-port=%s' % port,# 【必要】设置浏览器数据存储路径'--user-data-dir=E:/browser_data',# 隐藏一些弹窗之类的信息'--hide-crash-restore-bubble',# 设置浏览器分辨率。如果要跑多个浏览器可以将每个浏览器设置小一些'--force-device-scale-factor=1',# 假设代理地址为 http://127.0.0.1:10809'--proxy-server=http://127.0.0.1:10809',# 默认打开一个空白页面'about:blank']process = subprocess.Popen(cmd)# 返回pid 用于关闭浏览器杀死进程return process.piddef kill_process(parent_pid):try:# 获取父进程parent = psutil.Process(parent_pid)# 获取父进程的所有子进程(包括孙子进程等)children = parent.children(recursive=True)# 创建一个包含父进程PID的列表pids_to_kill = [parent_pid]# 将所有子进程的PID添加到列表中pids_to_kill.extend(child.pid for child in children)# 遍历列表,对每个PID发送SIGKILL信号for pid in pids_to_kill:try:os.kill(pid, signal.SIGILL)except PermissionError:# 忽略权限错误,可能我们没有权限杀死某个进程print("close browser PermissionError")passexcept ProcessLookupError:# 忽略进程查找错误,进程可能已经自然死亡print("close browser ProcessLookupError")passexcept (psutil.NoSuchProcess, PermissionError):# 忽略错误,如果进程不存在或者没有权限print("close browser PermissionError1")passreturn Truedef open_browser():"""打开浏览器"""# 打开指定端口的浏览器pid = run_cmd(9200)return piddef close_browser(pid):"""关闭浏览器"""# pid 为打开浏览器获取到的进程idkill_process(pid)pid = open_browser()
print(pid)# close_browser(25996)
spider.py
import time
import tracebackfrom selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys
from fake_useragent import UserAgent
import subprocess, datetime
import oschrome_options = Options()
ua = UserAgent()
# 浏览器端口信息,取决于启动浏览器设置的端口
browser_port = 9200
browser_host = "127.0.0.1"random_ua = ua.random
chrome_options.add_argument(f'user-agent={random_ua}')# 设置要连接的浏览器端口信息
chrome_options.add_experimental_option("debuggerAddress", "%s:%s" % (browser_host, browser_port))
driver = webdriver.Chrome(options=chrome_options)def open_gpt_page():driver.implicitly_wait(10)driver.get("https://chat.openai.com/")def new_chat():"""该方案当前只适用于已经登录到chatgpt的页面。不适用非的登录页面"""# 定位到新聊天元素new_chat_dom = driver.find_element(By.CSS_SELECTOR, '[data-testid="create-new-chat-button"]')# 发起点击,进入新界面new_chat_dom.click()def get_input_box():return driver.find_element(By.ID, "prompt-textarea")def get_ask_list():return ["请用Python写一个平均等分list的方案","请写一个关于小猪佩奇的笑话,要求:小猪佩奇可能不是猪,而是河马, 100字","称赞一个女生长得漂亮,如何不直接称赞也能看出来在形容她漂亮"]def get_response():# 等待响应完成idx = 0while True:idx = idx + 1# 请求超时if idx > 180:breaktime.sleep(1)try:driver.find_element(By.CSS_SELECTOR, '[data-testid="bad-response-turn-action-button"]')breakexcept:continue# 获取请求结果idx = 0content = Nonewhile True:idx = idx + 1# 请求超时if idx > 180:breaktime.sleep(1)try:html_dom = driver.find_element(By.CSS_SELECTOR, '.markdown')content = html_dom.get_attribute('innerHTML')breakexcept:continuereturn contentdef simulator(ask_msg):# 进入输入框并且点击print("进入输入框并且点击")textarea_dom = get_input_box()textarea_dom.click()# 发送ask_msg_arr = ask_msg.split('
')for msg_line in ask_msg_arr:textarea_dom.send_keys(msg_line)textarea_dom.send_keys(Keys.ENTER)# 获取响应content = get_response()# 保存数据到文件root_path = "./data"os.makedirs(root_path, exist_ok=True)full_path = f"{root_path}/%s.text" % int(time.time())with open(full_path, 'w', encoding='utf-8') as file:file.write(content)print("save success")def start():open_gpt_page()print("页面加载完毕")time.sleep(3)ask_list = get_ask_list()for ask_msg in ask_list:time.sleep(3)print("进入新的聊天")new_chat()print("current msg %s" % ask_msg)for retry in range(0,3):try:simulator(ask_msg)breakexcept:print(traceback.format_exc())time.sleep(10)passstart()
requirements.txt
fake_useragent==1.2.1
psutil==5.9.5
selenium==4.26.1
获取扩展源码
扩展源码是基于 chatgpt聊天页面,通过多个浏览器并行数据爬取,包含以下功能:
-
基于数据库创建问题队列
-
创建多个浏览器窗口多线程并行运行,提高产量和效率
-
解决人工校验-自动化进行人工校验
-
为多个浏览器配置不同的代理方案
-
代理配置,为浏览器自动化分配代理,
-
通过web端进行浏览器管理,代理管理,代理分配等
需要以上扩展源码,QQ:1186969412
相关文章:
如何使用Python WebDriver爬取ChatGPT内容(完整教程)
大背景 虽然我们能用网页版chatGPT来聊天、写文章,但是我们采集大量的内容,就得不断地手动输入提问来获取答案,并且将结果复制到数据库来保存。如果整个过程能使用程序来做自然要节省很多的人力,精力和时间。 Python webdirver …...
WSL切换默认发行版
查看适用于wsl的子系统有哪些: wslconfig /list 设置wsl的默认发行版 wslconfig /setdefault Ubuntu-20.04...
全志H618 Android12修改doucmentsui功能菜单项
背景: 由于当前的文件管理器在我们的产品定义当中,某些界面有改动的需求,所以需要在Android12 rom中进行定制以符合当前产品定义。 需求: 在进入File文件管理器后,查看...功能菜单时,有不需要的功能菜单,需要隐藏,如:新建窗口、不显示的文件夹、故代码分析以及客制…...
移动网络(2,3,4,5G)设备TCP通讯调试方法
背景: 当设备是移动网络设备连接云平台的时候,如果服务器没有收到网络数据,移动物联设备发送不知道有没有有丢失数据的时候,需要一个抓取设备出来的数据和服务器下发的数据的方法。 1.服务器系统是很成熟的,一般是linu…...
网络安全概论——入侵检测系统IDS
一、入侵检测的概念 1、入侵检测的概念 检测对计算机系统的非授权访问对系统的运行状态进行监视,发现各种攻击企图、攻击行为或攻击结果,以保证系统资源的保密性、完整性和可用性识别针对计算机系统和网络系统或广义上的信息系统的非法攻击,…...
Linux通信System V:消息队列 信号量
Linux通信System V:消息队列 & 信号量 一、信号量概念二、信号量意义三、操作系统如何管理ipc资源(2.36版本)四、如何对信号量资源进行管理 一、信号量概念 信号量本质上就是计数器,用来保护共享资源。多个进程在进行通信时&a…...
计算机网络基础图解
注:本文为来自 猿小许 的 “计算机网络” 相关系列文章合辑。 一、计算机网络概述 猿小许于 2021-06-03 18:39:47 发布 一、计算机网络的概念 1.1 计算机网络 概念 计算机网络: 是一个将分散的、具有独立功能的计算机系统,通过通信设备与…...
TDesign:NavBar 导航栏
NavBar 导航栏 左图,右标 appBar: TDNavBar(padding: EdgeInsets.only(left: 0,right: 30.w), // 重写左右内边距centerTitle:false, // 不显示标题height: 45, // 高度titleWidget: TDImage( // 左图assetUrl: assets/img/logo.png,width: 147.w,height: 41.w,),ba…...
hive注释comment中文乱码解决
问题描述 当使用以下命令查看表的元数据信息时出现中文乱码(使用的是idea连接hive) desc formatted test.t_archer; 解决 连接保存hive元数据的MySQL数据库,执行以下命令: use hive3; show tables;alter table hive3.COLUMNS_…...
电脑提示ntdll.d缺失是什么原因?不处理的话会怎么样?ntdll.dll文件缺失快速解决方案来啦!
电脑提示ntdll.dll缺失:原因、影响与解决方案 在日常的电脑使用中,我们偶尔会遇到一些令人困惑的系统错误,其中“ntdll.dll缺失”便是较为常见的一种。作为软件开发从业者,我深知这一错误给用户带来的不便,因此&#…...
MFC/C++学习系列之简单记录——序列化机制
MFC/C学习系列之简单记录——序列化机制 前言简述六大机制序列化机制使用反序列化总结 前言 MFC有六大机制,分别是程序启动机制、窗口创建机制、动态创建机制、运行时类信息机制、消息映射机制、序列化机制。 简述六大机制 程序启动机制:全局的应用程序…...
二十、服务发布Ingress
Ingress Kubernetes使用了一个Ingress策略定义和一个具体提供转发服务的Ingress Controller,两者结合,实现了基于灵活Ingress策略定义的服务路由功能。如果是对Kubernetes集群外部的客户端提供服务,那么IngressController实现的是类似于边缘路由器(Edge Router)的功能。需…...
计算机网络 八股青春版
什么是HTTP?HTTP和HTTPS的区别 HTTP HTTP是超文本运输协议,是一种无状态(每次请求都是独立的)的应用层协议。用于在客户端和服务器之间传输超文本数据(如HTML文件)。默认端口是80数据以明文形式传输&#…...
java全栈day18--Web后端实战(java操作数据库2)
前言:在上节入门程序当中我们见到了JDBC所提供的API,本节来详细说明一下。 一、JDBC--API详解 1.1DriverManager(驱动管理器) 回顾:作用获取连接,调用它里面的getConnection。即如下 作用 1.注册驱动解…...
electron-vite【实战】自定义标题栏【组件封装】(含异形标题栏,指定区域拖拽,窗口置顶,窗口最小化,窗口最大化,取消最大化,隐藏窗口到托盘等)
效果预览 技术要点 透明背景 src/main/index.ts 的 new BrowserWindow 中添加 transparent: true, // 设置窗口背景透明frame: false, // 隐藏窗口边框仅图标和标题部分可拖拽 仅图标和标题部分添加样式 drag .drag {-webkit-app-region: drag; }图标与标题栏的融合 标题栏的…...
vue2 项目webpack 4升5
项目背景 公司项目需要将进行微前端改造.主应用和子应用会需要共享依赖,考虑使用模块联邦进行依赖共享. 由于模块联邦要升级到webpack 5才能用,所以老项目要从webpack 4升级到webpack 5 实现思路 原来的项目用的是vue-cli 3,查了一下可以vue-cli 5用的就是webpack 5,所以可以…...
前端开发性能监控中的数据采集与性能调优方法
🌟 前端开发性能监控中的数据采集与性能调优方法 📖 前言 在现代 Web 应用中,性能是用户体验的关键因素之一。性能问题不仅会影响用户满意度,还可能导致业务损失。如何高效地监控前端性能并进行性能调优,成为每个开发…...
S32K324 Stack异常分析及解决方案
文章目录 前言正向排查尝试反向排查问题原因分析问题解决处理总结前言 在项目开发过程中,在一次软件变更时,调整了task优先级之后导致应用层软件中的float数据经常性的变为NAN,导致应用层功能失效。本文记录下这个bug的分析及解决过程。 正向排查尝试 由于问题复现的概率…...
[创业之路-202]:任正非管理华为的思想与毛泽东管理党、军队、国家的思想的相似性与差异性
目录 一、相似性 1、指导思想 2、管理策略 3、危机意识与自我否定 4、理想主义与奋斗精神 二、差异性 1、哲学基础与思想倾向 2、管理方法与策略 3、组织文化与价值观 一、相似性 任正非管理华为的思想与毛泽东管理党、军队、国家的思想在多个方面存在相似性。 以下…...
SAP PP ECN CSAP_MAT_BOM_MAINTAIN
刚开始的时候ECN总是加不上, 参考kimi给出的案例 点击链接查看和 Kimi 智能助手的对话 https://kimi.moonshot.cn/share/cth1ipmqvl7f04qkggdg 效果 加上了 FUNCTION ZPBOM_PLM2SAP. *"------------------------------------------------------------------…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
《Docker》架构
文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...
微服务通信安全:深入解析mTLS的原理与实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言:微服务时代的通信安全挑战 随着云原生和微服务架构的普及,服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
