案例:自动化获取Google注册页面——selenium
前言
提示:通过案例掌握selenium语法
涉及技术:Python + Selenium
在本文中,我们将通过一个实际案例来学习如何使用Selenium自动化工具模拟Google账号注册流程。这个案例涵盖了Selenium的多种高级用法,包括元素定位、表单填写、下拉框操作、异常处理等,非常适合想要深入学习Web自动化的读者。
一、目标即结果
1. 目标:
自动化完成Google账号注册流程,包括填写个人信息、选择用户名、设置密码、验证手机号等步骤。
2. 提前了解网页信息
- 注册入口:https://accounts.google.com/signup
- 注册流程包含多个步骤:
- 填写姓名
- 填写生日和性别
- 选择Gmail地址
- 设置密码
- 电话号码验证
- 添加恢复邮箱(可选)
- 同意隐私政策和条款
3. 结果
成功完成Google账号注册流程,获取新的Gmail账号。
图片就不放了,不能过审
二、逐步分析
1. Selenium环境配置
首先,我们需要正确配置Selenium环境,包括导入必要的库和设置WebDriver:
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import TimeoutException, NoSuchElementException
# WebDriver 配置
options = webdriver.ChromeOptions()
# 更新 User-Agent 为最新版本
options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.7049.115 Safari/537.36")
# 禁用自动化标志
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
# 添加新的反自动化检测参数
options.add_argument("--disable-blink-features=AutomationControlled")
# 添加其他有用的配置
options.add_argument("--disable-notifications") # 禁用通知
options.add_argument("--disable-popup-blocking") # 禁用弹窗拦截
options.add_argument("--disable-infobars") # 禁用信息栏
options.add_argument("--start-maximized") # 启动时最大化窗口
# 设置 CDP 命令以修改 webdriver 相关参数
options.add_argument("--remote-debugging-port=9222") # 开启调试端口
# 使用 Service 对象指定路径
service = webdriver.ChromeService()
driver = webdriver.Chrome(service=service, options=options)
wait = WebDriverWait(driver, 11) # 设置显式等待,最多等待11秒
这段代码中,我们特别注意以下几点:
- 使用最新的User-Agent
- 禁用自动化标志,避免被网站检测
- 设置显式等待,提高脚本稳定性
2. 填写姓名
# 打开 Google 账号注册页面
signup_url = "https://accounts.google.com/signup"
driver.get(signup_url)
# 填写姓名
wait.until(EC.visibility_of_element_located((By.NAME, "firstName"))).send_keys(first_name)
wait.until(EC.visibility_of_element_located((By.NAME, "lastName"))).send_keys(last_name)
# 点击"下一步"按钮
next_button_xpath = "//button[.//span[contains(text(), 'Next') or contains(text(), '下一步')]]"
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
这里我们使用了两种元素定位方式:
- 通过NAME属性定位输入框
- 通过XPATH定位按钮,并兼容英文和中文界面
3. 填写生日和性别
# 选择月份
try:
month_dropdown_element = wait.until(EC.element_to_be_clickable((By.ID, "month")))
select_month = Select(month_dropdown_element)
select_month.select_by_value(birth_month_value)
except TimeoutException:
print("错误:在等待时间内未能找到或点击月份下拉框。")
driver.save_screenshot('error_month_dropdown_timeout.png')
raise
except NoSuchElementException:
print("错误:DOM中不存在ID为'month'的元素。")
driver.save_screenshot('error_month_dropdown_noelement.png')
raise
# 填写日期和年份
day_element = wait.until(EC.visibility_of_element_located((By.ID, "day")))
day_element.send_keys(birth_day)
year_element = wait.until(EC.visibility_of_element_located((By.ID, "year")))
year_element.send_keys(birth_year)
# 选择性别
gender_dropdown = wait.until(EC.element_to_be_clickable((By.ID, "gender")))
select_gender = Select(gender_dropdown)
select_gender.select_by_value(gender_value)
# 点击"下一步"
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
这部分代码展示了:
- 如何使用Select类操作下拉框
- 如何进行异常处理并保存截图
- 如何使用ID定位元素
4. 选择Gmail地址
# 尝试定位"创建自己的Gmail地址"选项
try:
create_own_radio_xpath = "//div[contains(text(), 'Create your own Gmail address')]/preceding-sibling::div//input[@type='radio']"
wait.until(EC.element_to_be_clickable((By.XPATH, create_own_radio_xpath))).click()
except (TimeoutException, NoSuchElementException):
print("未找到'创建自己的Gmail地址'单选按钮,假设可以直接输入用户名。")
# 输入期望的用户名
username_input = wait.until(EC.visibility_of_element_located((By.NAME, "Username")))
username_input.send_keys(desired_username)
# 点击"下一步"
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
这里展示了如何处理可能存在也可能不存在的元素,增强脚本的健壮性。
5. 设置密码
# 输入密码
password_input = wait.until(EC.visibility_of_element_located((By.NAME, "Passwd")))
password_input.send_keys(password)
confirm_password_input = wait.until(EC.visibility_of_element_located((By.NAME, "PasswdAgain")))
confirm_password_input.send_keys(password)
# 点击"下一步"
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
6. 电话号码验证
# 检查是否可以跳过电话验证
skip_button_xpath = "//button[.//span[contains(text(), 'Skip') or contains(text(), '跳过')]]"
try:
skip_button = driver.find_element(By.XPATH, skip_button_xpath)
if skip_button.is_displayed() and skip_button.is_enabled():
skip_button.click()
else:
raise NoSuchElementException
except NoSuchElementException:
# 输入电话号码
phone_input = wait.until(EC.visibility_of_element_located((By.ID, "phoneNumberId")))
phone_input.send_keys(phone_number)
# 点击"下一步"发送验证码
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
# 等待并输入验证码
code_input_name = "code"
wait.until(EC.visibility_of_element_located((By.NAME, code_input_name)))
verification_code = input("请输入收到的6位Google验证码: ")
driver.find_element(By.NAME, code_input_name).send_keys(verification_code)
# 点击"验证"按钮
verify_button_xpath = "//button[.//span[contains(text(), 'Verify') or contains(text(), '验证') or contains(text(), 'Next') or contains(text(), '下一步')]]"
wait.until(EC.element_to_be_clickable((By.XPATH, verify_button_xpath))).click()
这部分代码展示了:
- 如何处理可能的跳过选项
- 如何与用户交互获取验证码
- 如何使用复杂的XPATH定位按钮
7. 处理后续步骤和同意条款
# 处理恢复邮箱步骤
try:
wait.until(EC.element_to_be_clickable((By.XPATH, skip_button_xpath))).click()
except (TimeoutException, NoSuchElementException):
try:
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
except (TimeoutException, NoSuchElementException):
print("警告:未找到下一步按钮,流程可能已变化。")
# 滚动到页面底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(1)
# 点击"同意"按钮
agree_button_xpath = "//button[.//span[contains(text(), 'I agree') or contains(text(), '同意') or contains(text(), 'Create Account') or contains(text(), '创建帐号')]]"
wait.until(EC.element_to_be_clickable((By.XPATH, agree_button_xpath))).click()
这部分展示了:
- 如何使用JavaScript执行滚动操作
- 如何处理多语言界面的按钮
三、完整代码
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import TimeoutException, NoSuchElementException
# --- 配置 ---
# 将 'path/to/your/chromedriver' 替换为你的 ChromeDriver 实际路径
# 如果 chromedriver 在系统 PATH 中,可以简化为: driver = webdriver.Chrome()
#webdriver_path = 'path/to/your/chromedriver' # 例如: '/usr/local/bin/chromedriver' 或 'C:/webdrivers/chromedriver.exe'
# --- 测试数据 (使用占位符,实际应安全管理) ---
first_name = "Franken"
last_name = "Markeron"
# Google 可能会建议用户名,或让你自己创建
desired_username = f"{first_name.lower()[:3]}{last_name.lower()[:3]}" # 创建一个独特的用户名尝试
password = "MyFrankPassword123!" # 使用强密码
birth_month_value = "1" # <--- 假设你要选择 1 月 (January)
birth_day = "1"
birth_year = "1995"
# 性别选项的值可能因语言和 Google 的更新而变化,需要检查页面元素
# 可能的值: 'Female', 'Male', 'Rather not say', 'Custom' (对应的 value 可能是 1, 2, 3, 4 或其他)
gender_value = "3" # 示例: 'Rather not say' (假设其 value 是 '3')
# 电话号码 - 这是自动化的一大难点
# 你需要提供一个有效的、能接收短信的号码
phone_number = "YOUR_VALID_PHONE_NUMBER" # <--- 必须替换为真实有效的号码
# --- WebDriver 初始化 ---
options = webdriver.ChromeOptions()
# 更新 User-Agent 为最新版本
options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.7049.115 Safari/537.36")
# 禁用自动化标志
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
# 添加新的反自动化检测参数
options.add_argument("--disable-blink-features=AutomationControlled")
# 添加其他有用的配置
options.add_argument("--disable-notifications") # 禁用通知
options.add_argument("--disable-popup-blocking") # 禁用弹窗拦截
options.add_argument("--disable-infobars") # 禁用信息栏
options.add_argument("--start-maximized") # 启动时最大化窗口
# 设置 CDP 命令以修改 webdriver 相关参数
options.add_argument("--remote-debugging-port=9222") # 开启调试端口
# 使用 Service 对象指定路径 (推荐方式)
service = webdriver.ChromeService()
driver = webdriver.Chrome(service=service, options=options)
wait = WebDriverWait(driver, 11) # 设置显式等待,最多等待 20 秒
print("WebDriver 初始化完成。")
try:
# 1. 打开 Google 账号注册页面
print("正在打开 Google 注册页面...")
# 注意:URL 可能因地区而异,或 Google 可能更改入口
signup_url = "https://accounts.google.com/signup"
driver.get(signup_url)
print("页面已加载。")
# --- 填写姓名 ---
print("正在填写姓名...")
wait.until(EC.visibility_of_element_located((By.NAME, "firstName"))).send_keys(first_name)
wait.until(EC.visibility_of_element_located((By.NAME, "lastName"))).send_keys(last_name)
# 点击“下一步”按钮 (可能需要调整定位器)
# Google 的按钮有时没有 name 或 id,需要 XPath 或 CSS Selector
# 尝试 XPath: //button[.//span[contains(text(), 'Next')]] 或类似
next_button_xpath = "//button[.//span[contains(text(), 'Next') or contains(text(), '下一步')]]" # 适配英文和中文 '下一步'
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
print("姓名填写完成,已点击下一步。")
# --- 填写基本信息 (生日和性别) ---
# --- Birth Month ---
# !! 重要: 将月份改为对应的数字值 (1-12) !!
# 例如: January -> "1", February -> "2", ..., December -> "12"
#birth_month_value = "1" # <--- 假设你要选择 1 月 (January)
try:
# 等待下拉框元素变为可点击状态
month_dropdown_element = wait.until(EC.element_to_be_clickable((By.ID, "month")))
print("月份下拉框已找到且可点击。")
# 创建 Select 对象
select_month = Select(month_dropdown_element)
# 使用 value 属性来选择月份
print(f"尝试通过 value '{birth_month_value}' 选择月份...")
select_month.select_by_value(birth_month_value)
print(f"已选择月份,值为: {birth_month_value}")
except TimeoutException:
print(f"错误:在 {wait._timeout} 秒内未能找到或点击 ID 为 'month' 的月份下拉框。")
print("请检查:")
print("1. 页面是否已完全加载?")
print("2. ID 'month' 是否仍然正确?(检查浏览器开发者工具)")
print("3. 下拉框是否被其他元素遮挡?")
print("4. 下拉框是否在 iframe 内?(如果是,需要先切换到 iframe)")
driver.save_screenshot('error_month_dropdown_timeout.png')
raise # 重新抛出异常,中断脚本
except NoSuchElementException:
print(f"错误:DOM 中不存在 ID 为 'month' 的元素。请确认定位器正确。")
driver.save_screenshot('error_month_dropdown_noelement.png')
raise
except Exception as e:
print(f"选择月份时发生意外错误: {e}")
driver.save_screenshot('error_month_dropdown_other.png')
raise
# --- Birth Day and Year (保持不变,但也要确保 ID 正确) ---
try:
day_element = wait.until(EC.visibility_of_element_located((By.ID, "day"))) # ID 可能会变
day_element.send_keys(birth_day)
year_element = wait.until(EC.visibility_of_element_located((By.ID, "year"))) # ID 可能会变
year_element.send_keys(birth_year)
print("日期和年份已填写。")
except TimeoutException:
print("错误:填写日期或年份的输入框未在预期时间内可见。请检查 ID 'day' 或 'year' 是否正确。")
driver.save_screenshot('error_day_year_timeout.png')
raise
except Exception as e:
print(f"填写日期或年份时发生错误: {e}")
driver.save_screenshot('error_day_year_other.png')
raise
# --- Gender (假设之前的逻辑可能有效,但同样需要检查) ---
# ... (之前的性别选择代码) ...
# 确保性别选择的定位器和值也与当前页面匹配
try:
gender_value = "3" # 示例: 'Rather not say' (假设其 value 是 '3')
gender_dropdown = wait.until(EC.element_to_be_clickable((By.ID, "gender"))) # ID 可能会变
select_gender = Select(gender_dropdown)
select_gender.select_by_value(gender_value) # 假设我们知道 value
print(f"已选择性别,值为: {gender_value}")
except (TimeoutException, NoSuchElementException):
print("警告:无法找到 ID 为 'gender' 的下拉框,尝试定位单选按钮或其他元素。")
# 添加其他性别元素的处理逻辑...
# 如果找不到性别元素也可能导致后续失败,需要健壮处理
driver.save_screenshot('error_gender_not_found.png')
# 根据你的测试需求决定是否在此处 raise 异常
except Exception as e:
print(f"选择性别时发生错误: {e}")
driver.save_screenshot('error_gender_other.png')
# 根据你的测试需求决定是否在此处 raise 异常
# 点击“下一步”
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
print("生日和性别填写完成,已点击下一步。")
# --- 选择 Gmail 地址 ---
print("正在选择 Gmail 地址...")
time.sleep(2) # 等待建议加载或输入框出现
# Google 可能提供建议,或者让你创建自己的地址
# 假设我们要创建自己的地址 (可能需要先点击某个选项)
# 尝试定位 "Create your own Gmail address" 选项(如果存在)
try:
# 定位器需要根据实际页面调整
create_own_radio_xpath = "//div[contains(text(), 'Create your own Gmail address')]/preceding-sibling::div//input[@type='radio']"
wait.until(EC.element_to_be_clickable((By.XPATH, create_own_radio_xpath))).click()
print("已选择 '创建自己的 Gmail 地址' 选项。")
time.sleep(0.5)
except (TimeoutException, NoSuchElementException):
print("信息:未找到 '创建自己的 Gmail 地址' 单选按钮,假设可以直接输入用户名。")
# 输入期望的用户名
# 定位器通常是 name='Username' 或类似
username_input = wait.until(EC.visibility_of_element_located((By.NAME, "Username"))) # Name 可能会变
username_input.send_keys(desired_username)
# 点击“下一步”
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
print(f"尝试使用用户名 '{desired_username}',已点击下一步。")
time.sleep(2) # 等待用户名检查结果
# 检查用户名是否可用(可能会出现错误消息)
# 你需要添加逻辑来处理用户名已被占用的情况(例如,查找错误提示元素)
# --- 设置密码 ---
print("正在设置密码...")
# 定位器通常是 name='Passwd' 和 name='ConfirmPasswd'
password_input = wait.until(EC.visibility_of_element_located((By.NAME, "Passwd")))
password_input.send_keys(password)
confirm_password_input = wait.until(EC.visibility_of_element_located((By.NAME, "PasswdAgain")))
confirm_password_input.send_keys(password)
# 可能有一个“显示密码”的复选框,可以忽略或根据需要交互
# 点击“下一步”
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
print("密码设置完成,已点击下一步。")
# --- !!! 电话号码验证 !!! ---
# 这是自动化最难的部分,很可能会失败或需要人工干预
print("进入电话号码验证阶段...")
time.sleep(2) # 等待页面加载
# 检查是否需要电话号码(有时可以跳过,但越来越少见)
# 你需要检查页面上是否有 "Skip" 或 "跳过" 按钮
skip_button_xpath = "//button[.//span[contains(text(), 'Skip') or contains(text(), '跳过')]]"
try:
skip_button = driver.find_element(By.XPATH, skip_button_xpath)
if skip_button.is_displayed() and skip_button.is_enabled():
print("找到'跳过'按钮,尝试跳过电话验证...")
skip_button.click()
print("已点击'跳过'。")
else:
raise NoSuchElementException # 如果按钮不可见或不可用,则认为需要输入号码
except NoSuchElementException:
print("未找到可用的'跳过'按钮,需要进行电话验证。")
try:
# 输入电话号码
# 定位器可能是 ID 'phoneNumberId' 或其他
phone_input_id = "phoneNumberId" # ID 极有可能变化,需要检查
phone_input = wait.until(EC.visibility_of_element_located((By.ID, phone_input_id)))
phone_input.send_keys(phone_number)
print(f"已输入电话号码: {phone_number}")
# 点击“下一步”发送验证码
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
print("已点击下一步,请求发送验证码。")
# --- !!! 等待并输入验证码 (手动或外部服务) !!! ---
print("\n" + "="*40)
print("!!! 重要: Google 已发送验证码到你的手机 !!!")
print("!!! 脚本现在暂停,请手动查看短信并在此处输入验证码。")
print("="*40 + "\n")
# 定位验证码输入框 (ID/Name 可能会变)
code_input_name = "code" # 假设 name 是 'code'
wait.until(EC.visibility_of_element_located((By.NAME, code_input_name))) # 等待输入框出现
verification_code = input("请输入收到的 6 位 Google 验证码: ")
driver.find_element(By.NAME, code_input_name).send_keys(verification_code)
# 点击“下一步”或“验证”按钮
verify_button_xpath = "//button[.//span[contains(text(), 'Verify') or contains(text(), '验证') or contains(text(), 'Next') or contains(text(), '下一步')]]" # 可能有不同文本
wait.until(EC.element_to_be_clickable((By.XPATH, verify_button_xpath))).click()
print("验证码已提交。")
except (TimeoutException, NoSuchElementException) as e:
print(f"错误:在电话验证阶段查找元素失败: {e}")
print("自动化流程可能在此处中断。请检查页面元素定位器。")
# 可以在这里加截图或其他调试信息
driver.save_screenshot('error_phone_verification.png')
raise # 重新抛出异常,中断脚本
# --- 后续步骤 (可能包括添加恢复邮箱、同意条款等) ---
print("处理后续步骤(恢复邮箱、条款等)...")
time.sleep(3) # 等待下一页
# 添加恢复邮箱(通常可以跳过)
try:
# 定位恢复邮箱输入框 (如果存在)
# recovery_email_input = wait.until(EC.visibility_of_element_located((By.NAME, "recoveryEmail")))
# 如果你想添加: recovery_email_input.send_keys("your_recovery_email@example.com")
# 查找并点击 "Skip" 或 "跳过" 按钮
# 注意:这里的按钮可能与电话验证的 Skip 按钮不同,检查 XPath
skip_recovery_xpath = skip_button_xpath # 假设 XPath 相同,需要验证
wait.until(EC.element_to_be_clickable((By.XPATH, skip_recovery_xpath))).click()
print("已跳过添加恢复邮箱步骤。")
except (TimeoutException, NoSuchElementException):
print("信息:未找到恢复邮箱输入框或跳过按钮,可能流程已变化或直接进入下一步。")
# 如果没找到跳过,可能需要点击 'Next'
try:
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
print("未找到跳过,点击了下一步。")
except (TimeoutException, NoSuchElementException):
print("警告:也未找到下一步按钮,流程可能卡住或已变化。")
time.sleep(2)
# 添加电话号码(有时会再次询问,通常也可以跳过)
try:
# 查找并点击 "Skip" 或 "跳过" 按钮
skip_add_phone_xpath = skip_button_xpath # 假设 XPath 相同,需要验证
wait.until(EC.element_to_be_clickable((By.XPATH, skip_add_phone_xpath))).click()
print("已跳过再次添加电话号码步骤。")
except (TimeoutException, NoSuchElementException):
print("信息:未找到再次添加电话号码的跳过按钮,可能流程已变化或直接进入下一步。")
# 如果没找到跳过,可能需要点击 'Yes, I'm in' 或 'Next'
try:
# 定位器需要根据实际情况调整
yes_im_in_button_xpath = "//button[.//span[contains(text(), 'Yes, I’m in')]]"
wait.until(EC.element_to_be_clickable((By.XPATH, yes_im_in_button_xpath))).click()
print("未找到跳过,点击了 'Yes, I’m in' 或类似按钮。")
except (TimeoutException, NoSuchElementException):
print("警告:也未找到 'Yes, I’m in' 或下一步按钮,流程可能卡住或已变化。")
time.sleep(2)
# 查看账户信息(确认页面)
try:
print("正在查看账户信息确认页面...")
wait.until(EC.element_to_be_clickable((By.XPATH, next_button_xpath))).click()
print("已确认账户信息,点击下一步。")
except (TimeoutException, NoSuchElementException):
print("警告:未找到账户信息确认页面的下一步按钮,流程可能已变化。")
# --- 同意隐私政策和条款 ---
print("正在处理隐私政策和条款...")
time.sleep(3) # 等待页面完全加载,特别是底部的按钮
# 需要滚动到底部才能使“同意”按钮可点击
print("滚动到页面底部...")
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(1) # 等待滚动完成
# 点击“同意”或“创建账户”按钮
# 定位器可能变化,文本可能是 'I agree', 'Create Account', '同意', '创建帐号' 等
agree_button_xpath = "//button[.//span[contains(text(), 'I agree') or contains(text(), '同意') or contains(text(), 'Create Account') or contains(text(), '创建帐号')]]"
try:
wait.until(EC.element_to_be_clickable((By.XPATH, agree_button_xpath))).click()
print("已同意条款并点击创建账户按钮。")
except (TimeoutException, NoSuchElementException) as e:
print(f"错误:无法找到或点击同意按钮: {e}")
driver.save_screenshot('error_agreement.png')
raise
# --- 注册完成 ---
# 等待跳转到 Google 欢迎页面或仪表板
print("等待注册完成并跳转...")
# 等待某个明确的、注册成功后才会出现的元素,例如账户图标或欢迎信息
# 例如,等待右上角的账户图标 (aria-label 可能包含姓名或邮箱)
try:
account_icon_xpath = f"//a[contains(@aria-label, '{first_name}') or contains(@aria-label, '{desired_username}')]"
wait.until(EC.visibility_of_element_located((By.XPATH, account_icon_xpath)))
print("\n" + "="*40)
print(">>> Google 账号注册成功! <<<")
print(f"用户名: {desired_username}@gmail.com")
print(f"密码: {password}")
print("="*40)
# 可以在这里加截图
driver.save_screenshot('registration_success.png')
except TimeoutException:
print("错误:注册似乎已完成,但无法在目标页面上找到预期的确认元素。")
print("请手动检查浏览器状态。")
driver.save_screenshot('registration_maybe_finished.png')
# 保持浏览器打开几秒钟以便观察
print("测试脚本执行完毕,浏览器将在一分钟后关闭...")
time.sleep(60)
except Exception as e:
print(f"\n--- 脚本执行过程中发生错误 ---")
print(e)
# 尝试截屏记录错误发生时的状态
try:
timestamp = time.strftime("%Y%m%d-%H%M%S")
error_screenshot_path = f'error_screenshot_{timestamp}.png'
driver.save_screenshot(error_screenshot_path)
print(f"错误截图已保存至: {error_screenshot_path}")
except Exception as screen_err:
print(f"尝试截屏时也发生错误: {screen_err}")
finally:
# --- 清理 ---
if 'driver' in locals() and driver:
print("正在关闭 WebDriver...")
driver.quit()
print("WebDriver 已关闭。")
四、技术要点总结
-
元素定位技巧
- 使用多种定位方式:ID、NAME、XPATH
- 构建健壮的XPATH表达式,兼容多语言界面
- 处理动态变化的元素
-
等待策略
- 使用显式等待提高脚本稳定性
- 合理设置等待条件和超时时间
-
异常处理
- 捕获并处理常见异常:TimeoutException、NoSuchElementException
- 保存错误截图便于调试
-
交互技巧
- 处理表单输入
- 操作下拉框
- 执行JavaScript脚本
- 与用户交互获取验证码
-
反自动化检测
- 设置合适的User-Agent
- 禁用自动化标志
- 添加反检测参数
五、声明
以上内容仅供学习,请勿用于其他用途;因此产生的纠纷与本人无关。
本文通过Google注册流程的自动化案例,详细讲解了Selenium的高级用法。希望这个实例能帮助你更好地理解和掌握Selenium自动化测试技术。如有问题,欢迎在评论区留言讨论!