当前位置: 首页 > news >正文

WEB UI自动化测试之Selenium框架学习

文章目录

  • 前言
  • 自动化测试介绍
  • Selenium简介
    • Selenium安装
    • 浏览器驱动安装与下载
  • 浏览器驱动初始化
    • 浏览器驱动管理
      • 自动管理驱动
      • 传统方法(指定驱动绝对/相对路径) 可选
    • 配置浏览器选项
  • Selenium 进行WEB自动化测试
    • 基本代码
    • 元素定位
      • 元素标签获取
      • 元素定位方法
        • id定位方法
        • name定位方法
        • class_name 方法
        • tag_name 方法
        • link_text
        • partial_link_text
        • xpath定位方法
        • CSS定位
      • 定位一组元素的方法
      • 元素定位方法的另一种写法
      • 元素定位实践经验
    • 元素等待与异常处理
      • 隐式等待
      • 显式等待
      • 强制等待
      • 异常处理 (根据实际情况,仅作介绍)
    • 模拟鼠标操作
      • 单击左键
      • 单击右键
      • 拖动
      • 鼠标悬停
    • 模拟键盘操作
    • 其他控制操作
      • 元素操作
      • 浏览器操作
    • 下拉框操作
    • 弹出框操作
    • 滚动条
    • frame/iframe表单
      • 连续切换frame/iframe
    • 多窗口切换
    • 截图操作
    • 验证码处理
    • 上传与下载文件
      • 上传文件
      • 下载文件
  • 参考目录


前言

阅读本文前请注意最后编辑时间,文章内容可能与目前最新的技术发展情况相去甚远。欢迎各位评论与私信,指出错误或是进行交流等。


自动化测试介绍

Selenium简介

Selenium是广泛使用的模拟浏览器运行的库,它是一个用于Web应用程序测试的工具。 Selenium测试直接运行在浏览器中,就像真正的用户在操作一样,并且支持大多数现代 Web 浏览器。Selenium 支持多种语言。目前,Selenium Web 驱动程序最受 Python 和 C#欢迎,本文以Python 为例。

官方地址:https://www.selenium.dev/

Selenium安装

# 使用pip安装最新版本
pip install selenium# 安装特定版本
pip install selenium==4.10.0# 在虚拟环境中安装(推荐)
python -m venv selenium_env
source selenium_env/bin/activate  # Linux/Mac
selenium_env\Scripts\activate.bat  # Windows
pip install selenium# 卸载:
pip uninstall selenium

浏览器驱动安装与下载

针对不同的浏览器,需要安装不同的驱动。安装驱动后,Selenium才能进行自动化操作。

注:从Selenium 4.0开始,提供了自动管理驱动的功能 但手动安装方法仍需了解:

以谷歌浏览器驱动为例:

1)、确定浏览器版本
在新标签页输入 chrome://settings/ 进入设置界面,然后选择 【关于 Chrome】。
或者点击chrome浏览器最右侧的“三个点”图标,然后点击弹出的“帮助”中的“关于Google Chrome”,查看自己的版本信息。
确定浏览器版本后,下载对应版本的 Chrome 驱动即可。在这里插入图片描述

获取谷歌浏览器的驱动地址:http://chromedriver.storage.googleapis.com/index.html

2)、获取浏览器的版本一定要选本地电脑谷歌浏览器版本号一样。注意:可能有些版本驱动没有一模一样的,可以选择用 . 号隔开的前三位必须相同,第四位可以选最接近你浏览器版本的那个数. 后面一步的是有,这里只有win32位,但是不影响,64位也能用这个驱动,但是显示的是64位,那么32位就不能用了,这里选择对应操作系统就可以了。
在这里插入图片描述
3)、下载完成后,压缩包内只有一个 exe 文件。
在这里插入图片描述
将 chromedriver.exe 保存到任意位置,并把当前路径保存到环境变量。
(建议将其保存到anaconda的安装目录下 或者 放到Python解释器根目录下,这样不需要再添加环境变量了)

添加成功后使用下面代码进行测试。

from selenium import webdriver
# Chrome浏览器
driver = webdriver.Chrome()

如果能弹出Chrome浏览器,则说明安装成功。

浏览器驱动初始化

浏览器驱动管理

通过驱动管理, 我们来用打开对应的浏览器。以谷歌浏览器驱动为例

自动管理驱动

from selenium import webdriver# 自动管理驱动
driver = webdriver.Chrome()

传统方法(指定驱动绝对/相对路径) 可选

from selenium import webdriver# 指定驱动路径
service = r'C:\Users\Gdc\.wdm\drivers\chromedriver\win32\96.0.4664.45\chromedriver.exe'
driver = webdriver.Chrome(service)

配置浏览器选项

from selenium import webdriver
from selenium.webdriver.chrome.options import Options# 创建Chrome选项对象
# 对所需进行的设置下进行add_argument 添加参数并设置值即可
chrome_options = Options()
chrome_options.add_argument("--headless")  # 无头模式
chrome_options.add_argument("--window-size=1920,1080")  # 设置窗口大小
chrome_options.add_argument("--disable-gpu")  # 禁用GPU加速
chrome_options.add_argument("--disable-extensions")  # 禁用扩展
chrome_options.add_argument("--proxy-server='direct://'")  # 代理设置
chrome_options.add_argument("--proxy-bypass-list=*")  # 绕过代理
chrome_options.add_argument("--start-maximized")  # 启动时最大化窗口
chrome_options.add_experimental_option("prefs", {"download.default_directory": "/path/to/download/directory",  # 设置下载目录"download.prompt_for_download": False,  # 禁用下载提示"download.directory_upgrade": True,"safebrowsing.enabled": True
})# 初始化WebDriver
driver = webdriver.Chrome(options=chrome_options)

