💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] ## **4.7 设置元素等待** WebDriver 提供了两种类型的元素等待:显式等待和隐式等待。 ### **4.7.1 显式等待** 显式等待是 WebDriver 等待某个条件成立则继续执行,否则在达到最大时长时抛出超时异常(TimeoutException)。 ``` from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Chrome() driver.get("http://www.baidu.com") element = WebDriverWait(driver, 5, 0.5).until( EC.visibility_of_element_located((By.ID, "kw")) ) element.send_keys('selenium') driver.quit() ``` WebDriverWait 类是 WebDriver 提供的等待方法。在设置时间内,默认每隔一段时间检测一次当前页面元素是否存在,如果超过设置时间仍检测不到,则抛出异常。具体格式如下。 ``` WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None) ``` * driver:浏览器驱动。 * timeout:最长超时时间,默认以秒为单位。 * poll_frequency:检测的间隔(步长)时间,默认为 0.5s * ignored_exceptions:超时后的异常信息,默认情况下抛出 NoSuchElementException异常。 WebDriverWait()一般与 until()或 until_not()方法配合使用,下面是 until()和 until_not()方法的说明。 ``` until(method, message=″) ``` 调用该方法提供的驱动程序作为一个参数,直到返回值为 True。 ``` until_not(method, message=″) ``` 调用该方法提供的驱动程序作为一个参数,直到返回值为 False。 在本例中,通过 as 关键字将 expected_conditions 重命名为 EC,并调用 presence_of_element_located()方法判断元素是否存在。 expected_conditions 类提供的预期条件判断方法如表 4-2 所示。 ![](https://img.kancloud.cn/b7/b7/b7b70107bdfc9cfc0f4a9f2e1a61eb55_794x629.png) 除 expected_conditions 类提供的丰富的预期条件判断方法外,还可以利用前面学过的is_displayed()方法自己实现元素显示等待。 ``` from time import sleep, ctime from selenium import webdriver driver = webdriver.Chrome() driver.get("http://www.baidu.com") print(ctime()) for i in range(10): try: el = driver.find_element_by_id("kw22") if el.is_displayed(): break except: pass sleep(1) else: print("time out") print(ctime()) driver.quit() ``` 相对来说,这种方式更容易理解。首先 for 循环 10 次,然后通过 is_displayed()方法循环判断元素是否可见。如果为 True,则说明元素可见,执行 break 跳出循环;否则执行 sleep()休眠 1s 后继续循环判断。10 次循环结束后,如果没有执行 break,则执行 for 循环对应的else 语句,打印“time out”信息。 这里故意将 id 定位设置为“kw22”,定位失败,执行结果如下。 ``` Mon Sep 27 15:19:31 2021 time out Mon Sep 27 15:19:42 2021 ``` <br /> ### **4.7.2 隐式等待** WebDriver 提供的 implicitly_wait()方法可用来实现隐式等待,用法相对来说要简单得多。 ``` from time import ctime from selenium import webdriver from selenium.common.exceptions import NoSuchElementException driver = webdriver.Chrome() # 设置隐式等待为 10s driver.implicitly_wait(10) driver.get("http://www.baidu.com") try: print(ctime()) driver.find_element_by_id("kw22").send_keys('selenium') except NoSuchElementException as e: print(e) finally: print(ctime()) driver.quit() ``` implicitly_wait()的参数是时间,单位为秒,本例中设置的等待时间为 10s。首先,这10s 并非一个固定的等待时间,它并不影响脚本的执行速度。其次,它会等待页面上的所有元素。当脚本执行到某个元素定位时,如果元素存在,则继续执行;如果定位不到元素,则它将以轮询的方式不断地判断元素是否存在。假设在第 6s 定位到了元素,则继续执行,若直到超出设置时间(10s)还没有定位到元素,则抛出异常。 这里同样故意将 id 定位设置为“kw22”,定位失败,执行结果如下。 ``` Mon Sep 27 16:08:03 2021 Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="kw22"]"} (Session info: chrome=93.0.4577.82) Mon Sep 27 16:08:13 2021 ```