Selenium是一个用于测试网站交互性的自动化测试工具。它提供了一种方法来编写程序化地操作网页的脚本。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。
一、selenium架构概述
Selenium 的架构主要由以下几个部分组成:
- Selenium Client Libraries:这是为不同编程语言(如 Python、Java、C#等)提供的客户端库,用于编写测试脚本。
- WebDriver:这是 Selenium 的核心组件,负责与浏览器进行直接通信。
- Browser Drivers:每种浏览器都有相应的驱动程序(如 ChromeDriver、GeckoDriver 等),它们充当 WebDriver与实际浏览器之间的桥梁。
- Browsers:实际运行的浏览器(如 Chrome、Firefox、Edge 等),执行由 Selenium脚本指定的操作。
二、selenium的工作流程
我们通过源码来看下selenium实现自动化测试的流程。
前提条件:
1、需要安装selenium库,这个应该大家都知道怎么安装
2、需要安装好chromedriver.exe驱动
- 启动chrome浏览器(相当于人为手动打开浏览器)
driver = webdriver.Chrome() # 注意:Chrome中的C一定要大写)
这行代码创建了一个 Chrome 浏览器的 WebDriver 实例对象。ChromeDriver 是一个与 Chrome 浏览器通信的驱动程序,它实现了 WebDriver 协议,允许 Selenium Python 客户端通过它与 Chrome 浏览器交互。
- 访问网址(相当于在浏览器上输入网址)
driver.get('http://www.baidu.com')
driver.get() 方法发送了一个命令给 Chrome 浏览器,要求它打开指定的 URL(这里是百度首页)。浏览器接收到命令后,加载页面并显示在窗口中。
- 查找搜索框的元素(相当于鼠标点击输入框)
driver.find_element('id','kw')
这一行代码试图查找页面中 id 为 ‘kw’ 的元素(百度搜索框)。
- 在搜索框中输入要查找的内容
driver.find_element('id','kw').send_keys('selenium学习方法')
这一行代码找到 id 为 ‘kw’ 的输入框元素(百度搜索框),然后向其发送键盘输入 ‘selenium学习方法’
- 点击百度一下
driver.find_element('id','su').click()
这一行代码找到 id 为 ‘su’ 的元素(百度搜索按钮),然后模拟用户点击操作
完整源码:
from selenium import webdriver
# 创建浏览器
driver = webdriver.Chrome()
# 访问网址
driver.get('http://www.baidu.com')
# 查找输入框的元素
driver.find_element('id','kw')
# 输入要查找的内容
driver.find_element('id','kw').send_keys('selenium学习方法')
# 点击百度一下
driver.find_element('id','su').click()
所以我们可以根据源码解释一下selenium的底层原理:
- 客户端脚本:Python 脚本中使用 Selenium 客户端库(from selenium import webdriver)来编写自动化测试脚本。
- WebDriver 实例化:webdriver.Chrome() 创建了一个 ChromeDriver 的实例,启动了 Chrome 浏览器。
- WebDriver 协议:客户端脚本通过 WebDriver 协议与 ChromeDriver 通信。例如,driver.get(‘http://www.baidu.com’) 发送了一个命令给 ChromeDriver,要求打开百度首页。
- 浏览器驱动程序:ChromeDriver 接收到命令后,启动 Chrome 浏览器,并加载指定的 URL。
- 页面操作:find_element_by_id 方法用于查找页面上的元素,send_keys 方法用于向输入框发送文本,click 方法用于点击按钮。
- 页面加载与渲染:浏览器根据命令执行操作,如加载页面、查找元素、模拟用户输入等。这些操作在浏览器内部被转化为底层的 DOM 操作。
- 返回结果:执行完毕后,ChromeDriver 将操作结果返回给 Python 脚本,脚本可以继续执行下一步操作或进行断言验证。
三、selenium的底层逻辑
通过上面的源码,我们大概清楚了selenium的一个工作原理,那接下来我们详细来看看selenium的底层API是如何来直接操作WebDriver 和 ChromeDriver的。
- 导入WebDriver类并创建实列
from selenium.webdriver.chrome.webdriver import WebDriver
# 创建 WebDriver 实例
driver = WebDriver()
- 解释一下:这里直接从 selenium.webdriver.chrome.webdriver 导入 WebDriver 类,而不是使用 webdriver.Chrome() 来创建实例。这种方式更加低级,直接操作 WebDriver 类。
- 底层原理:WebDriver 实例化时会启动 ChromeDriver,进而启动 Chrome 浏览器。
- 打开指定网址
# 访问网址
driver.execute('get', {'url': 'http://www.baidu.com'})
- 解释:使用 execute 方法直接发送 get 命令,参数为一个包含 URL 的字典。
- 底层原理:execute 方法通过 WebDriver 协议发送一个 HTTP POST 请求到 ChromeDriver,要求浏览器导航到指定的 URL。ChromeDriver 处理请求并指示浏览器加载页面。
- 查找元素
# 查找输入框元素
sele = driver.execute("findElement", {"using": "css selector", "value": '[id="kw"]'})['value']
- 解释:使用 execute 方法发送 findElement 命令,使用 CSS 选择器查找元素。返回的结果是一个字典,通过 [‘value’] 获取实际的元素对象。
- 底层原理:execute 方法发送一个 HTTP POST 请求到 ChromeDriver,使用 css selector 查找元素。ChromeDriver 解析请求并在页面中查找匹配的元素,返回元素的引用。
- 输入框发送键盘输入
# 向输入框发送键盘输入
sele._execute("sendKeysToElement", {"text": 'selenium原理', 'value': ""})
- 解释:使用元素对象的 _execute 方法直接发送 sendKeysToElement 命令,发送文本到输入框。
- 底层原理:_execute 方法通过 WebDriver 协议发送一个 HTTP POST 请求到 ChromeDriver,请求模拟键盘输入。ChromeDriver 将请求转化为浏览器内部的 DOM 操作,模拟用户在输入框中输入文本。
- 查找并点击百度一下
# 查找按钮元素
sele1 = driver.execute("findElement", {"using": "css selector", "value": '[id="su"]'})['value']
# 点击按钮
sele1._execute("clickElement")
- 解释:使用 execute 方法查找按钮元素,然后使用 _execute 方法发送 clickElement 命令,模拟点击操作。
- 底层原理:execute 方法发送 HTTP POST 请求查找元素,返回按钮元素的引用。_execute 方法发送 HTTP POST 请求,指示 ChromeDriver 模拟用户点击按钮。ChromeDriver 将请求转化为浏览器内部的 DOM 操作,执行点击操作。
完整源码:
from selenium.webdriver.chrome.webdriver import WebDriver
# 创建 WebDriver 实例
driver = WebDriver()
# 访问网址
driver.execute('get', {'url': 'http://www.baidu.com'})
# 查找输入框元素
sele = driver.execute("findElement", {"using": "css selector", "value": '[id="kw"]'})['value']
# 向输入框发送键盘输入
sele._execute("sendKeysToElement", {"text": 'selenium原理', 'value': ""})
# 查找按钮元素
sele1 = driver.execute("findElement", {"using": "css selector", "value": '[id="su"]'})['value']
# 点击按钮
sele1._execute("clickElement")
四、扩展:WebDriver协议
WebDriver 协议(也称为 Selenium WebDriver 协议或 JSON Wire Protocol)是一种用于在客户端和浏览器之间进行通信的协议。它定义了一组 API 和规范,使得不同的编程语言可以通过 WebDriver 客户端与各种浏览器进行交互。
- 协议的基本概念
HTTP/JSON: WebDriver 协议基于 HTTP 协议,并使用 JSON格式来传输数据。这使得不同的客户端和服务器能够使用标准的 HTTP 通信。
客户端-服务器架构: 在 WebDriver协议中,客户端(例如 Python、Java 等编程语言中的 Selenium 客户端库)向服务器(浏览器驱动)发送请求。浏览器驱动接收请求并控制实际的浏览器。
- 请求和响应
WebDriver 协议的核心在于它的请求和响应机制。客户端通过发送 HTTP 请求来控制浏览器,浏览器驱动程序处理这些请求并返回响应。
- 请求格式:
基本结构: 请求通常是一个 HTTP POST 请求,包含一个 URL(指定了要执行的操作)和一个 JSON 请求体,描述操作的参数。
创建一个新的浏览器会话的请求可能如下所示:
POST /session
Content-Type: application/json
{
"desiredCapabilities": {
"browserName": "chrome"
}
}
- 响应格式:
基本结构: 响应包含一个状态码和一个 JSON 数据体,数据体描述了操作的结果。
创建会话的响应可能如下所示:
HTTP/1.1 200 OK
Content-Type: application/json
{
"sessionId": "123456",
"value": {
"browserName": "chrome",
"version": "92.0.4515.107"
}
}
- 常用 API 操作
WebDriver 协议定义了一系列的 API 操作,常用的操作包括但不限于:
- 启动会话:
- POST /session: 创建新的会话。
- 导航:
- GET /session/{sessionId}/url: 导航到指定的 URL。
- 查找元素:
- POST /session/{sessionId}/element: 查找页面上的元素。
- 输入文本:
- POST /session/{sessionId}/element/{elementId}/value: 向指定元素发送文本。
- 点击元素:
- POST /session/{sessionId}/element/{elementId}/click: 点击指定元素。
- 获取页面内容:
- GET /session/{sessionId}/source: 获取当前页面的 HTML 源代码。
- 关闭会话:
- DELETE /session/{sessionId}: 结束会话并关闭浏览器。
- 状态码
WebDriver 协议使用标准的 HTTP 状态码来表示请求的结果。常用的状态码包括:
- 200 OK: 请求成功并返回结果。
- 404 Not Found: 请求的资源不存在(例如,指定的会话 ID 不存在)。
- 500 Internal Server Error: 服务器内部错误,处理请求时发生问题。
- 6xx Status Codes: WebDriver定义了一些特定的状态码,用于表示特定的错误情况,如元素不可见、元素不在 DOM 中等。
这篇文章是这几天学习selenium入门,总的来说懵懵懂懂的,也就说说对底层的东西如果想要理解得很透彻确实太难了,就是对原理的东西还是理解的不够透彻,如果文章哪里有错误,望大佬们纠正。