Selenium 超时异常未按预期工作

Posted

技术标签:

【中文标题】Selenium 超时异常未按预期工作【英文标题】:Selenium Timeout Exception not working as intended 【发布时间】:2022-01-23 03:55:16 【问题描述】:

我是 Python 新手,所以不确定这里出了什么问题。据我了解,当窗口没有聚焦时,Selenium 有时无法定位元素(因此我切换到无头)。所以我正在努力解决这个问题,让它 100% 的时间都有效。

这是错误的样子:

selenium.common.exceptions.TimeoutException: Message: 
Stacktrace:
Backtrace:
        Ordinal0 [0x00986903+2517251]
        Ordinal0 [0x0091F8E1+2095329]
        Ordinal0 [0x00822848+1058888]
        Ordinal0 [0x0084D448+1233992]
        Ordinal0 [0x0084D63B+1234491]
        Ordinal0 [0x00877812+1406994]
        Ordinal0 [0x0086650A+1336586]
        Ordinal0 [0x00875BBF+1399743]
        Ordinal0 [0x0086639B+1336219]
        Ordinal0 [0x008427A7+1189799]
        Ordinal0 [0x00843609+1193481]
        GetHandleVerifier [0x00B15904+1577972]
        GetHandleVerifier [0x00BC0B97+2279047]
        GetHandleVerifier [0x00A16D09+534521]
        GetHandleVerifier [0x00A15DB9+530601]
        Ordinal0 [0x00924FF9+2117625]
        Ordinal0 [0x009298A8+2136232]
        Ordinal0 [0x009299E2+2136546]
        Ordinal0 [0x00933541+2176321]
        BaseThreadInitThunk [0x770EFA29+25]
        RtlGetAppContainerNamedObjectPath [0x77B47A9E+286]
        RtlGetAppContainerNamedObjectPath [0x77B47A6E+238]

所以我试图找到一个解决方案,即重新运行/再次尝试,但是,它真的很乱:

2021-12-22 04:50:20.920372 Signed in
Password input crashed. Retrying now...
2021-12-22 04:50:31.234082 Loaded profile page
Username input crashed. Retrying now...
2021-12-22 04:52:12.192628 Signed in
Password input crashed. Retrying now...
2021-12-22 04:52:22.473065 Loaded profile page
2021-12-22 04:52:23.174232 Signed in
Password input crashed. Retrying now...
2021-12-22 04:52:33.452513 Loaded profile page

代码如下:

import tkinter as tk

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

from selenium.webdriver.chrome.options import Options

from selenium.webdriver.chrome.service import Service

from selenium.common.exceptions import TimeoutException

import threading

import time

from time import sleep

import datetime

options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("start-maximized")

root = tk.Tk()

app_width = 300
app_height = 320

screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()

x = (screen_width / 2) - (app_width / 2)
y = (screen_height / 2) - (app_height / 2)

root.geometry(f'app_widthxapp_height+int(x)+int(y)')

#
ser = Service("C:\Program Files (x86)\chromedriver.exe")
driver = webdriver.Chrome(service=ser, options=options)
wait = WebDriverWait(driver, 50)

testbtn_txt = tk.StringVar()
testbtn = tk.Button(root, textvariable=testbtn_txt, command=lambda:open_browser_func(), font="Arial", bg="#808080", fg="white", height=1, width=10)
testbtn_txt.set("Test")
testbtn.grid(row=10, column=0, columnspan=2, pady=5, padx=5)


def open_browser_func():
    global driver

    driver.get("https://twitter.com/i/flow/login")
    sleep(5)

    try:
        loginuser  = wait.until(EC.visibility_of_element_located((By.NAME, "text")))
        loginuser.send_keys("Username", Keys.RETURN)
    except TimeoutException:
        def retry_sign_in():
            print("Username input crashed. Retrying now...")
            driver.quit
            return open_browser_func()
        retrytimer = threading.Timer(5, retry_sign_in)
        retrytimer.start()

    try:
        loginPassword = wait.until(EC.visibility_of_element_located((By.NAME, "password")))
        loginPassword.send_keys("Password", Keys.RETURN)
    except TimeoutException:
        def retry_sign_in2():
            print("Password input crashed. Retrying now...")
            driver.quit
            return open_browser_func()
        retrytimer2 = threading.Timer(5, retry_sign_in2)
        retrytimer2.start()

    ct = datetime.datetime.now()
    print(ct, "Signed in")

    def logged_in_shot():
        driver.get_screenshot_as_file("logged_in_shot.png")
        driver.get("https://twitter.com/Username")
        
        ct2 = datetime.datetime.now()
        print(ct2, "Loaded profile page")

    logged_in_timer = threading.Timer(10, logged_in_shot)
    logged_in_timer.start()
    
    return driver

root.mainloop()

【问题讨论】:

所以你仍然拒绝Selenium's focus 您是否在比 Twitter 登录更无害的设置中解决了此方法?也许只是在 google.com 搜索栏上搜索?我发现使用 Selenium 时,一些高配置的登录页面可能会很困难。 没有。我只是希望它在失败时重新聚焦。 @Jack,这是 Selenium 的一个重点问题。被打断时会失去焦点。 【参考方案1】:

使用此处的异常处理,您可能希望限制尝试的次数,或者不按您的方式调用原始函数。

try:
    loginuser  = wait.until(EC.visibility_of_element_located((By.NAME, "text")))
    loginuser.send_keys("Username", Keys.RETURN)
except TimeoutException:
    def retry_sign_in():
        print("Username input crashed. Retrying now...")
        driver.quit
        return open_browser_func()
    retrytimer = threading.Timer(5, retry_sign_in)
    retrytimer.start()

您在这里重试,这很好,但是如果您每次都返回 open_browser_func(),如果它继续失败,它将继续运行该函数。如果您通过限制(IE,3 次)并强制执行,您可能会解决此问题。

对于这里的原始问题,我使用了两种解决方案来帮助解决尚未在 Selenium 中加载的元素-

    使用睡眠或等待功能,虽然有效,但可能很草率。 创建一个函数以等待元素出现在视图中。这往往效果最好。

【讨论】:

重点是,我希望它重新聚焦和/或重新启动功能,以便一切顺利。

以上是关于Selenium 超时异常未按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

WebDriverWait 未按预期工作

WebDriver 隐式等待未按预期工作

C# 中的异常未按预期运行

Selenium WebDriver 偶尔抛出超时异常

Angular ngOnit () 未按预期工作

$() 函数未按预期工作