Selenium 进行WEB自动化测试

基本代码

步骤:
1、导包
2、实例化浏览器对象
3、打开网页
4、测试代码
5、关闭网页
"""
web 自动化基本代码
"""
# 1、导包
from selenium import webdriver# 2、实例化浏览器对象:类名()
driver = webdriver.Chrome()# 3、打开网页
driver.get('https://www.baidu.com/')# 4、测试代码# 5、关闭网页
driver.quit() # 退出浏览器驱动

元素定位

为什么要使用元素定位?

计算机无法向人一样,所见即所得,因此需要先让计算机定位到要进行操作的元素,才能进行后续操作。

使用 selenium 定位页面元素的前提是你已经了解基本的页面布局及各种标签含义(HTML、CSS)

元素标签获取

​ 方法1)、谷歌使用 F12 进入开发者工具

以我们熟知的 百度为例,我们进入首页,按 【F12】 进入开发者工具。红框中显示的就是页面的代码,我们要做的就是从代码中定位获取我们需要的元素。
在这里插入图片描述
我们可以通过开发者工具所提供的功能, 如下图所示。点击该按钮,随后再点击想要定位的元素。
在这里插入图片描述
如下图所示。点击了该按钮后,鼠标悬停在该元素上方,最后我们点击鼠标左键。
在这里插入图片描述
所定位的元素的标签,会在代码区被高亮显示。
在这里插入图片描述

方法 2)、鼠标悬停元素上-点击右键-检查进入开发者工具
在这里插入图片描述
获取到所对应元素的标签
在这里插入图片描述

元素定位方法

定位元素方法通过什么找到元素?

通过标签名、属性、层级、路径
Selenium框架提供了八种元素定位方法,每种都有其适用场景:

定位方式:
1、id
2、name
3class_name(使用的是class属性进行定位)
4tag_name (标签名称)
5link_text(定位超链接 a 标签)
6partial_link_text(定位超链接 a 标签)
7xpath (路径)
8css (元素选择器)
id定位方法

说明:通过元素的id属性定位,id一般情况下在当前页面中是唯一。
提示:元素必须要有id属性。

# 方法:
find_element_by_id(元素value)# 演示
from selenium import webdriver
# 实例化浏览器对象
driver = webdriver.Chrome()
# 打开网址url
driver.get('https://www.baidu.com/')
# 通过元素 id 定位到它
driver.find_element_by_id('kw')

由于各种方法函数用法几乎相同,后续不再写演示

name定位方法

说明:通过元素的name属性来定位

提示:1、 元素必须要有name属性。
2、不同元素的 name 属性值可能相同, 最好确保其能够唯一指向目标元素之后使用
3、当页面内有多个元素的name 属性值相同的时候,执行该方法会默认获取第⼀个符合要求的元素。

driver.find_element_by_name('name的值')
class_name 方法

说明:通过元素的class属性来定位,一个元素的class属性可以有多个值。

提示:元素必须要有class属性。

注意:
1、方法名是class_name ,但实际是根据元素标签中的class属性
2、如果元素的 class 属性值存在多个值, 使用class_name 方法定位时, 只能使用其中的任意一个
3、不同元素的 class 属性值可能相同, 最好确保其能够唯一指向目标元素之后使用
4、当页面内有多个元素的 class 属性值相同的时候,执行该方法会默认获取第⼀个符合要求的元素。

driver.find_element_by_class_name
tag_name 方法

说明:通过元素的标签名称来定位,标签名(查看元素时尖括号(<)紧挨着的单词或字母就是标签名)
注意:1、由于一个页面中存在大量标签,并且重复性高,最好确保其能够唯一指向目标元素之后使用
2、如果页面中存在多个相同标签,默认返回第一个标签元素。

driver.find_element_by_tag_name("标签名")
link_text

说明:定位超链接标签

注意:1、只能使用精准匹配(a标签的全部文本内容)
2、该方法只针对超链接元素(a 标签),并且需要输入超链接的全部文本信息

driver.find_element_by_link_text('文本内容')
partial_link_text

说明:同样用于i定位超链接标签,但不强制要求a标签的全部文本内容,可以只传入a标签的局部文本,当然也可以传入全部文本。

注意:

  1. 可以使用精准或模糊匹配,如果使用模糊匹配最好使用能代表唯一的关键词
  2. 如果有多个值,默认返回第一个值
driver.find_element_by_partial_link_text('部分文本或全部文本')
xpath定位方法
# Xpath 定位方法:
driver.find_element_by_xpath('Xpath的策略')

说明:Xpath定位方法只有一种,但是策略有多种,不同策略参数的写法不同。

<html><head>...<head/><body><div id="csdn-toolbar"><div class="toolbar-inside"><div class="toolbar-container"><div class="toolbar-container-left">...</div><div class="toolbar-container-middle"><div class="toolbar-search onlySearch"><div class="toolbar-search-container"><input id="toolbar-search-input" autocomplete="off" type="text" value="" placeholder="C++难在哪里?">

以上方的XML文档为例,介绍Xpath常用的定位策略:

**绝对路径:**从最外层元素到指定元素之间所有经过元素层级的路径 ,绝对路径是以/html根节点开始,使用 / 来分割元素层级
根据上面的标签,定位最后一行 input 标签。
语法:driver.find_element_by_xpath(“/html/body/div/div/div/div[2]/div[2]/input”) (例子中div标签下有多个div标签,用div[2]索引的方式定位)
注意:绝对路径对页⾯结构要求比较严格

