杰瑞科技汇

Selenium Python教程怎么学?入门到实战指南?

Selenium Python 完整教程

目录

  1. 第一部分:入门准备

    Selenium Python教程怎么学?入门到实战指南?-图1
    (图片来源网络,侵删)
    • 什么是 Selenium?
    • 为什么选择 Selenium Python?
    • 环境搭建:安装 Python、Selenium 和浏览器驱动
    • 你的第一个 Selenium 脚本:打开一个网页
  2. 第二部分:核心元素定位

    • 为什么需要定位元素?
    • 单个元素定位方法 (8种)
    • 多个元素定位方法 (4种)
    • 定位策略最佳实践
  3. 第三部分:常用操作与交互

    • 浏览器操作 (打开、关闭、前进、后退)
    • 元素交互操作 (点击、输入、清除)
    • 获取元素信息 (文本、属性、CSS样式)
    • 等待机制 (显式等待 vs. 隐式等待)
  4. 第四部分:高级应用

    • 处 iframe 和框架
    • 处理弹窗
    • 处理下拉菜单
    • 文件上传
    • 执行 JavaScript
    • 截图
  5. 第五部分:项目实战与最佳实践

    Selenium Python教程怎么学?入门到实战指南?-图2
    (图片来源网络,侵删)
    • Page Object Model (POM) 设计模式
    • 使用 unittestpytest 框架
    • 代码示例:一个简单的登录测试
    • 运行测试并生成报告

第一部分:入门准备

什么是 Selenium?

Selenium 是一个用于 Web 应用程序测试的工具,它直接运行在浏览器中,就像真正的用户在操作一样,它可以模拟点击、输入、导航等用户行为,因此非常适合用于自动化测试、爬虫和数据抓取。

为什么选择 Selenium Python?

  • Python 语法简洁:Python 是一种易于学习和使用的编程语言,上手快。
  • 强大的社区支持:Python 拥有庞大而活跃的社区,遇到问题很容易找到解决方案。
  • 丰富的库生态:Python 有 unittestpytest 等成熟的测试框架,以及 requestsBeautifulSoup 等库,可以与 Selenium 无缝集成,构建强大的自动化解决方案。

环境搭建

步骤 1:安装 Python

如果你的电脑还没有安装 Python,请访问 Python 官网 下载并安装,安装时请勾选 "Add Python to PATH" 选项。

步骤 2:安装 Selenium 库

Selenium Python教程怎么学?入门到实战指南?-图3
(图片来源网络,侵删)

打开你的终端 (Windows 是 CMD 或 PowerShell,macOS/Linux 是 Terminal),运行以下命令:

pip install selenium

步骤 3:下载浏览器驱动

Selenium 本身不控制浏览器,它通过一个叫做 WebDriver 的“桥梁”来与浏览器通信,你需要为你的浏览器下载对应的驱动程序。

  • Chrome 浏览器驱动:

    1. 访问 Chrome for Testing availability
    2. 下载对应你 Chrome 浏览器版本的 chromedriver,最简单的方式是下载 win64 (或对应你系统的版本) 下的 chromedriver.exe
    3. 将下载好的 chromedriver.exe 文件放到你的 Python 脚本所在的同一个文件夹下,或者将其路径添加到系统的环境变量 PATH 中,为了方便,我们建议放在脚本同目录下。
  • Firefox 浏览器驱动:

    1. 访问 GeckoDriver 下载页面
    2. 下载对应你 Firefox 浏览器版本和操作系统的 geckodriver
    3. 同样,将其放在脚本同目录或系统 PATH 中。

你的第一个 Selenium 脚本

