selenium显示等待怎么写之WebDriverWait中until的两种实现方式及原理分析

关于显示等待WebDriverWait是什么,可以看selenium-wait源码解析

话不多说,先上实现代码:
第一种实现方式(官方提供):

from selenium.webdriver.support.wait import WebDriverWait

element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId"))

第二种实现方式(民间高手提供):

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'kw')))

一.第一种实现方式分析:
首先介绍下需要用到的lambda表达式:

f= lambda x:x+1
print(f(1))

输出:
2

可理解为:

def f(x):
	return x+1

了解了这个之后,我们来看下until是如何执行的:

    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)

通过value = method(self._driver)这行,我们可以理解为,我们先通过lambda表达式,定义了一个匿名函数,而入口的传参,正是driver
等价于:

driver.find_element_by_id("someId")

执行后返回一个webelement对象,供我们后续操作

二.第二种实现方式分析:
这里讲两个会引入的文件,expected_conditions.py和by.py
expected_conditions:封装了一些预期结果,通常用来测试
By:支持定位的策略集

我们看下我们引入的EC文件中的presence_of_element_located类:

class presence_of_element_located(object):
    """ An expectation for checking that an element is present on the DOM
    of a page. This does not necessarily mean that the element is visible.
    locator - used to find the element
    returns the WebElement once it is located
    """
    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        return _find_element(driver, self.locator)

这俩简单介绍下两种魔法方法的特性:

__init__:初始化时自动载入
__call__:允许类的实例像函数一样被调用

我们debug一下这种方式的执行步骤可以发现:
初始化完成后,until会借助value = method(self.driver),利用我们前面所讲的魔法方法__call_,把presence_of_element_located类当作实例,传递driver对象,调用 _find_element
再看_find_element:

def _find_element(driver, by):
    """Looks up an element. Logs and re-raises ``WebDriverException``
    if thrown."""
    try:
        return driver.find_element(*by)
    except NoSuchElementException as e:
        raise e
    except WebDriverException as e:
        raise e

会继续调用driver.find_element,
看下此时_find_element的入参:
driver:method给的driver,也就是WebDriverWait初始化时,我们自己传入的
by:这里可以看到,下面find_element(*by)是*by,所以他可以接收多个参数放到一个数组中,本质是一个tuple
接着看下by入参的是什么:在最开始EC.presence_of_element_located初始化时,locator入参为:(By.ID, ‘kw’),因为是通过__call__执行的,所以现在by的入参是通过locator传入的也是(By.ID, ‘kw’)(到这里发现调用了By类,所以也需要引入此文件)
再往下运行,就到了调用driver.find_element(*by),后续就是正常执行流程了,他会进入到webdriver.py的执行逻辑中selenium-webdriver源码解析

执行后也返回一个webelement对象,供我们后续操作

写在最后:
两种执行方式比较之后,如何选择还请各位小伙伴自行判断~

  • 12
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值