**相对路径:**匹配任意层级的元素,不限制元素的位置 ,相对路径是以 // 开始, // 跟元素名称,元素标签可以使用*代替(通配符)。
语法://input 或者 //*
driver.find_element_by_xpath(“//div[@id=‘csdn-toolbar’]/div/div/div[2]/div[2]/input”)
(没有从根节点开始,而是从id为’csdn-toolbar’的div标签开始向下找,采用了相对路径)

元素xpath路径获取
在这里插入图片描述
元素属性:
1、单独利用属性定位: 该方法可以使用目标元素的任意一个属性和属性值(需要保证唯⼀性)

# 语法1//标签名[@属性名='属性值']
# 语法2//*[@属性名='属性值']# 利用最后一个input标签的id属性来定位该元素
driver.find_element_by_xpath("//input[@id='toolbar-search-input']"))
driver.find_element_by_xpath("//*[@id='toolbar-search-input']"))

2、**层级与属性结合:**假如目标元素无法直接定位, 可以考虑先定位其父层级或祖辈层级, 再获取目标元素

# 语法举例://*[@id='父级id属性值']/input    (⽗层级定位策略/目标元素定位策略)
driver.find_element_by_xpath("//div[@id='toolbar-search-container']/input")
# 此处使用了最后一个input标签的父级属性查找策略,利用其id值进行定位,随后采用层级策略定位到input标签

3、**多个属性定位:**解决的是单个属性和属性值无法定位元素唯一性的问题。

# 语法: //*[@属性1="属性值1" and @属性2="属性值2"]

注:多个属性定位也可以和层级策略再进行结合使用

# xpath 扩展(还有其他很多策略, 根据需要进行使用)
1. //*[text()='文本信息'] # 定位文本值等于XXX的元素
另外一种写法 //a[contains(text(), '文本信息')]  提示:一般适合 p标签,a标签 
2. //*[contains(@属性,'属性值的部分内容')] # 定位属性包含xxx的元素提示:contains为关键字,不可更改。 
3. //*[starts-with(@属性,'属性值的开头部分')] # 定位属性以xxx开头的元素提示:starts-with为关键字不可更改 
4. //button[@type='submit' or @type='button']提示:属性定位可以使用 or 关键字 (也称为逻辑定位)
5. 轴定位是根据父节点,兄弟节点等节点来定位本节点,使用语法: 轴名称 :: 节点名称具体方法此处不再给出,可参考其他资料或官方文档
CSS定位

通过 css 的选择器语法定位元素

1、Selenium框架官方推荐使用 css ,因为定位效率高于xpath
2、 CSS是一种标记语言,焦点:数据的样式。控制元素的显示样式,就必须先找到元素,在css标记语言中找元素使用css选择器;
3、css的选择策略也有很多,但是无论选择哪一种选择策略都是用的同一种定位方法

# 方法:
driver.find_element_by_css_selector('css策略')
方法css策略举例描述
id 选择器#toolbar-search-input选择 id = ‘toolbar-search-input’ 的元素
class 选择器.toolbar-search-container选择 class = ‘toolbar-search-container’ 的元素,如果元素具有多个class属性值,需要全部输入
**选择所有元素
标签选择器input选择所有 <input> 元素
属性选择器type=‘text’选择 type = ‘text’ 的所有元素,input[name^=‘user’] # 属性值以user开头;input[name$=‘name’] # 属性值以name结尾;input[name*=‘erna’] # 属性值包含erna
组合选择器form input[type=‘text’]form标签后 属性type为text的input标签(采用了标签选择器、属性选择器两种策略结合)
element>elementdiv>input选择父元素为 <div> 的所有 <input> 元素
element+elementdiv+input选择同一级中在 <div> 之后的所有 <input> 元素

css的路径获取
在这里插入图片描述

定位一组元素的方法

​前文我们定位元素方法的是 driver.find_element_by_xxx
Selenium 同样提供了 driver.find_elements_by_xxx这种element后面带s的方法。执行结果返回的是列表类型,里面的数据是多个元素对象,用于定位多个满足查找条件的元素。

Selenium 中提供的定位一组元素的方法有以下:

find_elements_by_id()
find_elements_by_name()
find_elements_by_class_name()
find_elements_by_tag_name()
find_elements_by_xpath()
find_elements_by_css_selector()
find_elements_by_link_text()
find_elements_by_partial_link_text()

元素定位方法的另一种写法

上文介绍了八类元素定位的方法,但Selenium提供了另外一种写法。统一使用一种方法,元素定位方法作为参数输入。
语法:driver.find_element(方法, 方法所需参数)

方法例子
IDfind_element(by=By.ID, “具体参数”)
NAMEdriver.find_element(By.NAME, “具体参数”)
CLASS_NAMEfind_element(By.CLASS_NAME, “具体参数”)
TAG_NAMEfind_element(By.TAG_NAME, “具体参数”)
LINK_TEXTfind_element(By.LINK_TEXT, “具体参数”)
Partial Link Text定位(部分匹配)find_element(By.PARTIAL_LINK_TEXT, “具体参数”)
CSS选择器find_element(By.CSS_SELECTOR, “css选择器策略”)
XPathfind_element(By.XPATH, “xpath策略”)

元素定位实践经验

1、性能优化顺序:ID > Name > CSS > XPath
2、避免使用:绝对XPath路径(容易失效)
3、推荐使用:

  • 有意义的ID和名称属性
  • 短而明确的CSS选择器

元素等待与异常处理

