当有元素定位不到时,比如下拉框,弹出框等各种定位不到时;

一般是两种问题:1 、有frame ;2、没有加等待

下面学习三种等待方式:

2.1 强制等待 sleep(xx)或者Time.sleep

是在程序运行过程中使用time模块中的sleep进行代码的休眠进行强制等待,是显式等待中的一种极端情况。

这种方法简单粗暴,不管浏览器是否加载完,程序都要等待规定的xx时间,时间到了才继续执行下面的代码。

不建议总是用这种等待方式,会严重影响程序的执行速度。通过time模块中sleep进行代码的暂停,但是实际使用过程中,如果都以sleep进行控制严重影响了程序的运行。

2.1.1 参考代码1
#coding=utf-8🔥
#1.先设置编码,utf-8可支持中英文,如上,一般放在第一行
#2.注释:包括记录创建时间,创建人,项目名称。
'''Created on 2019-12-10
@author: 北京-宏哥 QQ交流群:705269076
Project: 《手把手教你》系列练习篇之9-python+ selenium自动化测试'''
#3.导入模块
importtime#强制等待——代码休眠
from selenium importwebdriver
driver=webdriver.Chrome()
driver.get("https://www.baidu.com")
time.sleep(3)
driver.quit()
2.1.2 参考代码2
#coding=utf-8🔥
#1.先设置编码,utf-8可支持中英文,如上,一般放在第一行
#2.注释:包括记录创建时间,创建人,项目名称。
'''Created on 2019-12-10
@author: 北京-宏哥 QQ交流群:705269076
Project: 《手把手教你》系列练习篇之9-python+ selenium自动化测试'''
#3.导入模块
from selenium importwebdriverfrom time importsleep
driver=webdriver.Chrome()
driver.get('https://www.baidu.com/')
sleep(3)#强制性等待3s再执行以下代码
print(driver.current_url)
driver.quit()#退出驱动,关闭所有窗口
2.2 隐性等待 implicitly_wait(xx)
这种方法是设置一个最长的等待时间,如果在规定时间内网页全部元素加载完成,则执行下一步,否则一直等待时间截止才执行下一步。比强制性等待智能些
!隐性等待对整个driver的周期都起作用,所以只要设置一次即可
2.2.1 参考代码1
# coding=utf-8🔥
# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行
# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2019-12-10
@author: 北京-宏哥 QQ交流群:705269076
Project: 《手把手教你》系列练习篇之9-python+ selenium自动化测试
'''
# 3.导入模块
from selenium importwebdriver
from selenium.common.exceptions importNoSuchElementException
from time importctime
driver =webdriver.Firefox()
# 设置隐式等待为10秒
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
try:
print(ctime())
driver.find_element_by_id("kw22").send_keys('selenium')
exceptNoSuchElementException as e:
print(e)
finally:
print(ctime())
driver.quit()
这里可以看到在10秒内没有找到想要找到的元素,但是依旧执行了10秒,然后报错,如果修改代码为可以找到,代码执行非常迅速。
implicitly_wait()默认参数的单位为秒,本例中设置等待时长为10秒。首先这10秒并非一个固定的等待时间,它并不影响脚本的执行速度。其次,它并不针对页面上的某一元素进行等待。当脚本执行到某个元素定位时,如果元素可以定位,则继续执行;如果元素定位
不到,则它将以轮询的方式不断地判断元素是否被定位到。假设在第6秒定位到了元素则继续执行,若直到超出设置时长(10秒)还没有定位到元素,则抛出异常。
2.2.2 参考代码2
#coding=utf-8🔥
#1.先设置编码,utf-8可支持中英文,如上,一般放在第一行
#2.注释:包括记录创建时间,创建人,项目名称。
'''Created on 2019-12-10
@author: 北京-宏哥 QQ交流群:705269076
Project: 《手把手教你》系列练习篇之9-python+ selenium自动化测试'''
#3.导入模块
from selenium importwebdriver
driver=webdriver.Chrome()
driver.get('https://www.baidu.com/')
driver.implicitly_wait(30)#隐性等待,最长30s
print(driver.current_url)
driver.quit()
2.3.显性等待 WebDriverWait
WebDriverWait配合该类的until()和until_not()方法,根据条件灵活的等待
程序每隔xx秒看一眼,如果条件成立了,则执行下一步,否则继续等待,直到超过设置的最长时间,然后抛出TimeoutException。
显式等待是你在代码中定义等待一定条件发生后再进一步执行你的代码。
A. 使用前,先引用相关库
B. 确定元素的定位表达式
C.  使用expected_conditions对应的方法来生成判断条件
WebDriverWait(driver,10,1).until(EC.visibility_of_element_located((By.ID,ele_locator)))
WebDriverWait(driver,10,1).until(EC.visibility_of_element_located((By.XPATH,ele_locator)))
D.  调用WebDriverWait类设置等待总时长、轮询周期
2.3.1 参考代码1
#coding=utf-8🔥
#1.先设置编码,utf-8可支持中英文,如上,一般放在第一行
#2.注释:包括记录创建时间,创建人,项目名称。
'''Created on 2019-12-10
@author: 北京-宏哥 QQ交流群:705269076
Project: 《手把手教你》系列练习篇之9-python+ selenium自动化测试'''
#3.导入模块
#A. 使用前,先引用相关库
from selenium importwebdriverfrom selenium.webdriver.support.wait importWebDriverWaitfrom selenium.webdriver.support importexpected_conditions as ECfrom selenium.webdriver.common.by importBy
driver= webdriver.Chrome()#打开Chrome浏览器
driver.get('https://www.baidu.com/')#打开百度
driver.find_element_by_xpath('//div[@id="u1"]//a[@name="tj_login"]').click()#点击【登录】;click() 方法,可模拟在按钮上的一次鼠标单击。#B. 确定元素的定位表达式
ele_locator = "TANGRAM__PSP_10__footerULoginBtn"#通过id,确定‘用户名登录’元素
#C. 使用expected_conditions对应的方法来生成判断条件#EC.方法名(定位方式,定位表达式)#EC.visibility_of_element_located(By.ID,ele_locator)#元素可见
#D. 调用WebDriverWait类设置等待总时长、轮询周期#WebDriverWait(driver, 超时时长, 调用频率(默认0.5s)).until(可执行方法, 超时时返回的信息)#等待10秒钟,每隔1秒去查看对应的元素是否可见;如果可见,继续下一步操作;如果不可见,则继续等待,直到10s结束,如果元素还是不可见,则抛出超时异常
WebDriverWait(driver,10,1).until(EC.visibility_of_element_located((By.ID,ele_locator)))
driver.find_element_by_id('TANGRAM__PSP_10__footerULoginBtn').click()#点击【用户名登录】
driver.close()#关闭当前窗口
2.3.2 参考代码2
# coding=utf-8🔥
# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行
# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2019-12-10
@author: 北京-宏哥 QQ交流群:705269076
Project: 《手把手教你》系列练习篇之9-python+ selenium自动化测试
'''
# 3.导入模块
from time importctime
from selenium importwebdriver
from selenium.webdriver.common.by importBy
from selenium.webdriver.support.ui importWebDriverWait
from selenium.webdriver.support importexpected_conditions as EC
dr =webdriver.Chrome()
dr.get('https://www.baidu.com')
try:
print(ctime())
element = WebDriverWait(dr, 10).until(
EC.presence_of_element_located((By.ID, "kw"))
)
# WebDriverWait(driver=self.driver, timeout=300, poll_frequency=0.5, ignored_exceptions=None)
# driver:浏览器驱动
# timeout:最长超时等待时间
# poll_frequency:检测的时间间隔,默认为500ms
# ignore_exception:超时后抛出的异常信息,默认情况下抛 NoSuchElementException 异常
print("我已找到")
finally:
print(ctime())
dr.quit()
执行结果:

