本文将对 DeepSeek Chat 自动化交互脚本进行技术分析,包括代码结构、实现原理以及关键技术点。该脚本使用 Selenium 实现了对 DeepSeek Chat 平台的自动化登录和问答功能。
1. 代码结构概览
该脚本主要由以下几个部分组成:
- 环境准备与依赖导入:导入必要的库和模块,设置基本环境
- WebDriver 配置:设置和配置 Chrome WebDriver
- 登录功能:实现 DeepSeek Chat 的自动化登录
- 问答功能:向 DeepSeek Chat 提问并等待回答
5. 辅助功能:截图、问题加载、随机问题选择等
- 主函数:处理命令行参数并协调整个流程
2. 核心功能实现原理
2.1 WebDriver 配置 (setup_driver 函数)
def setup_driver():
"""Set up and return a configured Chrome WebDriver."""
chrome_options = Options()
# 配置Chrome选项
chrome_options.add_argument("--start-maximized")
chrome_options.add_argument("--ignore-certificate-errors")
# ... 其他配置选项 ...
# 使用本地ChromeDriver
chromedriver_path = os.path.join(os.getcwd(), "chromedriver.exe")
service = Service(executable_path=chromedriver_path)
driver = webdriver.Chrome(service=service, options=chrome_options)
# 设置页面加载超时
driver.set_page_load_timeout(60)
return driver
实现原理:
- 创建并配置 Chrome WebDriver,设置各种参数以提高稳定性和兼容性
- 使用本地的 ChromeDriver 而非自动下载,确保版本匹配
- 设置页面加载超时时间,防止长时间等待
2.2 登录功能 (login_to_deepseek 函数)
def login_to_deepseek(driver, phone, password):
"""Log in to DeepSeek Chat using phone number and password."""
# 尝试加载网页
driver.get("https://chat.deepseek.com/")
# 查找并点击登录按钮
login_button = WebDriverWait(driver, 3).until(
EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Log in') or contains(text(), '登录')]"))
)
login_button.click()
# 切换到密码登录
password_tab = WebDriverWait(driver, 3).until(
EC.element_to_be_clickable((By.XPATH, "/html/body/div[1]/div/div[2]/div/div/div[2]/div[2]"))
)
password_tab.click()
# 输入手机号和密码
phone_input = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "/html/body/div[1]/div/div[2]/div/div/div[4]/div[1]/div/input"))
)
phone_input.send_keys(phone)
# ... 输入密码、勾选协议、点击登录按钮 ...
# 等待登录完成
WebDriverWait(driver, 60).until(
EC.presence_of_element_located((By.XPATH, "//div[contains(@class, 'chat-container') or //textarea[contains(@placeholder, 'Send a message')]]"))
)
return True
实现原理:
- 使用 WebDriverWait 和 expected_conditions 等待页面元素加载
- 采用主要/备用方法策略,当精确 XPath 失败时尝试备用定位方法
- 在关键步骤进行截图,便于调试和问题排查
- 使用异常处理确保脚本不会因单点故障而完全失败
2.3 问答功能 (ask_question 函数)
def ask_question(driver, question):
"""Ask a question in the chat interface."""
# 定位并输入问题
input_area = WebDriverWait(driver, 30).until(
EC.presence_of_element_located((By.XPATH, "//textarea[contains(@placeholder, 'Send a message') or contains(@placeholder, '发送消息')]"))
)
input_area.send_keys(question)
# 勾选"深度思考"选项
deep_thinking_option = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "/html/body/div[1]/div/div[2]/div[2]/div/div/div[2]/div[2]/div/div/div[2]/div[1]"))
)
deep_thinking_option.click()
# 勾选"联网搜索"选项
web_search_option = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "/html/body/div[1]/div/div[2]/div[2]/div/div/div[2]/div[2]/div/div/div[2]/div[2]"))
)
web_search_option.click()
# 点击提交按钮
submit_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "/html/body/div[1]/div/div[2]/div[2]/div/div/div[2]/div[2]/div/div/div[2]/div[3]/div[2]"))
)
submit_button.click()
# 等待回答完成
WebDriverWait(driver, 600).until_not(
EC.presence_of_element_located((By.XPATH, "//div[contains(@class, 'loading') or contains(@class, 'typing')]"))
)
return True
实现原理:
- 定位输入框并输入问题
- 勾选特定选项("深度思考"和"联网搜索")
- 提交问题并等待回答完成
- 通过等待加载指示器消失来判断回答是否完成
- 同样采用主要/备用方法策略,提高脚本的鲁棒性
2.4 辅助功能
截图功能 (take_screenshot 函数)
def take_screenshot(driver, output_dir="screenshots", filename=None):
"""Take a screenshot of the current page."""
if not os.path.exists(output_dir):
os.makedirs(output_dir)
if filename is None:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"deepseek_chat_{timestamp}.png"
filepath = os.path.join(output_dir, filename)
driver.save_screenshot(filepath)
return filepath
实现原理:
- 创建截图目录(如果不存在)
- 生成带时间戳的文件名(如果未提供)
- 使用 WebDriver 的 save_screenshot 方法保存当前页面截图
问题加载功能 (load_questions_from_file 和 get_random_question 函数)
def load_questions_from_file(file_path):
"""从文件加载问题列表"""
with open(file_path, 'r', encoding='utf-8') as f:
questions = [line.strip() for line in f if line.strip()]
return questions
def get_random_question(questions_file):
"""从问题文件中随机选择一个问题"""
questions = load_questions_from_file(questions_file)
if not questions:
return None
return random.choice(questions)
实现原理:
- 从文本文件中读取问题列表,每行一个问题
- 提供随机选择问题的功能,增加交互的多样性
3. 主函数流程
def main():
# 解析命令行参数
parser = argparse.ArgumentParser(description="Automate DeepSeek Chat interactions")
# ... 参数定义 ...
args = parser.parse_args()
# 获取凭据
phone = os.getenv("DEEPSEEK_PHONE")
password = os.getenv("DEEPSEEK_PASSWORD")
# 获取问题列表
questions = []
# ... 从不同来源获取问题 ...
# 设置WebDriver
driver = setup_driver()
try:
# 登录
if login_to_deepseek(driver, phone, password):
# 处理每个问题
for i, question in enumerate(questions):
# 尝试多次提问,直到成功或达到最大尝试次数
for attempt in range(1, args.max_retries + 1):
if ask_question(driver, question):
break
# 等待一段时间再问下一个问题
if i < len(questions) - 1:
time.sleep(args.wait_time)
finally:
# 关闭浏览器
driver.quit()
实现原理:
- 解析命令行参数,支持多种问题输入方式(单个问题、多个问题、问题文件、随机问题)
- 从环境变量获取登录凭据
- 设置 WebDriver 并执行登录
- 循环处理每个问题,支持失败重试机制
- 确保无论执行结果如何,都会正确关闭浏览器
4. 技术亮点与挑战
4.1 鲁棒性设计
脚本采用了多层次的鲁棒性设计:
- 主要/备用元素定位策略:当精确 XPath 失败时,尝试使用备用方法(如文本内容、相对位置等)
- 全面的异常处理:捕获并记录所有可能的异常,防止脚本崩溃
3. 重试机制:对关键操作(如提问)实现了重试机制
- 详细的日志记录:记录每一步操作和可能的错误
- 截图功能:在关键步骤保存截图,便于调试和问题排查
4.2 元素定位策略
脚本使用了多种元素定位策略:
- 精确 XPath:首选使用精确的 XPath 路径
- 文本内容匹配:使用包含特定文本的元素定位
- 属性匹配:通过元素属性(如 placeholder、type 等)定位
- 相对位置定位:通过元素之间的相对位置关系定位
4.3 等待策略
脚本使用了 Selenium 的显式等待机制:
- WebDriverWait:等待特定条件满足后再执行下一步
- expected_conditions:定义等待条件(如元素可点击、元素存在等)
- 自定义超时时间:根据不同操作设置不同的超时时间
5. 可能的改进方向
- 模块化重构:将功能进一步模块化,提高代码复用性
- 配置文件支持:将硬编码的 XPath 和其他配置移至配置文件
- 更智能的等待机制:实现更智能的等待机制,如基于页面状态的动态等待
- 结果解析与保存:添加解析和保存 DeepSeek 回答的功能
- 代理支持:添加代理支持,解决可能的 IP 限制问题
- 多账户支持:支持多账户轮换使用,避免单一账户使用频率过高
- 更完善的错误恢复:实现更完善的错误恢复机制,如页面刷新、重新登录等
6. 总结
该脚本通过 Selenium WebDriver 实现了对 DeepSeek Chat 平台的自动化交互,包括登录和问答功能。脚本设计考虑了鲁棒性、可靠性和易用性,采用了多种元素定位策略和异常处理机制,确保在各种情况下都能正常工作。
通过命令行参数,脚本支持多种问题输入方式,可以满足不同的自动化需求。同时,详细的日志记录和截图功能也便于调试和问题排查。
这种自动化交互脚本在测试、数据收集、批量查询等场景中有广泛的应用价值,也为其他类似平台的自动化交互提供了参考实现。