1、为什么要设置元素等待?
很多页面都使用 ajax 技术,页面的元素不是同时被加载出来的,定位这些尚在加载的元素,会导致报错。
页面加载和元素渲染需要时间。
​由于电脑配置或网络原因,在查找元素时,元素代码未在第一时间内被加载出来,而抛出未找到元素异常。

所以,这种情况下需要设置延时,进行元素等待。

2、什么是元素等待?
元素在第一次未找到时,元素等待设置的时长被激活,如果在设置的有效时长内找到元素,继续执行代码,如果超出设置的时长未找打元素,抛出未找到元素异常。

webdriver 中的等待分为 显式等待 和 隐式等待。

隐式等待

隐式等待是指定一个超时时间,如果超出这个时间指定元素还没有被加载出来,就会抛出 NoSuchElementException 异常。
隐式等待是全局性的,即运行过程中,如果元素可以定位到,它不会影响代码运行,但如果定位不到,则它会以轮询的方式不断地访问元素直到元素被找到,若超过指定时间,则抛出异常。
使用 implicitly_wait() 来实现隐式等待,使用难度相对于显式等待要简单很多。

示例:打开个人主页,设置一个隐式等待时间 5s,通过 id 定位一个不存在的元素,最后打印 抛出的异常 与 运行时间。

from selenium import webdriver
from time import timedriver = webdriver.Chrome()
driver.get('https://blog.csdn.net/qq_43965708')start = time()
driver.implicitly_wait(5)
try:driver.find_element_by_id('kw')
except Exception as e:print(e)print(f'耗时:{time()-start}')

在这里插入图片描述
代码运行到 driver.find_element_by_id(‘kw’) 这句之后触发隐式等待,在轮询检查 5s 后(超过最大等待时间)仍然没有定位到元素,抛出异常。

显式等待

显式等待:设置一个超时时间,每隔一段时间就去检测一次该元素是否存在(相比于隐式等待,显示等待是针对于某一个元素的),如果存在则执行后续内容,如果超过最大时间(超时时间)则抛出超时异常(TimeoutException)。显示等待需要使用 WebDriverWait,同时配合 until 或 not until 。

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)

  • driver:浏览器驱动
  • timeout:超时时间,单位秒
  • poll_frequency:每次检测的间隔时间,默认为0.5秒
  • ignored_exceptions:指定忽略的异常,如果在调用 until 或 until_not 的过程中抛出指定忽略的异常,则不中断代码,默认忽略的只有 NoSuchElementException 。