创建一个名为 first_script.py 的文件,并输入以下代码:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
# 1. 初始化 WebDriver,告诉 Selenium 使用哪个浏览器
# 确保 chromedriver.exe 在同目录下
driver = webdriver.Chrome()
# 2. 打开一个网页
driver.get("https://www.google.com")
# 3. 定位搜索框元素
# <input class="gLFyf" type="text" ...>
search_box = driver.find_element(By.NAME, "q") # 通过 name 属性定位
# 4. 在搜索框中输入 "Selenium"
search_box.send_keys("Selenium")
# 5. 模拟按下回车键
search_box.send_keys(Keys.ENTER)
# 6. 等待3秒,以便观察结果
time.sleep(3)
# 7. 关闭浏览器
driver.quit()

运行脚本:

在终端中,进入 first_script.py 所在的目录,然后运行:

python first_script.py

如果一切顺利,你的 Chrome 浏览器会自动打开,访问 Google,搜索 "Selenium",3 秒后自动关闭。


第二部分:核心元素定位

自动化测试的核心就是找到页面上的元素,然后对它进行操作,Selenium 提供了多种定位方式。

定位单个元素

假设有以下 HTML 代码:

<input id="user-name" class="form-control" type="text" name="username" placeholder="请输入用户名">
方法 描述 示例代码
find_element(By.ID, "value") 最推荐,通过元素的 id 属性定位,id 在页面中通常是唯一的。 driver.find_element(By.ID, "user-name")
find_element(By.NAME, "value") 通过 name 属性定位。 driver.find_element(By.NAME, "username")
find_element(By.CLASS_NAME, "value") 通过 class 属性定位,class 有多个空格分隔的值,只传其中一个即可。 driver.find_element(By.CLASS_NAME, "form-control")
find_element(By.TAG_NAME, "value") 通过 HTML 标签名定位,通常用于定位 <a>, <img>, <input> 等,但可能不唯一。 driver.find_element(By.TAG_NAME, "input")
find_element(By.XPATH, "value") 非常强大,通过 XPath 路径表达式定位,可以处理复杂的定位逻辑。 driver.find_element(By.XPATH, "//input[@id='user-name']")
find_element(By.CSS_SELECTOR, "value") 非常强大,通过 CSS 选择器定位,语法比 XPath 简洁,速度通常更快。 driver.find_element(By.CSS_SELECTOR, "#user-name")
find_element(By.LINK_TEXT, "value") 专门用于定位超链接 <a>,要求 href 属性的文本完全匹配。 driver.find_element(By.LINK_TEXT, "点击这里")
find_element(By.PARTIAL_LINK_TEXT, "value") 专门用于定位超链接,要求 href 属性的文本部分匹配。 driver.find_element(By.PARTIAL_LINK_TEXT, "这里")

定位多个元素

find_element 改为 find_elements,它会返回一个列表,如果找不到元素,返回空列表。

# 定位所有的 input 标签
all_inputs = driver.find_elements(By.TAG_NAME, "input")
# 定制所有的 class 为 "form-control" 的元素
all_controls = driver.find_elements(By.CLASS_NAME, "form-control")
# 遍历并操作找到的元素
for element in all_inputs:
    print(element.get_attribute('placeholder'))

定位策略最佳实践

  1. 优先级ID > Name > CSS Selector > XPath > Class Name > Tag Name
  2. 避免使用绝对 XPath:如 html/body/div/div/div/div/input,这种路径非常脆弱,页面结构一变就失效。
  3. 优先使用 CSS Selector:对于复杂的定位,CSS Selector 通常比 XPath 更简洁、性能更好。
  4. 组合使用:如果单个属性无法唯一定位,可以组合使用,By.CSS_SELECTOR, "input.form-control[type='text']"

第三部分:常用操作与交互

浏览器操作

driver = webdriver.Chrome()
# 打开网址
driver.get("https://www.example.com")
# 获取当前页面标题
print(driver.title) 
# 获取当前页面 URL
print(driver.current_url)
# 导航到另一个页面
driver.get("https://www.python.org")
# 后退
driver.back()
# 前进
driver.forward()
# 刷新页面
driver.refresh()
# 关闭当前标签页
driver.close()
# 关闭整个浏览器,并结束 WebDriver 会话
driver.quit() # 推荐,用这个

