4.7 设置元素等待
分 显式等待和隐式等待
4.7.1 显式等待
是Webdriver等待某个条件成立时则继续执行,否则在达到最大时长时抛出超时异常
官网原文: 显示等待是selenium客户可以使用的命令式过程语言。它们允许您的代码暂停程序执行,或冻结线程,直到满足通过的条件。这个条件会以一定的频率一直被调用,直到等待超时。这意味着只要条件返回一个假值,它就会一直尝试和等待。
由于显示等待允许您等待条件的发生,所以它们非常适合在浏览及其DOM和Webdriver脚本之间同步状态。
为了弥补我们之前的错误指令集,我们可以使用等待来让FindElement调用等待直到脚本中动态添加的元素被添加到DOM中。 但官网中的例子代码,跑不通。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
# from selenium.webdriver.support.wait import WebDriverWait # 官网用的,试验了,也能用
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
element = WebDriverWait(driver,5,0.5).until(
EC.visibility_of_element_located((By.ID,'kw')) # 该方法只允许1个参数,所以(By.ID,'kw')应该括起来做为1个参数
)
element.send_keys('selenium')
driver.quit()
WebDriverWait是一种等待方法。在设置时间内,默认每隔一段时间检测一次当前页面元素是否存在。如果超出设置时间仍检测不到,则抛出异常。
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
WebDriverWait()一般与until() 或 until_not()方法配合使用。
until() 调用该方法提供的一个驱动程序作为一个参数,直到返回值为True
而until_not()则直到返回值为False
本来想通过在visibility_of_element_located()后面加上print(time.time()),验证WebDriverWait,但发现这样写会千万语法问题。
文中说,超时后的异常信息,默认情况下抛出NoSuchElementException异常。但通过下面的试验,看到抛出的是TimeoutException。
如果将kw改成k1w,再执行,就会定位不到元素,超过5秒后,抛出超时异常
raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message:
excepted_conditions类提供的预期条件判断方法
方法 | 说明 |
title_is | 判断当前页面的标题是否等于预期 |
title_contains | |
presence_of_element_located | 判断元素是否被加在DOM中,并不代表可见 |
visibility_of_element_located | 判断元素是否可见 |
visibility_of | 与上一个方法作用相同,上一个方法的参数为定位,该方法接收的参数为定位后的元素 |
text_to_be_present_in_element | 判断某元素中的text是否包含预期的字符串 |
text_to_be_present_in_element_value | 判断某元素的value属性是否包含预期的字符串 |
frame_to_be_available_and_switch_to_it | 判断该表单是否可以切换进去,如果可以,返回True并且切换进去 |
element_bo_be_selected | 判断某个元素是否被选中,一般用在下拉列表中 |
alert_is_present | 判断页面上是否存在alert |
from time import sleep,ctime
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
print(ctime())
for i in range(10):
try:
el = driver.find_element(By.ID,'kw22')
if el.is_displayed(): # 使用is_displayed()确认元素是否可见
break
except:
pass
sleep(1)
else:
print('time out')
print(ctime())
driver.quit()
4.7.2 隐式等待
implicitly_wait()
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import ctime
from selenium.common.exceptions import NoSuchElementException
driver = webdriver.Chrome()
driver.implicitly_wait(10) ###
driver.get('https://www.baidu.com')
try:
print(ctime())
driver.find_element(By.ID,'kw22').send_keys('selenium')
except NoSuchElementException as e:
print(e)
finally:
print(ctime())
driver.quit()
implicitly_wait()的参数是时间,单位秒。首先,这个参数并非一个固定的等待时间,它并不影响脚本的执行速度。其次,它会等待页面上所有元素。当脚本执行到某个元素时,如果元素存在,则继续执行;如果定位不到元素,则它将以轮询的方式不断地判断元素是否存在。假设在第6s定位到了元素,则继续执行,若直到超出设置时间还没有定位到元素,则抛出异常。 感觉这段话的描述,与显示等待,没有什么区别。不知道是我理解错误,还是描述错误。
官网中对隐式等待的描述是:
通过隐式等待,webdriver在试图查找 任何 元素时在一定时间内轮询DOM(这倒是与上述一个意思)。当网页上的某些元素不是立即可用并且需要一些时间来加载是是很有用的。
默认情况下隐式等待元素出现是禁用的,它需要在单个会话的基础上手动启用。将显示等待和隐式等待混合在一起会导致意想不到的结果,就是说即便元素可用或条件为真也要等待睡眠的最长时间。
警告:不要混合使用隐式和显式等待。这样会导到不可预测的等待时间。例如,将隐式等待设置为10s,将显式等待设置为15s,可能会导致在20S后发生超时。
隐式等待是告诉webdriver如果在查找一个或多个不是立即可用的元素时轮询DOM一段时间。默认设置为0,表示禁用。一旦设置好,隐式等待就会被设置为会话的生命周期。
隐式等待与显式等待的区别,有的网文说,隐式等待在等待时间内浏览器会不断刷新页面去等待。我觉得这不可能。因为使用隐式等待时,没有发现页面刷新的现象。......
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import ctime,sleep
from selenium.common.exceptions import NoSuchElementException
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('https://www.baidu.com')
s_word = 'kw22'
for i in range(10):
if i < 3:
print(i," ",s_word," ",ctime()," ",end="") ##不换行 end=''
try:
el = driver.find_element(By.ID,s_word)
if el.is_displayed():
break
except:
print(ctime()," 定位不到元素")
i = i +1
continue
elif i == 3:
s_word = 'kw'
print(i," ",s_word," ",ctime())
driver.find_element(By.ID,s_word).send_keys('selenium')
else:
break
print("验证continue时,该语句的执行情况")
sleep(5)
driver.quit()
将continue改成pass后
从上面的代码,可以得到2点:
1 设置了隐式等待为10秒,当try进行元素定位时,只有超过10秒仍定位不到,才会向下走其它代码。
2 定位失败时,当用continue时,不再执行后面的print代码,直接执行下一次迭代,只有当下次迭代因为if条件不满足,没有执行continue时,而是执行了elif时才同时执行了print;当用pass时,每次迭代都会执行后面的print;同时如果运行了break,则是停止上一层(如果有多层循环)的所有循环迭代。
第2点,没问题了。但第1点,定位元素只有1条,如果是有多条定位元素,是每条都10秒,还是一起10秒?
发现是一起10秒
如果将2个定位语句分开呢?因为try中如果前面的第1条定位如果发生异常,后面的第2条定位应该是不会执行异常。
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import ctime,sleep
from selenium.common.exceptions import NoSuchElementException
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('https://www.baidu.com')
s_word = 'kw22'
s_word2 = 'su22'
for i in range(10):
if i < 3:
print(i," ",s_word," ",ctime()," ",end="") ##不换行 end=''
try:
el = driver.find_element(By.ID,s_word)
if el.is_displayed():
break
except:
print(ctime()," 定位不到第1个元素",end='')
try:
el2 = driver.find_element(By.ID,s_word2)
if el2.is_displayed():
break
except:
print(' ',ctime()," 定位不到第2个元素")
i = i +1
pass
elif i == 3:
s_word = 'kw'
s_word2 = 'su'
print(i," ",s_word," ",s_word2," ",ctime())
driver.find_element(By.ID,s_word).send_keys('selenium')
driver.find_element(By.ID,s_word2).click()
else:
break
print("验证pass时,该语句的执行情况")
sleep(5)
driver.quit()
由此可知,每条定位元素的语句的执行,都会最长进行10秒。
除了上面的2种等待,还有 强制等待(sleep()), 和官网上提到的 流畅等待。但看着跟显式等待是一样的啊
driver = Firefox()
driver.get("http://somedomain/url_that_delays_loading")
wait = WebDriverWait(driver, timeout=10, poll_frequency=1, ignored_exceptions=[ElementNotVisibleException, ElementNotSelectableException])
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//div")))
标签:WebDriver,webdriver,--,selenium,driver,element,import,等待 From: https://www.cnblogs.com/guohui2022/p/16894205.html