until(method, message=’ ‘)
until_not(method, message=’ ')
显示等待WebDriverWait,需要搭配until、until_not使用

  • method:指定预期条件的判断方法,在等待期间,每隔一段时间调用该方法,判断元素是否存在,直到元素出现。until_not 正好相反,当元素消失或指定条件不成立,则继续执行后续代码
  • message: 如果超时,抛出 TimeoutException ,并显示 message 中的内容

下面写一个简单的例子,帮助我们理解。这里定位一个页面不存在的元素,抛出的异常信息正是我们指定的内容。

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import Bydriver = webdriver.Chrome()
element = WebDriverWait(driver, 5, 0.5).until(EC.presence_of_element_located((By.ID, 'kw')),message='超时啦!')

在这里插入图片描述
由上可看到,声明了一个浏览器驱动driver。并且为此设置了显示等待,最大等待时间5秒,每间隔0.5秒去检查一次。直到(until)元素出现(presence_of_element),该元素通过ID进行定位,其ID的值为kw(By.ID, ‘kw’)。最后超出了最大等待时间5秒,报了超时异常(TimeoutException),且显示的文本信息是自行设置的message的值。

关于until中的methon,即等待期间的预期条件的判断方法是由 expected_conditions 提供,下面列举常用方法。
并介绍这些方法中要用到的定位器和元素

from selenium.webdriver.common.by import By
from selenium import webdriverdriver = webdriver.Chrome()
locator = (By.ID, 'kw') # 定位器
element = driver.find_element_by_id('kw') # 元素
方法描述
title_is(‘百度一下’)判断当前页面的 title 是否等于预期
title_contains(‘百度’)判断当前页面的 title 是否包含预期字符串
presence_of_element_located(locator)判断元素是否被加到了 dom 树里,并不代表该元素一定可见
visibility_of_element_located(locator)判断元素是否可见,可见代表元素非隐藏,并且元素的宽和高都不等于0
visibility_of(element)跟上一个方法作用相同,但传入参数为 element
text_to_be_present_in_element(locator , ‘百度’)判断元素中的 text 是否包含了预期的字符串
text_to_be_present_in_element_value(locator , ‘某值’)判断元素中的 value 属性是否包含了预期的字符串
frame_to_be_available_and_switch_to_it(locator)判断该 frame 是否可以 switch 进去,True 则 switch 进去,反之 False
invisibility_of_element_located(locator)判断元素中是否不存在于 dom 树或不可见
element_to_be_clickable(locator)判断元素中是否可见并且是可点击的
staleness_of(element)等待元素从 dom 树中移除
element_to_be_selected(element)判断元素是否被选中,一般用在下拉列表
element_selection_state_to_be(element, True)判断元素的选中状态是否符合预期,参数 element,第二个参数为 True/False
element_located_selection_state_to_be(locator, True)跟上一个方法作用相同,但传入参数为 locator
alert_is_present()判断页面上是否存在 alert

强制等待

使用 time.sleep() 强制等待,设置固定的休眠时间,对于代码的运行效率会有影响。

实践经验建议:

  • 添加页面加载和元素等待机制
  • 查找元素的超时和重试机制
  • 详细的错误处理机制
  • 避免使用time.sleep():不灵活且低效
  • 结合使用隐式等待和显式等待:隐式等待作为全局保护,显式等待针对特定场景
  • 设置合理的超时时间:不要过长或过短
  • 捕获并处理超时异常:提供适当的恢复机制或用户友好的错误信息
  • 为不同网络环境调整等待策略:可配置的超时参数

异常处理 (根据实际情况,仅作介绍)

Selenium操作可能会触发各种异常,合理的异常处理可以提高脚本的健壮性。

常见异常类型

from selenium.common.exceptions import (NoSuchElementException,  # 元素未找到TimeoutException,        # 等待超时ElementNotVisibleException,  # 元素不可见ElementNotInteractableException,  # 元素不可交互StaleElementReferenceException,  # 元素已过时(DOM已更新)WebDriverException,      # WebDriver通用异常InvalidSelectorException,  # 无效的选择器UnexpectedAlertPresentException,  # 意外的警告框NoAlertPresentException,  # 没有警告框SessionNotCreatedException,  # 会话创建失败ElementClickInterceptedException  # 元素点击被拦截
)

基本异常处理

try:element = driver.find_element(By.ID, "non_existent_element")element.click()
except NoSuchElementException:print("元素未找到")
except ElementNotInteractableException:print("元素不可交互")
except Exception as e:print(f"发生其他异常: {e}")

重试机制

def retry_click(driver, by, value, max_attempts=3, wait_time=1):"""尝试多次点击元素"""from time import sleepfor attempt in range(max_attempts):try:element = driver.find_element(by, value)element.click()return Trueexcept (NoSuchElementException, ElementNotInteractableException, ElementClickInterceptedException, StaleElementReferenceException) as e:if attempt == max_attempts - 1:print(f"无法点击元素,错误: {e}")return Falsesleep(wait_time)return False

处理StaleElementReferenceException

def get_fresh_element(driver, by, value):"""获取一个新鲜的元素引用,避免StaleElementReferenceException"""try:return driver.find_element(by, value)except StaleElementReferenceException:# 重新查找元素return driver.find_element(by, value)

模拟鼠标操作

在浏览器中定位元素后,也就需要能够模拟鼠标的一些操作了,在webdriver 中,鼠标操作绝大多数封装在ActionChains类中。

from selenium.webdriver.common.action_chains import ActionChains

常见方法如下:

方法描述
click()单击左键(不需要导入 ActionChains 即可实现)
context_click()单击右键
double_click()双击
drag_and_drop()拖动
move_to_element()鼠标悬停
perform()执行所有ActionChains中存储的动作

单击左键

# 定位搜索按钮
button = driver.find_element_by_xpath('//*[@id="toolbar-search-button"]/span')
# 执行单击操作
button.click()

单击右键

from selenium.webdriver.common.action_chains import ActionChains# 定位搜索按钮
button = driver.find_element_by_xpath('//*[@id="toolbar-search-button"]/span')
# 右键搜索按钮
ActionChains(driver).context_click(button).perform()

注意: 调用perform()才会执行
注意: selenium 框架虽然提供了 鼠标右键方法,但是没有提供选择右键菜单方法,可以通过键盘快捷键操作实现

拖动

模拟鼠标拖动操作,该操作有两个必要参数,

  • source:鼠标拖动的元素
  • target:鼠标拖至并释放的目标元素

from selenium import webdriver
from selenium.webdriver import ActionChainsdriver = webdriver.Chrome()
driver.get('file:///D:/%E6%A1%8C%E9%9D%A2/page/drag.html')red = driver.find_element_by_xpath('//*[@id="div1"]')
blue = driver.find_element_by_xpath('//*[@id="div2"]')# 实例化鼠标
action = ActionChains(driver)
# 鼠标拖拽
action.drag_and_drop(red, blue)
# 鼠标执行
action.perform()driver.quit()

在这里插入图片描述

鼠标悬停

模拟悬停的作用一般是为了显示隐藏的下拉框。

模拟键盘操作

在浏览器中定位元素后,也就需要能够模拟键盘的一些操作了,在webdriver 中,键盘操作绝大多数封装在Keys类中。

from selenium.webdriver.common.keys import Keys

使用方法

# 输入文本
element.send_keys('文本')
# 键盘单键
element.send_keys(Keys.XXX)
# 组合键
element.send_keys(Keys.XXX, 'a') # 注意这里的组合键都是小写

举例

from selenium.webdriver.common.keys import Keys# 定位输入框并输入文本
driver.find_element_by_id('xxx').send_keys('hello world')# 模拟回车键进行跳转(输入内容后) 
driver.find_element_by_id('xxx').send_keys(Keys.ENTER)# 使用 Backspace 来删除一个字符
driver.find_element_by_id('xxx').send_keys(Keys.BACK_SPACE)# Ctrl + A 全选输入框中内容
driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'a')# Ctrl + C 复制输入框中内容
driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'c')# Ctrl + V 粘贴输入框中内容
driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'v')

其他常见键盘操作:

描述按键
空格Keys.SPACE
Tab键Keys.TAB
Alt键Keys.ALT
Shift键Keys.SHIFT
向下箭头Keys.ARROW_DOWN
向左箭头Keys.ARROW_DOWN
向右箭头Keys.ARROW_RIGHT
向上箭头Keys.ARROW_UP
F1键Keys.F1

其他控制操作

元素操作

.clear()  # 清空内容 一般用于清空输入框内容
.is_displayed() # 判断该元素是否可见
.get_attribute() # 获取标签属性值
.size # 返回元素的尺寸
.text # 返回元素文本
.is_enabled() # 判断元素是否可用 如:element.is_enabled()
.is_selected() # 判断元素是否被选中 如:element.is_selected()

浏览器操作

