用Selenium跑自动化时会出现下拉框定位不到,弹出框等定位不到的问题,其实大多数情况是两种问题:1.有Frame. 2.没有加等待。
Selenium等待方式有强制等待,隐式等待和显示等待
1.强制等待
第一种也是最简单粗暴的一种方法就是强制等待sleep(xx)
WebDriver driver=new FireFoxDriver();
driver.get("www.baidu.com");
Thread.sleep(3);//强制等待3秒再执行下一步
driver.quit();
这种叫强制等待,不管
浏览器是否加载完成,程序都得等待3秒,3秒一到,继续执行下面的代码,作为调试很有用,但不建议总是用这种等待方式,太死板,会
严重影响程序执行速度。
2.隐式等待
第二种方式叫隐式等待,implicitly_wait(xx),隐式等待的意义在于等待规定时间内查找对应元素,如果在规定时间内没找到,那就跑出异常。
实例代码:
WebDriver driver=new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(2,TimeUnit.SECONDS) //注:这里的TimeUnit.SECONDS可以改为其他的计数单位,如TimeUnit.MINUTES.
driver.get("http://www.baidu.com");
driver.quit();
隐式等待是设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间截止,然后执行下一步。
这种方式有一个弊端,就是程序会一直等待整改页面加载完成,也就是一般情况下你看到的浏览器标签栏那个小圈不再转了,才会执行下一步,但有时候页面想要的
元素早就加载完成了,但是因为个别js之类的东西特别慢,程序仍然要等到页面全部完成才能执行下一步,我想要等我要的元素出来之后就进行下一步怎么办?那就是要看Selenium
提供的另一种等待方式-显式等待。
需要特别说明的是:隐式等待对整个driver的周期都起作用,所以只需要设置一次即可。不能将隐式等待当成sleep在用。
3.显式等待
wait模块的WebDriverWait类是显性等待类,先看看这个类下有哪些参数和方法:
Selenium.webdriver.support.ait.WebDriverWait类
_init_
driver:传入WebDriver实例,即上面提到的driver
timeout:超时时间,等待最长时间(同时要考虑隐式等待时间)
poll_frequency:调用until或者until_not中的方法的间隔时间,默认是0.5秒
ignored_exceptions:忽略的异常,如果在调用until或者until_not的过程中抛出这个元祖中的异常,则中断代码,抛出异常。默认
只有NoSuchElementException。
until
method:在等待期间,每隔一段时间调用这个传入的方法,直到范围值不是false
messages:如果超时,抛出TimeoutException,将message传入异常
until_not与until相反,until是当某元素出现或者什么条件成立则继续执行,
until_not是当某元素消失或什么条件不成立则继续执行,参数也相同。
调用方法如下:
WebDriverWait(driver,超时时长,调用频率,忽略异常).until(可执行方法,超时返回的信息)
这里需要特别注意的是until或until_not中的可执行方法method参数,很多人传入了WebElement对象,如下:
WebDriverWait(driver,10).until(driver.findElementByID('kw'))#这种写法错误
这是错误的用法,这里的参数一定要是可以调用的,即这个对象一定有_call_()方法,否则会抛出异常:
TypeError:‘xxx’ object is not callable
你可以用selenium提供的 expected_conditions
模块中的各种条件,也可以用WebElement的is_displayed()
、is_enabled()
、is_selected()
方法,或者用自己封装的方法都可以,那么接下来我们看一下selenium提供的条件有哪些:
expected_conditions
expected_conditions是selenium的一个模块,其中包含一系列可用于判断的条件:
selenium.webdriver.support.expected_conditions(模块)
这两个条件类验证title,验证传入的参数title是否等于或包含于driver.title
title_is
title_contains
这两个人条件验证元素是否出现,传入的参数都是元组类型的locator,如(By.ID,顾名思义,一个只要一个符合条件的元素加载出来就通过;另一个必须所有符合条件的元素都加载出来才行
presence_of_element_located
presence_of_all_elements_located
这三个条件验证元素是否可见,前两个传入参数是元组类型的locator,第三个传入WebElement
第一个和第三个其实质是一样的
visibility_of_element_located
invisibility_of_element_located
visibility_of
这两个人条件判断某段文本是否出现在某元素中,一个判断元素的text,一个判断元素的value
text_to_be_present_in_element
text_to_be_present_in_element_value
这个条件判断frame是否可切入,可传入locator元组或者直接传入定位方式:id、name、index或WebElement
frame_to_be_available_and_switch_to_it
这个条件判断是否有alert出现
alert_is_present
这个条件判断元素是否可点击,传入locator
element_to_be_clickable
这四个条件判断元素是否被选中,第一个条件传入WebElement对象,第二个传入locator元组
第三个传入WebElement对象以及状态,相等返回True,否则返回False第四个传入locator以及状态,相等返回True,否则返回Falseelement_to_be_selected
element_located_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be
最后一个条件判断一个元素是否仍在DOM中,传入WebElement对象,可以判断页面是否刷新了
staleness_of
实例代码:
WebDriver driver=new FirefoxDriver();
WebDriverWait wait=new WebDirverWait(driver,10);
WebElement we=driver.findElementByClassName("image");
wait.until(ExpectedConditions.elementToBeClickable(we)).click(); //等待可点击ClassName为图片的元素出现,出现后就实现点击操作。
10s内等待某个元素出现,出现就执行下一步操作,否则超过10s不出现就抛出异常:
wait.until(ExpectedConditions.presenceofElementLocated(By.cssSelector("css locator")));//这里的By.cssSelector可以替换成其他的定位方式如id,name等等。