元素交互操作

# 假设我们已经定位到了一个输入框和一个按钮
search_box = driver.find_element(By.ID, "search")
submit_button = driver.find_element(By.ID, "submit")
# 在输入框中输入文本
search_box.send_keys("自动化测试")
# 清空输入框
search_box.clear()
# 点击按钮
submit_button.click()
# 模拟拖拽 (需要 from selenium.webdriver.common.action_chains import ActionChains)
# source = driver.find_element(By.ID, "draggable")
# target = driver.find_element(By.ID, "droppable")
# ActionChains(driver).drag_and_drop(source, target).perform()

获取元素信息

element = driver.find_element(By.ID, "user-info")
# 获取元素的文本内容 (在标签之间)
print(element.text)
# 获取元素的属性值
print(element.get_attribute("id"))     # 输出: user-info
print(element.get_attribute("class")) # 输出: user-class
print(element.get_attribute("value"))  # 输出: 张三
# 获取元素的 CSS 属性值
print(element.value_of_css_property("color"))
print(element.value_of_css_property("font-size"))
# 判断元素是否可见
print(element.is_displayed())
# 判断元素是否可用 (未被禁用)
print(element.is_enabled())
# 判断元素是否被选中 (用于 radio, checkbox)
print(element.is_selected())

等待机制

这是 Selenium 自动化测试中最重要的概念之一,现代网页大量使用 JavaScript,元素不会立即加载完成,如果代码不等待,直接操作不存在的元素,就会抛出 NoSuchElementException 错误。

  • 隐式等待

    • 作用于全局,在 find_element 期间生效。
    • 一旦设置,对整个 driver 对象的生命周期都有效。
    • 如果元素在指定时间内没找到,它会一直尝试,直到超时,然后才抛出异常。
    • 缺点:即使元素已经加载出来了,它还是会傻傻地等到超时。
    driver.implicitly_wait(10) # 全局等待10秒
    # 在这个 driver 实例下的所有 find_element 操作,最多等待10秒
    element = driver.find_element(By.ID, "some-slow-loading-element")
  • 显式等待

    • 强烈推荐,针对某个特定的元素进行等待。
    • 它会每隔一段时间(默认0.5秒)检查一次条件,一旦条件满足,就立即继续执行代码,否则直到超时。
    • 更智能、更精确,避免了不必要的等待。
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    try:
        # 等待最多10秒,直到 id 为 "some-slow-loading-element" 的元素可见
        element = WebDriverWait(driver, 10).until(
            EC.visibility_of_element_located((By.ID, "some-slow-loading-element"))
        )
        print("元素已找到并可见!")
    except Exception as e:
        print(f"等待超时,元素未找到: {e}")
    # 其他常用的 expected_conditions:
    # EC.presence_of_element_located((By.ID, "myid")) # 元素存在于 DOM 中
    # EC.element_to_be_clickable((By.ID, "myid"))    # 元素可点击
    # EC.title_contains("Selenium")                  # 页面标题包含特定文本

第四部分:高级应用

处理 iframe 和框架

如果目标元素在一个 <iframe><frame> 内,你必须先“切换”到这个框架里,才能定位到其中的元素。

# 1. 切换到 iframe
# 方法一:通过 id 或 name
driver.switch_to.frame("frame-name")
# 方法二:通过 WebElement 对象
# iframe_element = driver.find_element(By.ID, "frame-id")
# driver.switch_to.frame(iframe_element)
# 现在可以定位 iframe 内部的元素了
inner_element = driver.find_element(By.ID, "inner-element-id")
inner_element.click()
# 2. 操作完成后,切回主页面
driver.switch_to.default_content()
# 也可以切到父级 frame
# driver.switch_to.parent_frame()

处理弹窗

Selenium 可以处理三种类型的弹窗:alert, confirm, prompt