# 方法
"""
1、driver.maximize_window()  # 最大化浏览器
2、driver.set_window_size(w,h)  # 设置浏览器大小 单位像素
3、driver.set_window_position(x,y)  # 设置浏览器位置
4、driver.back() # 后退操作
5、driver.forward() # 前进操作
6、driver.refrensh() # 刷新操作
7、driver.close() # 关闭当前主窗口(主窗口:默认启动那个界面,就是主窗口)
8、driver.quit() # 关闭driver对象启动的全部页面
9、driver.title # 获取当前页面title信息
10、driver.current_url # 获取当前页面url信息
"""

注意:driver.close() ,关闭当前主窗口,只有完成页面切换(下文提及)才可以关闭新的页面。
在我们打开浏览器时,打开的主页面称为主窗口。随后我们在该浏览器内可以打开多个页面,并且这些多个页面可以并列显示,但主窗口还是最初的那一个页面。

下拉框操作

下拉框是HTML中的元素,对下拉框的操作的方法封装在Select类中。

# 导包
from selenium.webdriver.support.select improt Select# 下拉框标签
<select>
<option></option>
<option></option>
</select>element = driver.find_element_by_id("select") # 通过元素定位方式找到<select>标签,也就是下拉框
# 实例化
select = Select(element)# 操作方法
​ 1)、select_by_index() # 根据option索引 选中下拉框选项
​ 2)、select_by_value() # 根据option属性 value值 选中下拉框选项
​ 3)、select_by_visible_text() # 根据option显示文本 选中下拉框选项

弹出框操作

一旦出现弹出框,如果不进行处理,则后续操作不可实现

JavaScript 有三种弹窗 alert(确认)、confirm(确认、取消)、prompt(文本框、确认、取消)。
处理方式:先定位(switch_to.alert自动获取当前弹窗),再使用 text、accept、dismiss、send_keys 等方法进行操作

方法描述
text获取弹窗中的文字
accept接受(确认)弹窗内容
dismiss解除(取消)弹窗
send_keys发送文本至警告框

一个简单的测试页面,其中包含三个按钮,分别对应三个弹窗。

<!DOCTYPE html>
<html lang="en"><head>
</head><body><button id="alert">alert</button><button id="confirm">confirm</button><button id="prompt">prompt</button><script type="text/javascript">const dom1 = document.getElementById("alert")dom1.addEventListener('click', function(){alert("alert hello")})const dom2 = document.getElementById("confirm")dom2.addEventListener('click', function(){confirm("confirm hello")})const dom3 = document.getElementById("prompt")dom3.addEventListener('click', function(){prompt("prompt hello")})</script>
</body>
</html>

下面使用上面的方法进行测试。为了防止弹窗操作过快,每次操作弹窗,都使用 sleep 强制等待一段时间。

from selenium import webdriver
from pathlib import Path
from time import sleepdriver = webdriver.Firefox()
driver.get('file:///' + str(Path(Path.cwd(), '弹窗.html')))
sleep(2)# 点击alert按钮 弹出alert弹窗
driver.find_element_by_xpath('//*[@id="alert"]').click()
sleep(1)
alert = driver.switch_to.alert # 定位到弹窗
# 打印alert弹窗的文本
print(alert.text)
# 确认
alert.accept()# 点击confirm按钮 弹出confirm弹窗
driver.find_element_by_xpath('//*[@id="confirm"]').click()
sleep(1)
confirm = driver.switch_to.alert # 定位到弹窗
print(confirm.text)
# 取消
confirm.dismiss()# 点击prompt按钮 弹出prompt弹窗
driver.find_element_by_xpath('//*[@id="prompt"]').click()
sleep(1)
prompt = driver.switch_to.alert # 定位到弹窗
print(prompt.text)
# 向prompt的输入框中传入文本
prompt.send_keys("hello world")
sleep(2)
prompt.accept()

滚动条

在现在浏览器页面中,元素可能是动态显示,需要根据滚动条的下拉而被加载。
或者有些特殊场景中,需要将页面滑动后才能进行操作。例如,页面注册同意条款,需要拉到最底端点击确认按钮。

Selenium框架中没有专门处理滚动条的方法,需要通过调用 Js 代码实现操作;webdriver 中使用execute_script方法实现 JavaScript 的执行。

通过 x ,y 坐标滑动滚动条,我们需要知道坐标的起始位置在页面左上角(0,0)

from selenium import webdriver 
from time import sleepdriver = webdriver.Chrome()
driver.get("https://blog.csdn.net/")
sleep(1)
# 设置操作滚动条操作JavaScript语句
# 0:为左边距 对应 水平滚动条
# 1000: 对应 垂直滚动条
js = "window.scrollTo(0,500);"
# 调用执行js方法,将设置js语句传入方法中
driver.execute_script(js)

frame/iframe表单

很多页面也会用 frame/iframe 表单嵌套,对于这种内嵌的页面 selenium 是无法直接定位其中的元素,需要使用 switch_to.frame() 方法将当前操作的对象切换成 frame/iframe 内嵌的页面,再进行元素定位操作。

使用方法:driver.switch_to.frame(“id/name/element”) 进行切换表单操作,传入的是代表表单唯一的特征值。如果 frame 没有 id 或 name ,这时就需要使用 xpath 进行定位。

