自动化实现web端Google SignUp——selenium

案例:自动化获取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秒

这段代码中,我们特别注意以下几点:

  1. 使用最新的User-Agent
  2. 禁用自动化标志,避免被网站检测
  3. 设置显式等待,提高脚本稳定性

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()

这部分代码展示了:

  1. 如何使用Select类操作下拉框
  2. 如何进行异常处理并保存截图
  3. 如何使用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()

这部分代码展示了:

  1. 如何处理可能的跳过选项
  2. 如何与用户交互获取验证码
  3. 如何使用复杂的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()

这部分展示了:

  1. 如何使用JavaScript执行滚动操作
  2. 如何处理多语言界面的按钮

三、完整代码

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 已关闭。")

四、技术要点总结

  1. 元素定位技巧

    • 使用多种定位方式:ID、NAME、XPATH
    • 构建健壮的XPATH表达式,兼容多语言界面
    • 处理动态变化的元素
  2. 等待策略

    • 使用显式等待提高脚本稳定性
    • 合理设置等待条件和超时时间
  3. 异常处理

    • 捕获并处理常见异常:TimeoutException、NoSuchElementException
    • 保存错误截图便于调试
  4. 交互技巧

    • 处理表单输入
    • 操作下拉框
    • 执行JavaScript脚本
    • 与用户交互获取验证码
  5. 反自动化检测

    • 设置合适的User-Agent
    • 禁用自动化标志
    • 添加反检测参数

五、声明

以上内容仅供学习,请勿用于其他用途;因此产生的纠纷与本人无关。


本文通过Google注册流程的自动化案例,详细讲解了Selenium的高级用法。希望这个实例能帮助你更好地理解和掌握Selenium自动化测试技术。如有问题,欢迎在评论区留言讨论!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值