以上代码执行后就发现,整段代码执行速度非常快,即使我在WebDriverWait中设置10秒,也不会等待10秒的情况,因为在不到一秒内,已经完成了加载并定位id为“kw”的元素。
通过WebDriverWait 和 ExpectedCondition 组合使用,让我们的代码执行只需要等待需要的时长,而不是固定的时长,这样最大限度的节省时间。
此外ExpectedCondition类中提供了很多预期条件判断方法,省去了再创建包的功夫:
"""title_is:判断当前页面的title是否等于预期
title_contains:判断当前页面的title是否包含预期字符串
presence_of_element_located:判断某个元素是否被加到了dom树里,并不代表该元素一定可见
visibility_of_element_located:判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0
visibility_of:跟上面的方法做一样的事情,只是上面的方法要传入locator,这个方法直接传定位到的element就好了
presence_of_all_elements_located:判断是否至少有1个元素存在于dom树中。举个例子,如果页面上有n个元素的class都是'column-md-3',那么只要有1个元素存在,这个方法就返回True
text_to_be_present_in_element:判断某个元素中的text是否 包含 了预期的字符串
text_to_be_present_in_element_value:判断某个元素中的value属性是否包含了预期的字符串
frame_to_be_available_and_switch_to_it:判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False
invisibility_of_element_located:判断某个元素中是否不存在于dom树或不可见
element_to_be_clickable - it is Displayed and Enabled:判断某个元素中是否可见并且是enable的,这样的话才叫clickable
staleness_of:等某个元素从dom树中移除,注意,这个方法也是返回True或False
element_to_be_selected:判断某个元素是否被选中了,一般用在下拉列表
element_located_to_be_selected
element_selection_state_to_be:判断某个元素的选中状态是否符合预期
element_located_selection_state_to_be:跟上面的方法作用一样,只是上面的方法传入定位到的element,而这个方法传入locator
alert_is_present:判断页面上是否存在alert"""
另外这里使用了until()函数也可以使用until_not()
until_not(method, message='')
调用该方法体提供的回调函数作为一个参数,直到返回值为False
until(method, message='')

调用该方法体提供的回调函数作为一个参数,直到返回值为True

3. 下拉框or弹框