<!DOCTYPE html>
<html lang="en"># HTML 其他部分略
<body><iframe id="CSDN_info" name="Dream丶Killer" src="https://blog.csdn.net/qq_43965708" width="400" height="200"></iframe>
</body>
</html>
from selenium import webdriver
from pathlib import Pathdriver = webdriver.Chrome()
# 读取本地html文件
driver.get('file:///' + str(Path(Path.cwd(), 'iframe测试.html')))# 1.通过id定位
driver.switch_to.frame('CSDN_info')
# 2.通过name定位
# driver.switch_to.frame('Dream丶Killer')
# 通过xpath定位
# 3.iframe_label = driver.find_element_by_xpath('/html/body/iframe')
# driver.switch_to.frame(iframe_label)

通过 driver.switch_to.frame()切换到表单当中后,我们再随后使用之前的元素定位方法就可以定位到表单中的元素,并进行后续的操作。

连续切换frame/iframe

说明:如果要实现多个frame之间的切换,假如现在页面中一共有两个iframe。从主页面已经切换到第一个iframe中,想要从第一个iframe切换到第二个iframe,需要先切换回到主页面,然后才能切换到第二个iframe。

回到主页面的方法:driver.switch_to.default_content()

from selenium import webdriverdriver = webdriver.Chrome()
driver.get('file:///D:/%E6%A1%8C%E9%9D%A2/page/%E6%B3%A8%E5%86%8C%E5%AE%9E%E4%BE%8B.html')driver.switch_to.frame('idframe1')
driver.find_element_by_id('userA').send_keys('admin')
# 切换回到主页面
driver.switch_to.default_content()
driver.switch_to.frame('myframe2')
driver.find_element_by_id('userB').send_keys('admin4')driver.quit()

多窗口切换

在点击超链接或某些按钮后,可能会在新窗口中打开新的页面。这时候 selenium 还是只能定位主窗口,需要进行切换才能够定位最新页面上的元素。

每个窗口都有唯一的一个句柄值,那么我们就可以通过句柄值来完成窗口的切换操作

​ 切换方法:

​ 1)、driver.current_window_handle (获取当前窗口的句柄值)

​ 2)、driver.window_handles ( 获取当前由driver启动的所有窗口句柄)

​ 3)、driver.switch_to.window(handle) —> 切换窗口

from selenium import webdriverdriver = webdriver.Chrome()
driver.get('file:///D:/%E6%A1%8C%E9%9D%A2/page/%E6%B3%A8%E5%86%8C%E5%AE%9E%E4%BE%8B.html')# 1、获取当前窗口的句柄值
# print("当前的句柄值是:", driver.current_window_handle)# 2、获取driver启动的所有窗口句柄
handles = driver.window_handles# 3、切换窗口
driver.switch_to.window(handles[-1])driver.quit()

注意:窗口切换后,现在使用close()就是关闭切换后的页面,如果还想重新操作原始页面,需要重新进行窗口切换。

截图操作

driver.get_screenshot_as_file(imgpath) # imgpath 图片保存路径
注意:需要先创建文件夹,该方法不会主动创建不存在的文件夹路径。

验证码处理

验证码是一种随机生成的信息(数字,字母、汉字、图片、算术题等)为了防止恶意的请求行为,增加应用的安全性。

在WEB应用中,大部分系统在用户注册和登录时,都需要输入验证码。在自动化测试的时候,就要处理验证码的问题。

处理方式大致有:
1、去除验证码(测试环境中 可以这样处理)
2、设置万能验证码(测试环境中 可以这样处理)
3、采用第三方的验证码识别库
4、记录cookie (使用cookie跳过登录)

主要介绍使用cookie跳过登录:

​客户端在登录账号后,将登录状态相关的cookie 信息发给服务器,再发送去请求,携带cookie信息如果跟服务器保留的一致,则服务器认为客户端是登录状态。(关于cookie的详细解释,可以查看我的另外一篇博客,或者自行查阅资料。)

webdriver 提供 cookies 的几种操作:读取、添加删除。

get_cookies:以字典的形式返回当前会话中可见的 cookie 信息。
get_cookie(name):返回cookie字典中 某个cookie 的Value。
add_cookie(cookie_dict):将 cookie 添加到当前会话中,以字典的方式添加
delete_cookie(name):删除指定名称的单个 cookie。
delete_all_cookies():删除会话范围内的所有 cookie。

1、获取与登录有关的cookie信息
2、整理cookie信息为字典数据
3、调用方法添加cookie
driver.add_cookie(cookie变量)
4、刷新页面 -->发送cookie给服务器验证
driver.refresh()

实例

准备工作,在百度WEB应用登录的状态下,获取cookie字段(BDUSS这个cookie,及其对应的Value与登录有关)
在这里插入图片描述

from selenium import webdriver
driver = webdriver.Chrome()driver.get('https://www.baidu.com/')
driver.maximize_window()# 1、整理cookie信息为字典数据,对应的是name和value,保存在一个变量中
# 此处的name和value是从浏览器上手动获取的
cookie_value = {'name':'BDUSS',
'value':'........................'}
# 2、调用方法添加cookie
driver.add_cookie(cookie_value)
# 3、刷新页面 -->发送cookie给服务器验证
driver.refresh()
# 登录成功
driver.quit()
# 另外一种思路
from selenium import webdriver
driver = webdriver.Chrome()driver.get('https://www.baidu.com/')
driver.maximize_window()# 查看所有cookie信息
print(driver.get_cookies())# 1、整理cookie信息为字典数据,对应的是name和value,保存在一个变量中
cookie_value = {'name':'BDUSS',
'value':driver.get_cookie('BDUSS')}
# 2、调用方法添加cookie
driver.add_cookie(cookie_value)
# 3、刷新页面 -->发送cookie给服务器验证
driver.refresh()
# 登录成功
driver.quit()# 删除 name = 'BDUSS' 的cookie信息
# driver.delete_cookie('BDUSS')
# 删除当前会话中的所有cookie
# driver.delete_all_cookies()