# 触发一个 alert 弹窗 (通过点击某个按钮)
# driver.find_element(By.ID, "alert-button").click()
# 切换到 alert
alert = driver.switch_to.alert
# 获取 alert 的文本
print(alert.text)
# 接受 alert (点击 "确定")
alert.accept()
# 或者 dismiss alert (点击 "取消")
# alert.dismiss()
# 对于 prompt,还可以输入文本
# alert.send_keys("我的输入")

处理下拉菜单

使用 Select 类来处理 <select> 标签创建的下拉菜单。

from selenium.webdriver.support.ui import Select
# 定位 select 元素
select_element = driver.find_element(By.ID, "country-select")
select = Select(select_element)
# 通过索引选择 (从0开始)
select.select_by_index(1)
# 通过 value 值选择
select.select_by_value("us")
# 通过可见文本选择
select.select_by_visible_text("United States")

文件上传

处理文件上传有两种常见方式:

  1. 普通 input[type="file"]:直接使用 send_keys 发送文件路径。

    file_input = driver.find_element(By.ID, "file-upload")
    # 注意:必须是文件的绝对路径
    file_path = "C:/Users/YourUser/Desktop/test_file.txt"
    file_input.send_keys(file_path)
  2. 非 input 元素(如按钮):这种情况下,需要先点击“上传”按钮,然后使用 pyautogui 等系统级工具来模拟键盘输入文件路径,这通常更复杂,且依赖于操作系统。

执行 JavaScript

Selenium 可以在浏览器中直接执行任意 JavaScript 代码,这对于处理一些棘手的场景非常有用。

# 滚动到页面底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 获取某个元素的文本(比 find_element 更快)
element = driver.find_element(By.ID, "my-id")
text = driver.execute_script("return arguments[0].textContent;", element)
print(text)
# 隐藏某个元素
driver.execute_script("document.getElementById('my-id').style.display = 'none';")

截图

在测试失败时截图是必不可少的。

try:
    # ... 你的测试代码 ...
    driver.find_element(By.ID, "non-existent-element").click()
except Exception as e:
    # 截取当前屏幕并保存
    driver.save_screenshot("error_screenshot.png")
    print(f"测试失败,已截图: {e}")

第五部分:项目实战与最佳实践

Page Object Model (POM) 设计模式

随着测试用例增多,如果所有代码都写在一起,会变得非常臃肿和难以维护,POM 是一种设计模式,它将页面和操作分离。

  • Page (页面类):负责存储页面的元素定位 (By) 和页面的基本操作方法。
  • Test (测试类):负责调用 Page 类中的方法来编写测试逻辑。

示例:一个登录页面

文件结构:

my_project/
├── pages/
│   ├── __init__.py
│   └── login_page.py
├── tests/
│   ├── __init__.py
│   └── test_login.py
└── requirements.txt

pages/login_page.py

from selenium.webdriver.common.by import By
class LoginPage:
    # 页面元素的定位器
    USERNAME_INPUT = (By.ID, "username")
    PASSWORD_INPUT = (By.ID, "password")
    LOGIN_BUTTON = (By.CSS_SELECTOR, "button[type='submit']")
    def __init__(self, driver):
        self.driver = driver
    def load(self):
        """打开登录页面"""
        self.driver.get("https://example.com/login")
    def login(self, username, password):
        """执行登录操作"""
        self.driver.find_element(*self.USERNAME_INPUT).send_keys(username)
        self.driver.find_element(*self.PASSWORD_INPUT).send_keys(password)
        self.driver.find_element(*self.LOGIN_BUTTON).click()

tests/test_login.py

