Selenium 有时会使用 presence_of_element_located() 抛出 TimeoutException

Selenium sometimes throws TimeoutException with presence_of_element_located()

我在 Python 3.6 中使用 Selenium,它工作正常,但并非总是如此。 我有这个代码:

 try:

    table = wait.until(
        EC.presence_of_element_located((
            By.XPATH,
            "/html/body/div/div[2]/div[1]/table/tbody/"
            "tr[2]/td/table/tbody/tr/td/div/table[2]"
        ))
    )
except TimeoutException:
    driver.quit()
    return {
        "statusCode": 500,
        "body": json.dumps({"error": "WebPage dont load"}),
        "headers": {
            "Content-Type": "application/json"
        }
    }

这行得通,但有时会出现超时异常,我需要 100% 的时间都在工作。我已经尝试使用 time.sleep(5)presence_of_all_elements_locatedvisibility_of_element_located 函数来等待网页加载,但问题没有解决。

我还有:

driver.implicitly_wait(20)

wait = WebDriverWait(driver, 30)

使等待隐式和显式。

确保问题不是错误,也许元素并不总是出现在页面上。如果是错误,请与开发人员讨论。

如果不是错误,请使用相对 XPath 而不是绝对 XPath,因为绝对 XPath 非常脆弱。或者更好的是,使用唯一 ID 或 class。 您可以找到有关 XPath here.

的更多信息

presence_of_element_located()

presence_of_element_located() 是检查元素是否存在于页面的 DOM 上的期望值。这并不一定意味着该元素是可见的。因此它可能无法满足您的需求。


visibility_of_element_located()

visibility_of_element_located() 是检查元素是否存在于页面的 DOM 并且可见的期望值。可见性是指该元素不仅被显示而且高度和宽度都大于0。


这个用例

所以理想情况下,您需要将 presence_of_element_located() 替换为 visibility_of_element_located(),您的有效代码块将是:

try:

   table = wait.until(
       EC.visibility_of_element_located((
           By.XPATH,
           "/html/body/div/div[2]/div[1]/table/tbody/"
           "tr[2]/td/table/tbody/tr/td/div/table[2]"
       ))
   )

额外考虑

与其使用 absolute xpath,不如使用 relative xpath。


参考文献

您可以在以下位置找到一些相关的详细讨论:

  • Selenium - wait until element is present, visible and interactable)