Selenium可以自动化操作浏览器,例如:选择元素,输入,点击等,可以用于软件自动化测试,爬虫等工作,也可以做你想做的任何事情。
本文环境: Python3.12,Windows10,Selenium 4.15.2,Chrome 119.0.6045.160
原理
WebDriver是一套标准API协议,由Selenium提出,W3C将其作为推荐标准,用于描述对UI界面的操作指令,使得客户端使用同样的函数就能操作不同的浏览器。自动化框架Appium也是基于WebDriver协议传输指令。
Selenium各种编程语言的lib库(客户端)使用WebDriver协议,向Driver程序传输控制指令,各种浏览器都有自己对应的Driver程序,Driver程序实际上就是把WebDriver 指令翻译成实际的浏览器控制命令。
安装
一、安装Chrome
方法1.安装标准版Chrome(如果系统中已安装可跳过)
官网下载安装标准版(https://www.google.com/chrome/),Selenium会自动在PATH路径寻找系统安装的浏览器,并自动下载对应的Driver程序。
方法2.安装测试专用版
去chromiun官网(https://chromedriver.chromium.org/downloads) 下载各平台对应的测试专用版本Chrome和对应驱动,解压后放到项目路径。此种方式需要初始化驱动时配置浏览器和驱动的路径,后文会有介绍。
二、安装Python
去官网下载安装即可 https://www.python.org/downloads/windows/
可以自定义安装位置和特性。
注:安装给所有人,默认安装到系统路径(C:\Program Files\)下,有些库文件会分散安装到系统其他路径。
安装给当前用户,默认安装到路径(C:\Users\username\AppData\Local\Programs\)下。所有文件都会安装到一个文件夹下,把这个目录复制到别处,只需自己配好PATH路径就能继续使用。
注:由于Python3.12的基础库有些变动,如果你使用Pycharm请升级其到最新版,否则可能管理不了虚拟环境。
三、安装selenium库
pip install selenium
示例:访问百度
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://www.baidu.com/")
print(driver.title)
input = driver.find_element(by=By.ID, value="kw")
input.send_keys('abc')
submit = driver.find_element(by=By.XPATH, value='//*[@id="su"]')
submit.click()
time.sleep(300)
第一次运行可能要等一段挺长的时间,之后会自动打开页面输入内容,点击搜索:
初始化driver
以下初始化参数请按需选择
from selenium import webdriver
options = webdriver.ChromeOptions()
options.page_load_strategy = 'normal' # 网页加载模式:等待所有资源都被下载
options.binary_location = r".\chrome-win64\chrome.exe" # 指定被操作的浏览器程序路径
# headless模式需要的三个配置,不需要可以注释掉
options.add_argument("--headless") # 无界面模式
options.add_argument("--disable-gpu") # headless模式下,windows系统可能需要
options.add_argument('--window-size=1920,1080') # 缺少此配置,headless模式可能点击不到元素
options.add_argument("--start-maximized") # 启动时最大化窗口
options.add_argument(f"--force-device-scale-factor={1}") # 缩放后的高分屏截屏模糊,需要恢复
options.add_argument("--test-type=gpu") # 关掉提示:“Chrome测试版 仅适用于自动测试”
options.add_experimental_option("detach", True) # driver退出,但保留浏览器(注意不要执行driver.quit())
switches = ['enable-automation', # 关掉提示:“Chrome正受到自动测试软件的控制”
'enable-logging', # 关闭浏览器日志
]
options.add_experimental_option('excludeSwitches', switches)
prefs = {"credentials_enable_service": False, # 禁止保存密码弹窗
"profile.password_manager_enabled": False, # 禁止保存密码弹窗
}
options.add_experimental_option("prefs", prefs)
service = webdriver.ChromeService(service_args=["--verbose", "--log-path=.\\qc1.log"], # chromedriver的日志
executable_path=r".\chromedriver-win64\chromedriver.exe" # chromedriver程序路径
)
driver = webdriver.Chrome(options=options, service=service)
driver.implicitly_wait(50) # 查找元素标签时,等待时长
注:浏览器启动后,可以在地址栏访问:chrome://version/ 查看启动参数,需要屏蔽的默认参数可以放到excludeSwitches中。
注:如果想用detach True参数,在Pycharm中不要直接Run,要在Terminal标签,或系统cmd命令行运行。或者excludeSwitches中包含'enable-logging'确保浏览器不输出日志。
注:关于指定所用的浏览器和web驱动
在4.10.0版本后,selenium包含了一个Selenium Manager工具,会自动探测系统上安装的浏览器位置,自动下载对应的web驱动程序,这种情况下也可以删除上文中这两个配置:上文的百度示例就是没有这两个配置,第一次运行自动下载驱动消耗了一段时间。
# 指定浏览器
options.binary_location = r".\chrome-win64\chrome.exe"
# 指定web驱动
service = webdriver.ChromeService(executable_path=r".\chromedriver-win64\chromedriver.exe")
现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:691998057【暗号:csdn999】
打开网页
打开网页,selenium只有get方法,其他方法只能操作浏览器,由浏览器或js脚本发送。
driver.get('https://www.w3schools.com/js/default.asp')
# driver.refresh() 刷新页面,如果链接未变,重复get无用,可以刷新。
网页操作简单来说就分两步:1. 定位元素 2.执行操作。
from selenium.webdriver.common.by import By
accept_button = driver.find_element(by=By.XPATH,
value='//*[@id="accept-choices"]')
accept_button.click()
元素定位
主要通过find_element()函数进行,有两个参数,by参数选择定位方式;value参数输入定位方式对应的值。
其他定位方式:
By.XPATH:使用XPATH定位: '//*[@id="accept-choices"]'。
By.TAG_NAME:使用tag名定位: 即h1,div,a等。
By.ID: 使用ID属性:<div id="content"></div>
By.NAME: 使用name属性:<div name="content"></div>
By.CSS_SELECTOR: css选择器:"#book"
By.CLASS_NAME:类名:<div class="content"></div>
By.LINK_TEXT:通过链接文字:<a href="continue.html">Continue</a>
By.PARTIAL_LINK_TEXT:部分链接文字:上例中只写Cont
定位元素不只针对窗口,也可以从已经定位的元素开始,driver.find_element() 返回的是一个 WebElement,它也有find_element()方法
table = driver.find_element(by=By.ID, value="table")
t_body = table.find_element(by=By.TAG_NAME, value="tbody")
t_tr = t_body.find_elements(by=By.TAG_NAME, value='tr')
元素操作
# 按钮链接等
button.click()
# 文本框
username_box.send_keys(username)
# select元素
from selenium.webdriver.support.ui import Select
select_elm = driver.find_element(by=By.TAG_NAME, value='select')
selecter = Select(select_elm)
selecter.select_by_value("2023-12")
切换iframe和窗口
有时候你会发现,怎么也定位不到元素,这也许是因为他们处于不同的iframe或窗口,必须先切换过去才能操作。
切换iframe
<iframe id="buttonframe" name="myframe" src="https://seleniumhq.github.io">
<button>Click here</button>
</iframe>
------------------------------------
# Store iframe web element
iframe = driver.find_element(By.CSS_SELECTOR, "#modal > iframe")
# switch to selected iframe
driver.switch_to.frame(iframe)
# Switch frame by id
driver.switch_to.frame('buttonframe')
# Now click on button
driver.find_element(By.TAG_NAME, 'button').click()
# switch back to default content
driver.switch_to.default_content()
切换窗口
driver.current_window_handle # 当前窗口句柄
driver.window_handles # 所有的窗口列表,可以从中取出handle
# Opens a new tab and switches to new tab
driver.switch_to.new_window('tab')
# Opens a new window and switches to new window
driver.switch_to.new_window('window')
driver.switch_to.window(handle) # 切换到一个窗口,
driver.close() # 关闭窗口
等待(Wait)
点击了按钮或执行了某个操作后,浏览器需要一定的时间加载资源或进行计算,js也会改变DOM内容。
因此,很多时候我们需要等待一定的条件才能继续操作。
手工等待
最简单的等待可以添加time.sleep()硬性等待,短时间的等待(一两秒)是可以使用的,对于等待时长不固定,有较大概率等待时间较长的情况一般不要使用,但在遇到问题时可以临时用这种方法定位问题。
隐式等待
在初始化好driver后,使用如下语句配置
driver.implicitly_wait(20)
如果没有配置默认值为0,即如果元素没有就位会立刻返回错误;如果配置了则等待对用时长后元素还没有就位才返回错误;如果元素就位会立即返回,不会浪费时间。
显式等待(最重要)
显式等待,是等待某个或某些条件的成立,条件是否成立由一个函数判断,这个函数作为参数传寄给Wait机制的until()或until_not()函数:
from selenium.webdriver.support.ui import WebDriverWait
wait = WebDriverWait(driver, timeout=20)
element = wait.until(lambda d : revealed.is_displayed())
wait.until_not(lambda d : revealed.is_displayed())
# 还可以配置其探测间隔,忽略的异常等
errors = [NoSuchElementException, ElementNotInteractableException]
wait = WebDriverWait(driver, timeout=2, poll_frequency=.2, ignored_exceptions=errors)
wait.until(lambda d : revealed.send_keys("Displayed") or True)
until()函数直到回调函数返回"真"值,否则抛出超时异常;until_not()函数相反,直到回调函数返回"假"值就返回否则抛出异常,另外如果遇到被忽略的异常,会返回True。
回调函数接收一个参数,即初始化wait时的driver。
def condition_fun(driver):
if time.time() > 2524579200: # 2050-01-01后满足条件
return True
resp = wait.until(condition_fun)
系统预定义条件
系统预置了一些expected conditions函数,他们通过闭包的方式,生成一个符合until()函数需要的单参数函数:
from selenium.webdriver.support import expected_conditions as EC
f_condition = EC.element_to_be_clickable(submit_button)
wait.until(f_condition) # f_condition是一个函数
EC.element_to_be_clickable()函数会帮我们生成需要的回调函数。这个函数等待指定的元素可点击。
函数的参数指定要等待的元素,有两种类型,一种是之前见过的使用find_element找到的元素,另一种是使用一个元组,传入定位方式和定位值,被称为locator:
例:
# 传入元素
submit_button = driver.find_element(by=By.XPATH, value='//*[@id="submit"]')
submit_button = wait.until(EC.element_to_be_clickable(submit_button))
if submit_button :
submit_button.click()
# 传入locator
submit_button = wait.until(EC.element_to_be_clickable(
(By.XPATH, '//*[@id="submit"]')
))
if submit_button :
submit_button.click()
预定义的条件很多,详情见官方文档,这里简单介绍几个:
EC.alert_is_present() # 当前正弹出告警框,并返回告警框
EC.element_attribute_to_include() # 元素包含某个属性
EC.element_to_be_clickable() # 元素可被点击
EC.visibility_of() # 元素可见
EC.staleness_of() # 元素消失
EC.text_to_be_present_in_element() # 元素种出现某个字符
EC.title_contains(title) # 页面标题包含某字符串
# 还有些条件的组合函数
EC.all_of() # 所有条件都满足
EC.any_of() # 任何一个条件满足
EC.none_of() # 所有条件都不满足
文档:https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html
补充:等待AJAX请求结束,并获取其内容
由于前后端分离技术,越来越多的页面并不是后端渲染完再返回显示,而是先返回一个框架,通过AJAX请求异步获取数据,再用js渲染到页面。Selenium对js的这些请求没有处理。
网络波动会对下载产生很大影响,时不时会有一个很长的等待(概率低但不是没有),如果使用sleep()手动等待,就需要等待很长时间,才能保证每一次请求都能完成。
所以如果能准确地等待一个数据请求结束,将会节省很多时间。
# 首先记得在初始化时打开performance日志
options.set_capability(
"goog:loggingPrefs", {"performance": "ALL"}
)
这样就可以通过日志获得链接即将发送请求,响应以及响应结束三种状态。
def ec_request_finish(url, timestamp):
"""
等待ajax发起的GET或POST请求结束
:param url: 请求前缀,
:param timestamp: 请求开始前记录的时间,可帮助排除页面自动发起的请求,或减少处理的日志数量
:return: request_id, 可以通过它获取文件内容
"""
request_id = ''
def check_fish(driver):
for log in driver.get_log('performance'):
if timestamp * 1000 > log['timestamp'] or 'message' not in log:
continue
log_entry = json.loads(log['message'])
try:
method = log_entry['message']['method']
params = log_entry['message']['params']
if not request_id and method in ['Network.requestWillBeSent', 'Network.responseReceived']:
if method == 'Network.requestWillBeSent' and \
params['request']['method'] in ['POST', 'GET'] and \
url in params['request']['url']:
request_id = params['requestId']
if method == 'Network.responseReceived' and \
params['response']['method'] in ['POST', 'GET'] and \
url in params['response']['url']:
request_id = params['requestId']
if request_id and method in ['Network.loadingFinished'] and \
request_id == params['requestId']:
return request_id
except Exception as e:
pass
return check_fish
# 等待请求结束
request_id = wait.until(ec_request_finish('https://www.abc.com/x/y/z',0))
# 获取返回的内容,此处以返回json格式字符串为例
result = self.driver.execute_cdp_cmd("Network.getResponseBody", {"requestId": request_id})
data = json.loads(result['body'])
浏览器操作
# 导航
driver.back()
driver.forward()
driver.refresh()
# 获取信息
driver.title # 标题
driver.current_url # 当前链接
driver.capabilities # 查看driver的一些配置
# Cookies
driver.add_cookie({"name": "foo", "value": "bar"})
driver.get_cookie("foo")
driver.get_cookies() #获取所有域名的cookies
driver.delete_cookie("foo")
driver.delete_all_cookies()
# 执行js脚本,有些信息可以通过js获取,当然也可以做其他事情
driver.execute_script('return arguments[0].innerText', header)
size = driver.get_window_size() # 获取窗口尺寸
driver.set_window_size(1024, 768) # 设置窗口尺寸
driver.get_window_position() # 获取窗口位置
driver.set_window_position(0, 0) # 设置窗口位置
driver.maximize_window() # 最大化
driver.minimize_window() # 最小化
driver.fullscreen_window() # 全屏显示,相当于F11
截屏
# 对窗口截屏
driver.get_screenshot_as_file('./image.png') # 截屏当前窗口,gng格式
driver.save_screenshot('./image.png') # 对get_screenshot_as_file()的封装
driver.get_screenshot_as_png() # 对窗口截屏,返回二进制png数据
driver.get_screenshot_as_base64() # 对窗口截屏,返回base64数据
# 对目标元素截屏
element = driver.find_element(...)
element.screenshot('./image.png')
element.screenshot_as_base64 # 注意不是函数,是property属性
element.screenshot_as_png # 注意不是函数,是property属性
补充:截长屏的方法
一般的截屏工具截长屏是通过滚轮操作滚动条,然后不断拼接完成的。Selenium应该也可以这样操作,不断的滚动、切图、拼接。
这里分享一个更简单些的操作:设置窗口大小,使滚动条消失内容全部显示。但要注意,这种方式一般需要在headless模式下才能正常工作。
截屏浏览器:
original_size = driver.get_window_size()
height = driver.execute_script('return document.documentElement.scrollHeight')
width = driver.execute_script('return document.documentElement.scrollWidth')
driver.set_window_size(width, height) # the trick, and must in headless mode
screenshot = form.screenshot_as_base64
form.screenshot('image.png')
driver.set_window_size(original_size['width'], original_size['height'])
截取带滚动条的元素:
content = driver.find_element(by=By.XPATH, value='//div[@id="app-content"]')
original_size = driver.get_window_size()
height = content.size['height']
width = content.size['width']
driver.set_window_size(width, height+100) # the trick, and must in headless mode
# screenshot = content.screenshot_as_base64
content.screenshot('image.png')
driver.set_window_size(original_size['width'], original_size['height'])
下载文件
有些网页有文档或数据导出功能,点击按钮会下载文件,可以使用的相关参数有:
prefs = {
"download.default_directory": 'D:\\', # 下载文件的保存地址,一定要是绝对地址
"download.prompt_for_download": False,
"download.directory_upgrade": True,
"profile.default_content_settings.popups": 0,
}
options.add_experimental_option("prefs", prefs)
default_directory一定要注意写绝对地址,其他参数是屏蔽弹窗什么的,遇到了可以试试。
有时候想直接指定文件名,暂时看是不可以的,可以下载回来后再给文件改名。
警告框操作
警告框是通过js的 alert()、 confirm()、 prompt()函数弹出的
# 使用wait等待警告框出现,并保存它
alert = wait.until(EC.alert_is_present())
# 或者直接获取警告框
alert = driver.switch_to.alert
# 警告框的文字内容
text = alert.text
# 按确定按钮
alert.accept()
# 按取消按钮
alert.dismiss()
# 向prompt()输入内容,作为其返回值
alert.send_keys("Selenium")
设备操作
能模拟键盘,鼠标,滚轮等操作。主要通过ActionChains,ActionBuilder 操作。
通用的一些操作
.pause(3) # 暂停3秒
.perform() # 执行action chain
键盘操作
from selenium.webdriver import Keys, ActionChains
# 直接输入到当前活跃元素,支持链式调用
ActionChains(driver)\
.key_down(Keys.SHIFT)\
.send_keys("abc")\
.key_up(Keys.SHIFT)\
.send_keys("def")\
.perform()
# 发送到特定元素(会自动点击传入的元素)
text_input = driver.find_element(By.ID, "textInput")
ActionChains(driver)\
.send_keys_to_element(text_input, "abc")\
.perform()
# 剪切复制粘贴
cmd_ctrl = Keys.COMMAND if sys.platform == 'darwin' else Keys.CONTROL
ActionChains(driver)\
.send_keys("Selenium!")\
.send_keys(Keys.ARROW_LEFT)\
.key_down(Keys.SHIFT)\
.send_keys(Keys.ARROW_UP)\
.key_up(Keys.SHIFT)\
.key_down(cmd_ctrl)\
.send_keys("xvv")\
.key_up(cmd_ctrl)\
.perform()
鼠标操作
from selenium.webdriver import Keys, ActionChains
button= driver.find_element(By.ID, "button")
ActionChains(driver)\
.move_to_element(button) \
.click() \
.perform()
# 移动鼠标
.move_to_element(to_element)
.move_by_offset(xoffset, yoffset)
.move_to_element_with_offset(to_element, xoffset, yoffset)
# 点击相关
.click() # 单击
.double_click() # 双击
.context_click() # 右击
.click_and_hold() # 单击不释放
.release() # 释放按钮
# 拖动
.drag_and_drop(source, target) # 一个元素拖动到另一个元素的位置
.drag_and_drop_by_offset(source, xoffset, yoffset) # 一个元素按像素拖动
# 滚轮滚动条,如果没效果尝试用一个新的ActionChains
.scroll_by_amount(delta_x, delta_y)
.scroll_to_element(element)
.scroll_from_origin(origin, delta_x, delta_y)
补充:显示鼠标指针
鼠标指针是操作系统管理的,我们可以移动浏览器的指针焦点位置,但是操做系统不会让鼠标跟着动。所以我们要想直观些看到指针(debug用,正常时候不要用),需要自己画一个:
def enable_cursor(driver):
enable_cursor = """
(function() {
var seleniumFollowerImg = document.createElement("img");
seleniumFollowerImg.setAttribute('src', 'data:image/png;base64,'
+ 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAQAAACGG/bgAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAA'
+ 'HsYAAB7GAZEt8iwAAAAHdElNRQfgAwgMIwdxU/i7AAABZklEQVQ4y43TsU4UURSH8W+XmYwkS2I0'
+ '9CRKpKGhsvIJjG9giQmliHFZlkUIGnEF7KTiCagpsYHWhoTQaiUUxLixYZb5KAAZZhbunu7O/PKf'
+ 'e+fcA+/pqwb4DuximEqXhT4iI8dMpBWEsWsuGYdpZFttiLSSgTvhZ1W/SvfO1CvYdV1kPghV68a3'
+ '0zzUWZH5pBqEui7dnqlFmLoq0gxC1XfGZdoLal2kea8ahLoqKXNAJQBT2yJzwUTVt0bS6ANqy1ga'
+ 'VCEq/oVTtjji4hQVhhnlYBH4WIJV9vlkXLm+10R8oJb79Jl1j9UdazJRGpkrmNkSF9SOz2T71s7M'
+ 'SIfD2lmmfjGSRz3hK8l4w1P+bah/HJLN0sys2JSMZQB+jKo6KSc8vLlLn5ikzF4268Wg2+pPOWW6'
+ 'ONcpr3PrXy9VfS473M/D7H+TLmrqsXtOGctvxvMv2oVNP+Av0uHbzbxyJaywyUjx8TlnPY2YxqkD'
+ 'dAAAAABJRU5ErkJggg==');
seleniumFollowerImg.setAttribute('id', 'selenium_mouse_follower');
seleniumFollowerImg.setAttribute('style', 'position: absolute; z-index: 99999999999; pointer-events: none; left:0; top:0');
document.body.appendChild(seleniumFollowerImg);
document.onmousemove = function (e) {
document.getElementById("selenium_mouse_follower").style.left = e.pageX + 'px';
document.getElementById("selenium_mouse_follower").style.top = e.pageY + 'px';
};
})();
// enableCursor();
"""
driver.execute_script(enable_cursor)
鼠标除了常用的按键还有一些特殊的,比如“中键”。这些按键需要用更底层的action机制:ActionBuilder
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.actions.mouse_button import MouseButton
# 按鼠标按键
action = ActionBuilder(driver)
action.pointer_action.pointer_down(MouseButton.MIDDLE)
action.pointer_action.pointer_up(MouseButton.MIDDLE)
action.perform()
注:ActionChains 底层也是使用ActionBuilder创建的action对象:
class ActionChains:
def __init__(self, driver: WebDriver, duration: int = 250, devices: list[AnyDevice] | None = None) -> None:
...
self.w3c_actions = ActionBuilder(driver, mouse=mouse, keyboard=keyboard, wheel=wheel, duration=duration)
def click(self, on_element: WebElement | None = None) -> ActionChains:
if on_element:
self.move_to_element(on_element)
self.w3c_actions.pointer_action.click()
self.w3c_actions.key_action.pause()
self.w3c_actions.key_action.pause()
return self
因此,学习ActionBuilder可以通过学习ActionChains源码进行。
指点设备
触控屏,触摸板,指点笔之类的
pointer_area = driver.find_element(By.ID, "pointerArea")
pen_input = PointerInput(POINTER_PEN, "default pen")
# 关键是替换默认的mouse
action = ActionBuilder(driver, mouse=pen_input)
action.pointer_action\
.move_to(pointer_area)\
.pointer_down()\
.move_by(2, 2, tilt_x=-72, tilt_y=9, twist=86)\
.pointer_up(0)
action.perform()
颜色支持
Selenium有个操作颜色的类,帮助判定颜色,配置颜色
from selenium.webdriver.support.color import Color
# 创建颜色
BLACK = Color.from_string('black')
CHOCOLATE = Color.from_string('chocolate')
HOTPINK = Color.from_string('hotpink')
TRANSPARENT = Color.from_string('transparent')
HEX_COLOUR = Color.from_string('#2F7ED8')
RGB_COLOUR = Color.from_string('rgb(255, 255, 255)')
RGB_COLOUR = Color.from_string('rgb(40%, 20%, 40%)')
RGBA_COLOUR = Color.from_string('rgba(255, 255, 255, 0.5)')
RGBA_COLOUR = Color.from_string('rgba(40%, 20%, 40%, 0.5)')
HSL_COLOUR = Color.from_string('hsl(100, 0%, 50%)')
HSLA_COLOUR = Color.from_string('hsla(100, 0%, 50%, 0.5)')
# 从页面元素获取颜色
login_button = driver.find_element(By.ID,'login')
login_button_colour = Color.from_string(login_button.value_of_css_property('color'))
login_button_background_colour = Color.from_string(login_button.value_of_css_property('background-color'))
# 从颜色生成hex,rgb,rgba颜色
login_button_background_colour.hex # '#ff69b4'
login_button_background_colour.rgba # 'rgba(255, 105, 180, 1)'
login_button_background_colour.rgb # 'rgb(255, 105, 180)'
# 判断元素的颜色
assert login_button_background_colour == HOTPINK
总结:
本文描述了Selenium自动化操控浏览器的原理,环境安装,及其支持的各种操作,并补充了一些很有用的扩展功能,希望能帮助读者对Selenium有个整体的认识,更多操作请参考官方资料。
下面是配套资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!
最后: 可以在公众号:自动化测试老司机 ! 免费领取一份216页软件测试工程师面试宝典文档资料。以及相对应的视频学习教程免费分享!,其中包括了有基础知识、Linux必备、Shell、互联网程序原理、Mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。
如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!