做ui自动化时,最头疼的地方莫过于元素查找的不稳定,经常会发现,代码昨天还好好的执行,今天怎么执行就报了个找不到元素的错误。通常这里使用等待来解决,介绍几种常见的等待方法,如果能完美解决问题,来找我。如果不能解决问题,就别找我了 - ,-

一、强制等待 

sleep()

俗称死等,这种等待方式,等待时间到达,就会继续执行下面的语句,这种等待方式比较死板,不能保证元素的加载情况已经网络情况。

import time

print('当前时间为:',time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))
time.sleep(3)
print('现在时间为:',time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))

结果为:

当前时间为: 2019-08-27 09:13:00
现在时间为: 2019-08-27 09:13:03

这种等待好处是你可以控制等待的时长,如果不稳定可以多等一些时间,但坏处也同样体现出来,等待时间如果远大于元素加载的时间了。这个等待的时间就是无用的时间,非常浪费

二、隐形等待

driver.implicitly_wait()

这个等待表示在规定的时间内页面所有元素都加载完了就执行下一步,否则一直等到超时,再去执行下一步。这个方法比较灵活,但缺点是,如果页面元素加载完成了,但是页面还没有加载完成,这时就发生了页面还没有展示完,需要等待页面元素加载完之后才去执行下一步。

import time
from selenium import webdriver
d = webdriver.Chrome()
print('当前时间为:',time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))
d.implicitly_wait(10)
d.get('https://www.cnblogs.com/dflblog/default.html?page=1')
print('当前时间为:',time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))
d.quit()

结果为:

当前时间为: 2019-08-27 09:30:03
当前时间为: 2019-08-27 09:30:06

三、显性等待

WebDriverWait(driver=d,timeout=10,poll_frequency=0.5).until(expected_conditions.presence_of_element_located(('xpath','//*[contains(@id,"kw")]')))

selenium中的方法,需要引入WebDriverWait包以及exception_conditions,wait方法配合ec的until或者until_not,可以实现针对于某一个元素等待,每经过多少秒就查看一次元素是否可见,如果可见就停止等待,如果不可见就继续等待直到超过规定的时间后,报超时异常;这种方法就比较常用,可以灵活的使用各种场景

这里不演示结果了

from selenium import webdriver
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait

d = webdriver.Chrome()

WebDriverWait(driver=d,timeout=10,poll_frequency=0.5).until(expected_conditions.presence_of_element_located(('xpath','//*[contains(@text,"测试文本")]')))

d.quit()

当然,ec还有很多其他的方法可以用,下面介绍一些,也可以自行百度。

from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
driver = webdriver.Chrome()

WebDriverWait(driver,10).until(EC.title_is("百度一下,你就知道"))
'''判断title,返回布尔值'''

WebDriverWait(driver,10).until(EC.title_contains("百度一下"))
'''判断title,返回布尔值'''

WebDriverWait(driver,10).until(EC.presence_of_element_located(('id','kw')))
'''判断某个元素是否被加到了dom树里,并不代表该元素一定可见,如果定位到就返回WebElement'''

WebDriverWait(driver,10).until(EC.visibility_of_element_located(('id','kw')))
'''判断某个元素是否被添加到了dom里并且可见,可见代表元素可显示且宽和高都大于0'''

WebDriverWait(driver,10).until(EC.visibility_of(('id','kw')))
'''判断元素是否可见,如果可见就返回这个元素'''

WebDriverWait(driver,10).until(EC.presence_of_all_elements_located(('id','kw')))
'''判断是否至少有1个元素存在于dom树中,如果定位到就返回列表'''

WebDriverWait(driver,10).until(EC.text_to_be_present_in_element(('id','kw'),'设置'))
'''判断指定的元素中是否包含了预期的字符串,返回布尔值'''

WebDriverWait(driver,10).until(EC.text_to_be_present_in_element_value(('id','kw'),u'百度一下'))
'''判断指定元素的属性值中是否包含了预期的字符串,返回布尔值'''

WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it(('id','kw')))
'''判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False'''
#注意这里并没有一个frame可以切换进去

WebDriverWait(driver,10).until(EC.invisibility_of_element_located(('id','kw')))
'''判断某个元素在是否存在于dom或不可见,如果可见返回False,不可见返回这个元素'''
#注意#swfEveryCookieWrap在此页面中是一个隐藏的元素

WebDriverWait(driver,10).until(EC.element_to_be_clickable(('id','kw'))).click()
'''判断某个元素中是否可见并且是enable的,代表可点击'''
#WebDriverWait(driver,10).until(EC.element_to_be_clickable(('id','kw'))).click()

WebDriverWait(driver,10).until(EC.staleness_of(('id','kw')))
'''等待某个元素从dom树中移除'''
#这里没有找到合适的例子

WebDriverWait(driver,10).until(EC.element_to_be_selected(('id','kw')))
'''判断某个元素是否被选中了,一般用在下拉列表'''

WebDriverWait(driver,10).until(EC.element_selection_state_to_be(('id','kw'),True))
'''判断某个元素的选中状态是否符合预期'''

WebDriverWait(driver,10).until(EC.element_located_selection_state_to_be(('id','kw'),True))
'''判断某个元素的选中状态是否符合预期'''

WebDriverWait(driver,10).until(EC.alert_is_present())
'''判断页面上是否存在alert,如果有就切换到alert并返回alert的内容'''