这两天在学习显式等待,其实就是把expected_conditions模块下的几个类实践,去敲一下。上周六学到visibility_of()遇到些问题,今天分享下
个人博客:https://blog.csdn.net/zyooooxie
一)visibility_of()
这是源码:
class visibility_of(object):
""" An expectation for checking that an element, known to be present on the
DOM of a page, is visible. Visibility means that the element is not only
displayed but also has a height and width that is greater than 0.
element is the WebElement
returns the (same) WebElement once it is visible
"""
def __init__(self, element):
self.element = element
def __call__(self, ignored):
return _element_if_visible(self.element)
翻译下注释:visibility_of()这个类是检查元素存在DOM页的,要能够看得到;可见就代表元素不仅仅只是显示,还要求宽和高大于0;
需要传入一个WebElement;一旦可见返回相同的WebElement;
我的总结是这个类需要传入一个element;可见就返回这个element,不可见就返回False;
二)不存在的元素
这是一个错误的例子!!!
是我的思路跑偏了:visibility_of()用来判断元素是否可见-不存在的元素肯定不可见,所以就掉到自己挖的坑里。
正确的思路应该是:元素是否可见,1.可见 2.不可见,不可见那就是隐藏、不显示。
先分享 这个不存在的例子
def test_57k1(self):
"""expected_conditions模块visibility_of(element) """
# 判断element元素是否可见。直接传element;如果可见就返回这个元素,不可见就返回False
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get("https://www.baidu.com")
print('开始', time.ctime())
print(EC.visibility_of(self.driver.find_element(By.CSS_SELECTOR, 'input#kw'))(self.driver)) # 传入driver 返回一个WebElement
print(EC.visibility_of(self.driver.find_element(By.CSS_SELECTOR, 'input#kw'))(self.driver).get_attribute('class')) # 成功返回一个WebElement 可获取tag_name\\获取class属性值
print('1', time.ctime())
try:
print(EC.visibility_of(self.driver.find_element(By.CSS_SELECTOR, 'input#kw123'))(self.driver)) # 查找一个不存在的元素
except BaseException as e111:
print(e111) # 报错的是 no such element: Unable to locate element
print('2', time.ctime())
print(WebDriverWait(self.driver, 10).until(EC.visibility_of(self.driver.find_element(By.CSS_SELECTOR, 'input#kw')))) # 显式等待 + 判断这个元素是否可见
print(WebDriverWait(self.driver, 10).until(EC.visibility_of(self.driver.find_element(By.CSS_SELECTOR, 'input#kw'))).tag_name)
print('3', time.ctime())
try:
print('ABC', time.ctime())
WebDriverWait(self.driver, 10).until(EC.visibility_of(self.driver.find_element_by_css_selector('input#kw123')), '失败') # 一个不存在的元素
except BaseException as e222:
print('BCD', time.ctime())
print(e222) # Message: no such element: Unable to locate element
self.assertEqual(WebDriverWait(self.driver, 10).until(EC.visibility_of(self.driver.find_element(By.ID, 'su'))).tag_name, 'input')
# 如果传入的WebElement是找不到,定位不了的,实际用不到until方法,更不要提显式等待的20秒
print('end', time.ctime())
time.sleep(1)
self.driver.quit()
上图的结果 可以清楚的看得到时间是不对的,按照预期,应该有一个10秒的显式等待的查找时间啊。我就想 为啥没有查找时间呢?
想了2天,还是没想通,直到被同事的一句话: 那个数字是什么?
WebDriverWait(self.driver, 10).until(EC.visibility_of(self.driver.find_element_by_css_selector(‘input#kw123’)), ‘失败’)
这行代码最初msg不是‘失败’,是我随手打得一串数字,同事问我,我才突然醒悟:打印的msg不是那串数字,也就是说 并非是显式等待的错误!是没找到元素的错误 = =
三)不显示、隐藏的元素
这是一个正确的例子!
12306网站上有些元素是隐藏的,所以拿来做例子。
def test_57k2(self):
"""expected_conditions模块visibility_of(element) """
# 判断element元素是否可见。直接传element;如果可见就返回这个元素;不可见就返回 False
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get("https://www.12306.cn/index/")
print('开始', time.ctime())
# <input id="toStation" type="hidden" value="" name="to_station">
# 这个元素默认是隐藏的
print(EC.visibility_of(self.driver.find_element(By.ID, 'toStation'))(self.driver)) # 传入driver 不可见 返回False
print('1', time.ctime())
# <input type="text" class="input error" value="" id="toStationText">
# 这个元素是可见的
print(EC.visibility_of(self.driver.find_element(By.ID, 'toStationText'))(self.driver)) # 传入driver 如果找到就返回一个WebElement
print(EC.visibility_of(self.driver.find_element(By.ID, 'toStationText'))(self.driver).tag_name)
print('2', time.ctime())
try:
WebDriverWait(self.driver, 10).until(EC.visibility_of(self.driver.find_element(By.ID, 'toStation')), '失败') # 这是隐藏的
except BaseException as e111:
print(e111)
print('3', time.ctime())
try:
WebDriverWait(self.driver, 10).until(EC.visibility_of(self.driver.find_element(By.ID, 'toStationText')), '失败') # 这是显示的
print('这是可见的')
except BaseException as e1112:
print(e1112)
print('4', time.ctime())
# id="toStation"到达地 type="hidden" 所以要先删除属性
sc11 = 'document.getElementById("toStation").removeAttribute("type")'
self.driver.execute_script(sc11)
time.sleep(2)
print('10', time.ctime())
# 到达地toStation 这个元素是隐藏的,强制等待的过程就看得到这个方框;
try:
WebDriverWait(self.driver, 10).until(EC.visibility_of(self.driver.find_element(By.ID, 'toStation')), '失败') # 这次是可见的
print('这次是可见的')
except BaseException as e1111:
print(e1111)
print('11', time.ctime())
print('end', time.ctime())
time.sleep(1)
self.driver.quit()
对比两个图片 就可以看得到有一个元素被显示出来了。代码中 最初显式等待+判断这个元素是否显示,返回的是失败;再移除type属性后,故而元素是可见的。结果如下图,
这个类的坑不好爬,所以不太推荐使用这个来做显式等待的判断条件。
交流技术 欢迎+QQ 153132336 zy
个人博客 https://blog.csdn.net/zyooooxie