import unittest
from selenium import webdriver
from pages.login_page import LoginPage
class TestLogin(unittest.TestCase):
    def setUp(self):
        """每个测试方法执行前的初始化操作"""
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(10)
        self.login_page = LoginPage(self.driver)
    def tearDown(self):
        """每个测试方法执行后的清理操作"""
        self.driver.quit()
    def test_successful_login(self):
        """测试登录成功场景"""
        self.login_page.load()
        self.login_page.login("standard_user", "secret_sauce")
        # 断言:登录成功后,URL 应该发生变化
        self.assertIn("dashboard", self.driver.current_url)
    def test_failed_login(self):
        """测试登录失败场景"""
        self.login_page.load()
        self.login_page.login("wrong_user", "wrong_pass")
        # 断言:登录失败后,应该看到错误提示
        error_message = self.driver.find_element(By.CSS_SELECTOR, ".error-message").text
        self.assertEqual("用户名或密码错误", error_message)
if __name__ == "__main__":
    unittest.main()

使用 pytest 框架

pytestunittest 更灵活、语法更简洁,上面的测试用例用 pytest 重写如下:

tests/test_login_pytest.py

import pytest
from selenium import webdriver
from pages.login_page import LoginPage
@pytest.fixture
def driver():
    """fixture,提供 driver 实例"""
    d = webdriver.Chrome()
    d.implicitly_wait(10)
    yield d
    d.quit()
def test_successful_login(driver):
    """测试登录成功场景"""
    login_page = LoginPage(driver)
    login_page.load()
    login_page.login("standard_user", "secret_sauce")
    assert "dashboard" in driver.current_url
def test_failed_login(driver):
    """测试登录失败场景"""
    login_page = LoginPage(driver)
    login_page.load()
    login_page.login("wrong_user", "wrong_pass")
    error_message = driver.find_element(By.CSS_SELECTOR, ".error-message").text
    assert "用户名或密码错误" == error_message

运行 pytest 测试:

pip install pytest
pytest

代码示例:一个简单的登录测试 (整合版)

这里是一个不使用 POM,但结构清晰的完整示例。

import unittest
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
class LoginTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.wait = WebDriverWait(self.driver, 10)
    def test_login_with_valid_credentials(self):
        # 1. 打开登录页面
        self.driver.get("https://the-internet.herokuapp.com/login")
        # 2. 使用显式等待定位用户名和密码输入框
        username_input = self.wait.until(
            EC.presence_of_element_located((By.ID, "username"))
        )
        password_input = self.wait.until(
            EC.presence_of_element_located((By.ID, "password"))
        )
        login_button = self.driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
        # 3. 输入有效凭据
        username_input.send_keys("tomsmith")
        password_input.send_keys("SuperSecretPassword!")
        # 4. 点击登录按钮
        login_button.click()
        # 5. 验证登录成功
        # 使用显式等待,直到成功消息出现
        success_message = self.wait.until(
            EC.visibility_of_element_located((By.ID, "flash"))
        )
        self.assertIn("You logged into a secure area!", success_message.text)
    def tearDown(self):
        self.driver.quit()
if __name__ == "__main__":
    unittest.main()

总结与进阶

  • 学习路径:从掌握基本定位和操作开始,然后深入理解等待机制,再学习 POM 设计模式,最后结合测试框架(unittestpytest)来构建一个健壮的自动化测试项目。
  • 官方文档:遇到问题时,Selenium Python 官方文档 是最好的参考资料。
  • 进阶方向
    • Selenium Grid:用于分布式执行测试,在多台机器上并行运行测试用例,大幅提升效率。
    • 无头模式:在不打开浏览器界面的情况下运行测试,适用于 CI/CD 环境。
      from selenium.webdriver.chrome.options import Options
      chrome_options = Options()
      chrome_options.add_argument("--headless")
      driver = webdriver.Chrome(options=chrome_options)
    • 与 API 测试结合:使用 requests 库先调用登录 API 获取 token,再在 Selenium 中使用 driver.add_cookie() 来实现免登录,提高测试效率。

希望这份详细的教程能帮助你顺利入门并精通 Selenium Python!祝你学习愉快!

分享:
扫描分享到社交APP
上一篇
下一篇