问:关于 python + selenium 中的隐式等待

Q: about implicit waits in python + selenium

我对隐式等待在 selenium 中的工作方式有疑问。据我了解,隐式等待直到元素为 located/visible/present,并具有给定的最大值。例如:

wait = WebDriverWait(driver, 
10).until(EC.presence_of_element_located((By.CLASSNAME,'classname')))

这条语句让 selenium 等待,直到找到具有 class 名称 'classname' 的元素,或者直到达到最长十秒的等待时间,对吗?

现在,我编写了一个从网站获取数据并使用隐式等待的脚本,如下所示:

def move_to_next_page():
    (this function loads the next page)

def get_page_data():
    wait = WebDriverWait(driver, 
    10).until(EC.presence_of_element_located((By.CLASS_NAME, 'class')))
    items = driver.find_elements_by_class_name('class')
    for item in items:
        itemList.append(item.text)
    return itemList

move_to_next_page()
get_page_data()

昨天,我运行这个脚本多次成功;隐式等待使我的程序暂停了最多五秒钟,以确保一切正常。但是,我现在正在尝试 运行 脚本,大约 70% 的时间我收到一条错误消息:

selenium.common.exceptions.StaleElementReferenceException: Message: 
stale element reference: element is not attached to the page document 

暗示浏览器仍在加载?奇怪的是我在达到 10 秒的限制之前就收到了这条消息。我什至尝试了 20 秒和 30 秒,但 selenium 仍然崩溃了很多次。为什么硒不会等待至少 10/20/30 秒?

我很确定隐式等待会导致崩溃,因为当我使用显式等待时,例如:

time.sleep(4)

程序每次运行s。

我有要找的数据,所以我真的不再需要这个脚本了。只是不能写出不管浏览器加载时间如何都能正常工作的东西真的很令人沮丧。

首先,WebDriverWaitExpectedConditions是显式等待,不是隐式等待。您可以详细了解差异 here,但长话短说 explicit wait 正在等待满足特定条件,而 implicit wait 正在等待元素存在于 DOM .

至于异常,StaleElementReferenceException 并不意味着页面未加载,它意味着 DOM 在您定位元素和尝试加载元素之间发生了更改或重新加载用它做点什么。可以在报错信息中看到

stale element reference: element is not attached to the page document

您可以尝试 presence_of_all_elements_located

items = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'class')))
for item in items:
    itemList.append(item.text)

WebDriverWait.until 将 return ExpectedConditions 正在检查的元素。

我写了一个通用的方法来解决selenium中的等待问题,我已经测试过了,效果很好。

timeout = 是您要设置的总超时时间

value = 是标识符

key = 发送键值。想点击就留空

输入="C"=点击"S"=发送键

def wait_and_send( timeout,value,key,byWhat="By.ID",input=""):

       try:
            el = WebDriverWait(browser,time).until(
            EC.presence_of_element_located((eval(byWhat),value))
            )
            if input == "C":
                el.click()
            if input == "S":
                el.send_keys(key)
        except:
            print EC.NoSuchElementException

例如。 wait_and_send(10,"identifier","abc@test.com","By.NAME","S")