Selenium3+python3自动化(二十七)--webdriver中等待,显式等待(WebDriverWait),强制等待sleep(),隐式等待implicitly_wait()...

前言

在脚本中加入太多的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 \n
            element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) \n
            is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).\ \n
                        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 
    WebDriverWait(driver, 10, 0.5).until_not(lambda driver: driver.find_element_by_id("kw")).send_keys("hehe")
  File "D:\Program Files\python37\lib\site-packages\selenium\webdriver\support\wait.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无法加载,但是想找的元素已经出来了,它还是会继续等待,知道页面加载完成(浏览器标签左上角圈圈不再转),才会执行下一句。某些情况下会影响脚本执行速度。

你可能感兴趣的:(自动化,python,运维,开发语言)