软件
- 下载地址https://pan.67an.com/
jetbrains
中pycharm-professional-2023.1
python
中python-3.8.10-amd64
selenium4
中IEDriverServer_Win32_4.14.0
、edge
、chrome
等驱动DisableIEToEdge
开启IE浏览器
Win10、11开启IE11
DisableIEToEdge
下载打开点击修复(杀毒软件会杀,需加入白名单防拦截,非IE11不要使用)- 修复完成后弹窗
修复成功咯,恭喜您可以继续使用IE11啦!祝您工作顺利,万事顺意
- 桌面有
Internet Explorer
图标
Selenium4
html
Python
面向对象pytest
yaml
数据驱动allure
报告log
日志PO
封装jenkins
IE浏览器官方答复
必要的配置
IEDriverServer
可执行文件必须已下载并放置在您的 PATH 中.- 在Windows Vista, Windows 7或Windows 10上的IE 7或更高版本上, 必须将每个区域的保护模式设置设置为相同的值. 该值可以打开或关闭, 只要每个区域的值相同. 要设置受保护模式设置, 请从“工具”菜单中选择“Internet选项…”, 然后单击“安全”选项卡. 对于每个区域, 标签底部将有一个复选框, 标记为“启用保护模式”.
- 此外, IE 10及更高版本必须禁用“增强保护模式”. 此选项位于“Internet选项”对话框的“高级”选项卡中.
- 浏览器缩放级别必须设置为100%, 以便将本机鼠标事件设置为正确的坐标.
- 对于Windows 10, 您还需要在显示设置中将“更改文本、应用程序和其他项目的大小”设置为100%.
- 仅对于IE 11, 您需要在目标计算机上设置一个注册表项, 以便驱动程序能够保持与它创建的Internet Explorer实例的连接. 对于32位Windows安装, 您必须在注册表编辑器中检查的项是
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BFCACHE
. 对于64位Windows安装, 键为HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BFCACHE
. 请注意,FEATURE_BFCACHE
子项可能存在, 也可能不存在, 如果不存在, 则应创建该子项. 要点: 在此键内, 创建一个名为iexplore.exe
值为0的DWORD.
原生事件以及Internet Explorer
- 由于
InternetExplorerDriver
仅适用于Windows, 因此它尝试使用所谓的“原生”或操作系统级事件 在浏览器中执行鼠标和键盘操作. 针对同样的操作, 与使用JavaScript模拟相比有明显的差异. 使用原生事件的优点是它不依赖于JavaScript沙箱, 并且可以确保在浏览器中正确传播JavaScript事件. 但是, 当IE浏览器窗口失焦, 以及当尝试将鼠标悬停在元素上时, 当前存在一些鼠标事件问题.
浏览器焦点
- 难点在于, 如果窗口没有焦点, IE本身似乎没有完全尊重我们在IE浏览器窗口 (
WM\_MOUSEDOWN
和WM\_MOUSEUP
) 上发送的Windows消息. 具体来说, 被单击的元素将在其周围接收一个焦点窗口, 但该元素不会处理该单击. 可以说, 我们根本不应该发送信息; 相反, 我们应该使用SendInput()
API, 但该API明确要求窗口具有焦点. WebDriver项目有两个相互冲突的目标. - 首先, 我们争取尽可能地模仿用户. 这意味着使用原生事件, 而不是使用JavaScript模拟事件.
- 其次, 我们不希望浏览器窗口的焦点被自动化. 这意味着仅将浏览器窗口强制到前台是次优的.
- 另一个考虑因素是 多个IE实例在多个WebDriver实例下运行的可能性, 这意味着任何此类“将窗口置于前台”解决方案 都必须包装某种同步结构 (互斥体?)到 IE驱动程序的C++代码中. 即使如此, 若用户将另一个窗口带到前台的操作, 介于驱动程序将IE带到前台和执行原生事件之间, 则此代码仍将受制于竞争条件.
- 围绕驱动程序的需求, 以及如何对这两个相互冲突的目标进行优先排序的讨论正在进行中. 当前流行的观点是前者优先于后者, 并在使用IE驱动程序时, 将您的机器标记为无法执行其他任务. 然而, 这一决定远未最终确定, 实现这一决定的代码可能相当复杂.
悬停在元素上
- 当您尝试将鼠标悬停在元素上, 并且物理鼠标光标位于IE浏览器窗口的边界内时, 鼠标悬停将不起作用. 更具体地说, 悬停将在几分之一秒内工作, 然后元素将恢复到其以前的状态. 出现这种情况的普遍理论是, IE在其事件循环期间正在进行某种类型的命中测试, 这导致它在物理光标位于窗口边界内时响应物理鼠标位置. WebDriver开发团队仍未找到解决IE这种行为的方法.
点击元素选项或提交表单以及弹窗
- IE驱动程序在两个地方不使用原生事件与元素交互. 这是在
<select>
元素中单击<option>
元素. 在正常情况下, IE驱动程序根据元素的位置和大小计算单击位置, 通常由JavaScriptgetBoundingClientRect()
方法返回. 但是, 对于<option>
元素,getBoundingClientRect()
返回一个位置为零、大小为零的矩形. IE驱动程序通过使用click()
来处理这一场景, 它本质上设置了元素.selected
的属性, 并在JavaScript中模拟onChange
事件. 但是, 这意味着如果<select>
元素的onChange
事件 包含调用alert()
,confirm()
或prompt()
的JavaScript代码, 则调用WebElement的click()
方法将挂起, 直到手动取消模式对话框. 对于此行为, 仅使用WebDriver代码没有已知的解决方法. - 类似地, 在某些情况下, 通过WebElement的
submit()
方法提交HTML表单 可能会产生相同的效果. 如果驱动程序调用表单上的JavaScriptsubmit()
函数, 并且有一个onSubmit事件处理程序调用 JavaScriptalert()
,confirm()
或prompt()
函数, 则可能发生这种情况. - 该限制被记录为3508号问题 (谷歌代码).
设置选项
ie_options = Options()
ie_options.ignore_protected_mode_settings = True
ie_options.ignore_zoom_level = True
ie_options.require_window_focus = True
driver = webdriver.Ie(options=ie_options)
- ignore_protected_mode_settings:忽略保护模式设置
- ignore_zoom_level:忽略缩放级别
- require_window_focus:要求窗囗获得焦点
打开浏览器
# 创建浏览器实例对象
driver = webdriver.Chrome()
# 浏览器最大化
driver.maximize_window()
# 打开网址
driver.get("https://www.67an.cn")
# 关闭当前窗口
driver.close()
# 关闭浏览器selenium4执行结束自动关闭(IE不适用)
driver.quit()
HTML
h、p、span标签
a、img标签
ul、li标签
div标签
form表单
iframe内联框架
css
js
ID定位 By.ID
# send_keys输入内容
driver.find_element(By.ID,"kw").send_keys('七安')
# click点击
driver.find_element(By.ID,"su").click()
类名定位 By.CLASS_NAME
#获取class属性的第一个元素
driver.find_element(By.CLASS_NAME,'list-goto')
#获取class属性的所有元素
driver.find_elements(By.CLASS_NAME,'list-goto')[4].click()
for ele in driver.find_elements(By.CLASS_NAME, 'footer-widget-links'):
print(ele.text)
标签名定位 By.TAG_NAME
driver.find_element(By.TAG_NAME,"input")
document.getElementsByTagName("input")
名称定位 By.NAME
#只获取属性的第一个元素
driver.find_element(By.NAME,'wd')
#获取属性的所有元素
driver.find_elements(By.NAME,'wd')
链接文本定位 By.LINK_TEXT
driver.find_element(By.LINK_TEXT,'新闻')
链接部分文本定位 By.PARTIAL_LINK_TEXT
driver.find_element(By.PARTIAL_LINK_TEXT,'闻')
css_selector定位 By.CSS_SELECTOR
选择器 | 格式 | 示例 | 示例说明 |
标签选择器 | html标签 | input | 选择所有元素 |
ID选择器 | #id属性值 | #kw | 选择所有id='kw'的元素 |
类选择器 | .class属性值 | .nav-search-input | 选择所有class='nav-search-input'的元素 |
属性选择器1 | [属性名] | [name="wd"] | 选择所有name等于"wd"的元素 |
组合选择器 | 标签加属性描述 | input.s_ipt | 选择所有class='_ipt'的元素 |
父子关系 | 元素1>元素2 | div>a | 选择所有父级是的元素 |
后代关系 | 元素1 元素2 | div a | 选择中的所有元素 |
第一子元素 | :first-child | a:first-child | 选择所有元素且该元素是其父级的第一个元素 |
最后一个元素 | :last-child | a:last-child | 选择所有元素且该元素是其父级的最后一个元素 |
顺序选择器 | :nth-child(n) | a:nth-child(2) | 选择所有元素且该元素是其父级的第二个子元素 |
xpath定位 By.XPATH
说明 | 举例 |
从根节点开始选取(绝对路径) | /html/div/ |
从任意节点开始选取(相对路径) | //div,列举出所有div标签 |
选取当前节点的父节点 | //input/.. 会选取 input 的父节点 |
选取属性,或者根据属性选取 | |
使用id属性定位 | //div[@id='id_value'] |
使用class属性定位 | //a[@class="mnav"] |
使用name属性定位 | //div[@name='wd'] |
多个属性定位 | //input[@name="wd" and @class="s_ipt"] |
第n个元素,使用index定位 | //div[@id="s-top-left"]/a[3] |
最后一个元素 | //a[@class="mnav"][last()] |
属性包含某字段 | //div[contains(@title,'text')] |
属性以某字段开头 | //div[starts-with(@title,'text')] |
属性以某字段结尾 | //div[ends-with(@title,'text')] |
文本包含 | //a[contains(text(),"网盘")] |
文本等于 | //span[text() = "菜单"] |
同级弟弟元素 | //div[@id=='id']/following-sibling::div |
同级哥哥元素 | //div[@id=='id']/preceding-sibling::div |
使用Chrome(谷歌浏览器)定位
使用PyCharm定位
Select 选择器
Select类的常用方法:
select_by_index(index):通过索引选择下拉列表中的选项。索引从0开始。
select_by_value(value):通过选项的value属性选择下拉列表中的选项。
select_by_visible_text(text):通过选项的可见文本选择下拉列表中的选项。
options:获取所有选项的列表,每个选项是一个WebElement对象。
all_selected_options:获取所有已选中的选项,返回一个列表,每个选项是一个WebElement对象。
first_selected_option:获取第一个已选中的选项,返回一个WebElement对象。
driver.get('https://sahitest.com/demo/selectTest.htm')
select = Select(driver.find_element_by_id("s1"))
#根据index下标进行选择,从0开始
select.select_by_index(1)
time.sleep(2)
# 根据value进行定位
select.select_by_value("48")
time.sleep(2)
# 根据展示的内容定位
select.select_by_visible_text("Home Phone")
frame框架
frame包括(frameset标签、frame标签、iframe标签)
iframe 是个内联框架,是在页面里生成个内部框架。可以嵌套多个html页面。大多网页使用的是iframe框架。
切换iframe的方法为:driver.switch_to.frame(),frame()中参数可以为id,name或者index,也可以为iframe元素
driver.get('https://sahitest.com/demo/iframesTest.htm')
driver.find_element(By.ID, 'checkRecord').clear()
driver.find_element(By.ID, 'checkRecord').send_keys("6666")
time.sleep(2)
#切换至第一个iframe
driver.switch_to.frame(0)
driver.find_element(By.ID, 'open-self').click()
driver.switch_to.frame("iframe2")
# 切换到上一级
driver.switch_to.parent_frame()
# 切换到主界面
driver.switch_to.default_content()
三种弹框
Alert弹框演示
driver.implicitly_wait(10)
driver.get('https://sahitest.com/demo/alertTest.htm')
# 根据name定位并点击
driver.find_element(By.NAME, 'b1').click()
# 使用alert.text打印确定按钮的文字
print(driver.switch_to.alert.text)
time.sleep(2)
# 使用accept进行确认,不使用click函数
driver.switch_to.alert.accept()
Confirm弹框演示
driver.implicitly_wait(10)
driver.get('https://sahitest.com/demo/confirmTest.htm')
driver.find_element(By.NAME, 'b1').click()
print(driver.switch_to.alert.text)
time.sleep(2)
# 使用accept进行确认,不使用click函数
driver.switch_to.alert.accept()
# 使用dismiss进行取消操作
# driver.switch_to.alert.dismiss()
time.sleep(2)
Prompt弹框演示
driver.implicitly_wait(10)
driver.get('https://sahitest.com/demo/promptTest.htm')
driver.find_element(By.NAME, 'b1').click()
time.sleep(2)
# alert基础上使用send_keys输入内容
driver.switch_to.alert.send_keys("七安")
driver.switch_to.alert.accept()
# 也可以用下面语法
# 先把弹框获取为一个对象
driver.implicitly_wait(10)
driver.get('http://sahitest.com/demo/promptTest.htm')
driver.find_element(By.NAME, 'b1').click()
time.sleep(2)
alert = driver.switch_to.alert
alert.send_keys("七安")
alert.accept()
time.sleep(2)
driver.close()
selenium的等待机制
影响元素加载的因素
- 计算机的性能,cpu,内存执行速度,一定程度上影响页面加载速度
- 服务器的性能,接口的响应速度,带宽一定程度上影响资源的传输时间
- 浏览器的性能,不同浏览器针对不同的网页,加载速度有区别
- 网络因素,本地网络的好差一定程度影响页面的加载速度(墙或者不墙)
等待机制包含强制等待、隐性等待、显性等待
强制等待 time.sleep(3)
优点:语法简单,粗暴。方便调试
缺点:用例中使用太多的sleep,影响执行速度。而且具体设置多少时间不好把握
import time
# 当前进程暂停3秒钟
time.sleep(3)
隐性等待 implicitly_wait()
会在约定好的时间内持续检测元素,一般找到目标元素就执行后续的操作,如果超过了约定时间未找到就报错
隐性等待需要当前页面元素全部加载完成才会执行下一步
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(5)
driver.get('http://www.baidu.com')
# 5秒内没找到就报错
driver.find_element(By.ID, 'kw1').send_keys("666")
time.sleep(2)
显性等待 WebDriverWait
显性等待更适合UI自动化,它比隐性等待更灵活,提供多种方法供使用
WebDriverWait(driver, 超时时长, 调用频率, 忽略异常).until(可执行方法, 超时后返回的信息)
locate = (By.XPATH,'/html/body/table/tbody/tr[156]/td[2]/a')
# element = WebDriverWait(driver,3).until(EC.visibility_of_element_located(locate),"找不到这个元素")
element = WebDriverWait(driver, 3).until(EC.url_contains("registry.npmmirror.com1"),"找不到这个元素")
# element.click()
判断语法 | 描述 |
title_is(title) | 判断页面title和预期title是否一致 |
title_contains(title) | 判断页面title是否包含预期title是否一致 |
presence_of_element_located(locator) | 用于检查某个元素是否出现,元素不一定可见 |
presence_of_all_elements_located(locator,locator2) | 用于检查所有元素是否出现 |
url_contains(url) | 传入url,包含时返回true |
url_matches(url) | 传入url,包含时返回true |
url_to_be(url) | 传入正则表达式 |
url_changes(url) | 传url,不匹配时返回true |
visibility_of_element_located(locator) | 参数是 locator,判断元素是否在页面DOM 中,如果在并且可见返回 True,否则返回 False |
visibility_of(WebElement) | 参数是元素,判断元表是否在页面 DOM 中,如果在并且可见返回 True,否则返回 False |
visibility_of_any_elements_located(locator) | 参数是locator,根据定位器至少应该能定位到一个可见元素,返回值是列表,如果定位不到则报错 |
visibility_of_all_elements_located(locator) | 参数是locator,判断根据定位器找到的所有符合条件的元素是否都是可见素,如果都是的话返回值是列表,定位不到或者不全是的话则报错 |
invisibility_of_element_located(locator) | 判断这个 locator的元素是否不存在或者不可见,满足条件返回 True,否则返回 False |
invisibility_of_element(locator or element) | 判断这个 locator 或者 element 是否不存在或者不可见,满足条件返回 True,否则返回 False |
frame_to_be_available_and_switch_to_it(frame_locator) | 判断frame_ locator 是否存在,存在的话切换到这个frame中,成功返回 True。不存在的话返回 False |
text_to_be_present_in_element(locator, text) | 判断text 是否出现在元素中,两个参数,返回一个布尔值 |
text_to_be_present_in_element_value(locator, text) | 判断text 是否出现在元素的属性value 中,两个参数,返回一个布尔值 |
element_to_be_clickable(locator) | 判断这个元素是否可见并且可单击,满足条件返回 True,否则返回 False |
element_to_be_selected(element) | 判断元素是否被选中,传入的参数是element,如果被选中,那么返回值是这个元素 |
alert_is_present(driver) | 判断是否有alert,有切换到该alert,没有返回False |
浏览器操作
打开、关闭、刷新浏览器
# 打开Chrome浏览器
driver = webdriver.Chrome()
# 关闭当前窗口
driver.close()
# 退出浏览器进程
driver.quit()
# 刷新浏览器
driver.refresh()
切换窗口
# 获取当前窗口句柄
driver.current_window_handle
# 获取所有窗口句柄
driver.window_handles
# 切换窗口
driver.switch_to.window()
# 打开一个标签页
driver.switch_to.new_window('tab')
driver.find_element(By.CSS_SELECTOR, 'a[href="http://news.baidu.com"]').click()
# 打印当前句柄
current_handle = driver.current_window_handle
# 循环切换,先切换第一个窗口,再切换第二个窗口
# for handle in driver.window_handles:
# if handle != current_handle:
# driver.switch_to.window(handle)
# print(handle)
# time.sleep(2)
# all_handles = driver.window_handles
# # 根据下标去取
# driver.switch_to.window(all_handles[1])
# driver.find_element(By.CSS_SELECTOR, 'a[href="//help.baidu.com"]').click()
# 打开新标签
driver.switch_to.new_window("tab")
driver.get("https://www.bilibili.com")
浏览器窗口最大化,最小化
maximize_window()
窗口最大化minimize_window()
窗口最小化
driver = webdriver.Chrome()
driver.get('https://www.bilibili.com/')
driver.maximize_window() # 窗口最大化
time.sleep(2)
driver.minimize_window() # 窗口最小化
time.sleep(2)
driver.close()
获取浏览器窗口大小,设置窗口大小
get_window_size()
# 获取浏览器窗口大小set_window_size(width=1000, height=500)
# 设置浏览器窗口
driver = webdriver.Chrome()
driver.get('https://www.bilibili.com/')
size = driver.get_window_size() # 获取浏览器窗口大小 {'width': 1200, 'height': 829}
print(size)
driver.set_window_size(width=1000, height=500) # 设置浏览器窗口
time.sleep(2)
driver.close()
获取页面title,url,源代码
driver.title
页面titledriver.current_url
页面url地址driver.page_source
页面源代码
driver = webdriver.Chrome()
driver.get('https://www.bilibili.com/')
title = driver.title # 页面title
url = driver.current_url # 页面url地址
page = driver.page_source # 页面源代码
获取元素的相关信息
获取元素的信息可以为执行用例后进行断言或者作为前置条件
- 获取元素的文本
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://www.baidu.com/")
element1 = driver.find_element(By.CSS_SELECTOR, 'a[href="http://news.baidu.com"]')
element2 = driver.find_element(By.ID, 'su')
element3 = driver.find_element(By.XPATH, '//span[@class="title-content-title"]')
# a标签
print(element1.text)
# button标签要使用accessible_name
print(element2.accessible_name)
# span标签
print(element3.text)
- 获取元素是否可用
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://sahitest.com/demo/clicks.htm")
element3 = driver.find_element(By.XPATH, '/html/body/form/input[5]')
# disabled返回False,否则返回True
print(element3.is_enabled())
- 判断元素是否选中
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://sahitest.com/demo/clicks.htm")
element2 = driver.find_element(By.XPATH, '/html/body/form/input[6]')
# 没选中为False
print(element2.is_selected())
element2.click()
# 选中为True
print(element2.is_selected())
网页的前进和后退
driver.back()
后退driver.forward()
前进
鼠标操作
selenium提供模拟鼠标操作的功能,常见的鼠标操作有:单击、右键点击、双击、移动鼠标、拖拽鼠标
selenium工具中全局鼠标操作语法如下:
第1步:初始化ActionChians类(动作链条): actions = ActionChains(driver)
第2步:找到要操作的元素: find_element
第3步:调用鼠标操作方法: actions.move_to_element(element)
第4步:执行鼠标操作方法: actions.perform()
具体用法:ActionChains(driver).click(element).perform()
初始化ActionChians→找到对应元素element→调用鼠标操作方法click()→执行鼠标操作方法perform()
鼠标操作 | 关键字 | 解释 |
单击 | click | 单击鼠标左键在元素上。 |
双击 | double_click | 双击鼠标左键在元素上。 |
右击 | context_click | 单击鼠标右键在元素上。 |
鼠标悬停 | move_to_element | 将鼠标悬停在指定的元素上。 |
拖放 | drag_and_drop | 将一个元素拖放到另一个元素上。 |
拖放到坐标点 | drag_and_drop_by_offset | 将一个元素拖放到指定的坐标点上。 |
移动到坐标点 | move_by_offset | 将鼠标移动到指定的坐标点上。 |
鼠标按下 | click_and_hold | 按下鼠标左键在元素上,但不释放。 |
鼠标释放 | release | 释放鼠标左键,用于与click_and_hold一起使用。 |
双击并按住 | double_click_and_hold | 双击鼠标左键在元素上并按住,用于与release一起使用。 |
JavaScript应用
Selenium提供了execute_script方法,用来执行JavaScript,从而完成一些特殊的操作
操作页面元素
driver.get('https://www.baidu.com/')
driver.execute_script('document.getElementById("kw").value="selenium"')
driver.execute_script('document.getElementById("su").click()')
操作滚动条
driver.get('https://news.baidu.com/')
# 向下滑动200像素
driver.execute_script("window.scrollTo(0,200)")
time.sleep(2)
# 滑动到顶部
driver.execute_script("window.scrollTo(0,0)")
time.sleep(2)
#滑动到底部
driver.execute_script("window.scrollTo(0,document.body.scrollHeight)")
JS处理元素不可见解决方式
element = driver.find_element_by_xpath("表达式")
driver.execute_script("arguments[0].click();", element)
element = driver.find_element_by_xpath("表达式")
driver.execute_script("arguments[0].scrollIntoView();", element)
element = driver.find_element_by_xpath("表达式")
driver.execute_script("arguments[0].scrollIntoViewIfNeeded(true);", element)