声明:个人用于技术研究,分享的只是成长历程,切勿用来做违法犯罪的事喔。
一、概要
与openAI(ChatGPT) 的爬虫对抗的爱恨情仇 。对于人机验证还无法完美避开,各位大佬有什么好方法可以告诉我一下,谢谢。。。
二、方案选择
- 注意了喔:有个国内的框架可以使用python脚本获取gpt使用的对话列表或者进行对话。最好不建议使用,我大概看了一下源码,其实是使用你自己的accesstoken调用api的形式,但是最终好像是转接到他们的服务中了,你的账号密码或者token有泄漏的风险。(个人拙见,可能存在偏差)
- API的形式脚本创建:还没有提供api创建的形式(pass)
- 通过接口抓取,模拟浏览器请求
a、ChatGPT的cookie会动态变动,且接口无法二次访问
b、追踪发现是每次请求会返回一个set_cookie的值,都会追加到下个请求的cookie中,并且请求是链式的操作,模拟比较复杂(主要还是搞不懂)
c、比如gpt列表接口,需要session接口返回的set_cookie,session接口的set_cookie又需要mine接口的set_cookie,最终在登录之前就已经出现set_cookie,追踪链路较长。 - selenium的方式模拟点击(最终选择方案,但是还有些问题)
a、ChatGPT的页面元素会是不是变化,比如gpt创建界面的confirm button的xpath会变化(出现过三次)
b、人机校验,目前正在困惑中,找到资料说Chrome和chromedriver版本过高可能出现,降版本尝试中。。。
有大坑:chrome_options.add_experimental_option(‘excludeSwitches’, [‘enable-automation’]) # 防止人机校验
但是吧,看到一篇文章说这个只适用与118版本之前的chromedriver,我下载的117,尝试结果报错:from invalid argument: unrecognized chrome option: excludeSwitches。然后发现119之前不支持chrome_options.add_experimental_option(“debuggerAddress”, “127.0.0.1:9222”),无奈又换回119,还得饱受人机验证的折磨。
c、元素加载不出来就点击出现的无响应问题(增加元素等待可解决)
d、模拟等了会被识别出人机,所以手动登录后续脚本点击。远程调用Chrome的方式
三、整体架构流程
- 登录ChatGPT
- 模拟点击创建操作
- 规避人机校验
四、技术细节
- 创建chrome_option,网上找的资料,一股脑全加了。
// An highlighted block
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222") # 开启远程debug模式,可以与开启的网页进行交互。即先登录,在执行后续脚本,规避chatgpt登录过程非法校验
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_argument("Mozilla/5.0 (Macintosh; ***/119.0.0.0 Safari/537.36")
chrome_options.add_argument('--no-sandbox') # 解决DevToolsActivePort文件不存在的报错
chrome_options.add_argument('window-size=1920x1080') # 指定浏览器分辨率
chrome_options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug
chrome_options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面
chrome_options.add_argument('blink-settings=imagesEnabled=false') # 不加载图片, 提升速度
chrome_options.add_argument("--lang=zh-CN")
chrome_options.add_argument(f'--proxy-server={"127.0.0.1:7890"}')
chrome_options.headless = True
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation']) # 规避人机校验,不知是否生效还未验证
# 创建browser
browser = webdriver.Chrome(options=chrome_options)
- 元素等待加载
// 创建等待元素的东东,只有元素加载出来才会进行后续操作,否则超时
web_driver_waits = WebDriverWait(browser, 60)
- 防止被检测,不知道有没有用,也加上
# 防止被监测
browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
- click
# 等待xpath加载出来之后,进行click事件操作
web_driver_waits.until(ec.presence_of_element_located(
(By.XPATH,"/html/body/div[1]/div[1]/div[1]/div/div/div/div/nav/div[3]/div/div/div/button"))).click()
- input标签上传文件/文本/图片都是这种形式
web_driver_waits.until(ec.presence_of_element_located(
(By.XPATH,"/html/body/div[1]/div[1]/div/div/div[2]/div[1]/div/div/div[2]/div/div/div[1]/input"))).
send_keys(input)
#对于隐藏隐藏的input标签的处理及上传操作
hidden_input = web_driver_waits.until(ec.presence_of_element_located(
(By.XPATH,"/html/body/div[5]/div/div[1]/input")))
browser.execute_script("arguments[0].style.display = 'block';", hidden_input)
hidden_input.send_keys(input)
五、小结
1、 下载chromedriver
2、运行chrome的远程控制debug模式,指定端口,要和option中配置一致。
./Google\ Chrome --remote-debugging-port=9222 --user-data-dir=“随便一个目录,保存用户相关信息”
3、手动登录(selenuim登录会出现人机检测问题,怀疑是js检测)
这个过程避不开才选择的这种方式,反编译chromedriver规避js校验也没有解决(有个国外老哥通过反编译chromedriver修改里面两个参数名称可行,但是我使用的版本较高,没有找到这两个参数,以失败告终)
4、执行脚本
- 完整代码
# This is a sample Python script.
from retry import retry
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.common.exceptions import TimeoutException
def create_robot():
print("start")
browser = create_driver()
web_driver_waits = WebDriverWait(browser, 60)
create_logic(browser, web_driver_waits)
fail_num = 0
@retry()
def create_logic(browser, web_driver_waits):
global fail_num
if fail_num <= 3:
try:
# 逻辑代码
web_driver_waits.until(ec.presence_of_element_located(
(By.XPATH,
"/html/body/div[1]/div[1]/div[1]/div/div/div/div/nav/div[3]/div/div/div/button"))).click()
except TimeoutException:
fail_num = fail_num + 1
print("retry:", fail_num)
browser = create_driver()
browser.get("url")
else:
raise
def create_driver():
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_argument("Mozilla/5.0 (Macinto*** Chrome/119.0.0.0 Safari/537.36")
chrome_options.add_argument('--no-sandbox') # 解决DevToolsActivePort文件不存在的报错
chrome_options.add_argument('window-size=1920x1080') # 指定浏览器分辨率
chrome_options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug
chrome_options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面
chrome_options.add_argument('blink-settings=imagesEnabled=false') # 不加载图片, 提升速度
chrome_options.add_argument("--lang=zh-CN")
chrome_options.add_argument(f'--proxy-server={"127.0.0.1:7890"}')
chrome_options.headless = True
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
browser = webdriver.Chrome(options=chrome_options)
# 防止被监测
browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
return browser
if __name__ == '__main__':
create_robot()
追加
奈何又出问题了,连续点击(gpt创建)的时候会出现部分元素xpath变化的情况
xpath: /html/div/div/div[num]/div…
xpath会一直变动
1、这个过程中穿插其他操作防止div_index变化
2、寻找xpath规律,每次更新xpath的值。