注意:
1、不同项目的cookie字段信息不同
2、利用cookie绕过了登录,但也别忘记对登录功能进行测试。
3、部分项目用cookie绕过登录,可能需要添加多个cookie
4、cookie信息可能会过期,需要重新登录获取。

上传与下载文件

上传文件

常见的 web 页面的上传,一般使用 input 标签或是插件(JavaScript、Ajax),对于 input 标签的上传,可以直接使用 send_keys(路径) 来进行上传。

一个测试用的页面。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><input type="file" name="">
</body>
</html>

在这里插入图片描述
通过 xpath 定位 input 标签,然后使用 send_keys(str(file_path) 上传文件。

from selenium import webdriver
from pathlib import Path
from time import sleepdriver = webdriver.Chrome()
file_path = Path(Path.cwd(), '上传下载.html')
driver.get('file:///' + str(file_path))driver.find_element_by_xpath('//*[@name="upload"]').send_keys(str(file_path))

在这里插入图片描述

下载文件

Chrome 浏览器要想实现文件下载,需要通过 add_experimental_option 添加 prefs 参数。

download.default_directory:设置下载路径。
profile.default_content_settings.popups:0 禁止弹出窗口。

下面测试下载搜狗图片。指定保存路径为代码所在路径。
在这里插入图片描述

from selenium import webdriver prefs = {'profile.default_content_settings.popups': 0,'download.default_directory': str(Path.cwd())}
option = webdriver.ChromeOptions() 
option.add_experimental_option('prefs', prefs)
driver = webdriver.Chrome(options=option)
driver.get("https://pic.sogou.com/d?query=%E7%83%9F%E8%8A%B1&did=4&category_from=copyright")
driver.find_element_by_xpath('/html/body/div/div/div/div[2]/div[1]/div[2]/div[1]/div[2]/a').click()driver.switch_to.window(driver.window_handles[-1])
driver.find_element_by_xpath('./html').send_keys('thisisunsafe')

代码最后两句实际作用是当你弹出像下面的页面 “您的连接不是私密连接” 时,可以直接键盘输入 “thisisunsafe” 直接访问链接。由于该标签页是新打开的,所以要通过 switch_to.window() 将窗口切换到最新的标签页。

在这里插入图片描述

Firefox 浏览器要想实现文件下载,需要通过 set_preference 设置 FirefoxProfile() 的一些属性。

  • browser.download.foladerList:0 代表按浏览器默认下载路径;2 保存到指定的目录。
  • browser.download.dir:指定下载目录。
  • browser.download.manager.showWhenStarting:是否显示开始,boolean 类型。
  • browser.helperApps.neverAsk.saveToDisk:对指定文件类型不再弹出框进行询问。
  • HTTP Content-type对照表:https://www.runoob.com/http/http-content-type.html
from selenium import webdriver
import os
fp = webdriver.FirefoxProfile()
fp.set_preference("browser.download.dir",os.getcwd())
fp.set_preference("browser.download.folderList",2)
fp.set_preference("browser.download.manager.showhenStarting",True)
fp.set_preference("browser.helperApps.neverAsk.saveToDisk","application/octet-stream")driver = webdriver.Firefox(firefox_profile = fp)
driver.get("https://pic.sogou.com/d?query=%E7%83%9F%E8%8A%B1&did=4&category_from=copyright")
driver.find_element_by_xpath('/html/body/div/div/div/div[2]/div[1]/div[2]/div[1]/div[2]/a').click()

参考目录

https://www.bilibili.com/video/BV1eZ4y1s7BY
https://www.bilibili.com/video/BV18Q4y1y7v3
https://blog.csdn.net/yuanbang_bc/article/details/147515853
https://blog.csdn.net/qq_54219272/article/details/123310772
https://blog.csdn.net/kobepaul123/article/details/128796839
https://blog.csdn.net/qq_43965708/article/details/120658713
https://blog.csdn.net/qq_54219272/article/details/123338773

相关文章:

  • 【HarmonyOS】作业三 UI
  • 【信息系统项目管理师-论文真题】2024上半年(第二批)论文详解(包括解题思路和写作要点)
  • 【云备份】服务端工具类实现
  • Unity动态列表+UniTask异步数据请求
  • 嵌入式AI还是一片蓝海
  • MySQL 服务搭建
  • 范式演进:从ETL到ELT及未来展望
  • 多智能体空域协同中的伦理博弈与系统调停
  • 题解:CF1398D Colored Rectangles
  • 华为eNSP:多区域集成IS-IS
  • Python基本语法(控制语句)
  • Java中修饰类的关键字
  • windows中Python的pip工具换源的方法及其原理
  • RISC-V AIA SPEC学习(四)
  • 位运算切换大小写
  • C 语言 第五章 指针(5)
  • MATLAB 中zerophase函数——零相位响应
  • (B题|矿山数据处理问题)2025年第二十二届五一数学建模竞赛(五一杯/五一赛)解题思路|完整代码论文集合
  • 「面白い」日本 课文详解
  • 2025东三省C题深圳杯C题数学建模挑战赛数模思路代码文章教学: 分布式能源接入配电网的风险分析
  • 全国铁路昨日发送2311.9万人次,同比增长11.7%创历史新高
  • 长三角铁路今日预计发送旅客420万人次,有望创单日客发量新高
  • 山西太原一处居民小区发生爆炸,现场产生大量浓烟
  • 解放日报头版聚焦“人民城市”:共建共享展新卷
  • TAE联手加州大学开发出新型核聚变装置:功率提升百倍,成本减半
  • “杭州六小龙”的招聘迷局