前言
在脚本中加入太多的sleep后会影响脚本的执行速度,虽然implicitly_wait()这种方式隐式等待方法一定程度上节省了很多时间。
但是一旦页面上某些js无法加载出来(其实界面元素已经出来了),左上角那个图标一直转圈,这时候会一直等待的。
一、WebDriverWait参数解释
1.WebDriverWait有4个参数:
WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)
需要通过 from selenium.webdriver.support.wait import WebDriverWait 导入模块
- driver:返回浏览器的一个实例,浏览器驱动
- timeout:超时的总时长,默认以秒为单位
- poll_frequency:循环去查询的间隙时间,默认0.5秒
- ignored_exceptions:超时后的抛出的异常信息,默认抛出NoSuchElementException异常
以下是源码的解释文档
class WebDriverWait(object): def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None): """Constructor, takes a WebDriver instance and timeout in seconds. :Args: - driver - Instance of WebDriver (Ie, Firefox, Chrome or Remote) - timeout - Number of seconds before timing out - poll_frequency - sleep interval between calls By default, it is 0.5 second. - ignored_exceptions - iterable structure of exception classes ignored during calls. By default, it contains NoSuchElementException only. Example: from selenium.webdriver.support.ui import WebDriverWait element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)). until_not(lambda x: x.find_element_by_id("someId").is_displayed()) """ self._driver = driver self._timeout = timeout self._poll = poll_frequency # avoid the divide by zero if self._poll == 0: self._poll = POLL_FREQUENCY exceptions = list(IGNORED_EXCEPTIONS) if ignored_exceptions is not None: try: exceptions.extend(iter(ignored_exceptions)) except TypeError: # ignored_exceptions is not iterable exceptions.append(ignored_exceptions) self._ignored_exceptions = tuple(exceptions) def __repr__(self): return '<{0.__module__}.{0.__name__} (session="{1}")>'.format( type(self), self._driver.session_id) def until(self, method, message=''): """Calls the method provided with the driver as an argument until the return value is not False.""" screen = None stacktrace = None end_time = time.time() + self._timeout while True: try: value = method(self._driver) if value: return value except self._ignored_exceptions as exc: screen = getattr(exc, 'screen', None) stacktrace = getattr(exc, 'stacktrace', None) time.sleep(self._poll) if time.time() > end_time: break raise TimeoutException(message, screen, stacktrace) def until_not(self, method, message=''): """Calls the method provided with the driver as an argument until the return value is False.""" end_time = time.time() + self._timeout while True: try: value = method(self._driver) if not value: return value except self._ignored_exceptions: return True time.sleep(self._poll) if time.time() > end_time: break raise TimeoutException(message)
与until()或者until_not()方法结合使用
WebDriverWait(driver,10).until(method,message="") #调用该方法提供的驱动程序作为参数,直到返回值为True WebDriverWait(driver,10).until_not(method,message="") #调用该方法提供的驱动程序作为参数,直到返回值为False
在设置时间(10s)内,等待后面的条件发生。如果超过设置时间未发生,则抛出异常。
在等待期间,每隔一定时间(默认0.5秒),调用until或until_not里的方法,直到它返回True或False。
WebDriverWait与expected_conditions结合使用
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By wait = WebDriverWait(driver,10,0.5) element =waite.until(EC.presence_of_element_located((By.ID,"kw"),message="")) # 此处注意,如果省略message=“”,则By.ID外面是两层()
如下实例,使用了匿名函数lambda、expected_condtions的presence_of_element_located方法(判断某个元素是否被加到了 dom 树里,并不代表该元素一定可见)
# coding:utf-8 from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.get("https://www.baidu.com") WebDriverWait(driver, 10, 0.5).until(EC.presence_of_element_located((By.ID, "kw"))).send_keys("xixi") WebDriverWait(driver,3).until(EC.presence_of_element_located(("id","kw"))).send_keys("_on_") WebDriverWait(driver,5).until(lambda x: x.find_element("id","kw")).send_keys("_good_") WebDriverWait(driver, 10, 0.5).until_not(lambda driver: driver.find_element_by_id("kw")).send_keys("hehe") # a=lambda x:x+22 # print(a(5))
运行结果:
Traceback (most recent call last): File "E:/study/selenium_study/a825.py", line 12, in <module> WebDriverWait(driver, 10, 0.5).until_not(lambda driver: driver.find_element_by_id("kw")).send_keys("hehe") File "D:Program Filespython37libsite-packagesseleniumwebdriversupportwait.py", line 96, in until_not raise TimeoutException(message) selenium.common.exceptions.TimeoutException: Message:
二、强制等待:sleep()
import time sleep(5) #等待5秒
设置固定休眠时间,单位为秒。由python的time包提供,导入time包后就可以使用。
缺点:不智能,使用太多的sleep会影响脚本运行速度。
三、隐式等待:implicitly_wait()
driver.implicitly_wait(10) #隐式等待10秒
由webdriver提供的方法,一旦设置,这个隐式等待会在WebDriver对象实例的整个生命周期起作用,它不针对某一个元素,是全局元素等待,即在定位元素时,需要等待页面全部元素加载完成,才会执行下一个语句。如果超出 了设置时间的则抛出异常。
缺点:当页面某些js无法加载,但是想找的元素已经出来了,它还是会继续等待,知道页面加载完成(浏览器标签左上角圈圈不再转),才会执行下一句。某些情况下会影响脚本执行速度。