【问题标题】:Selenium locate element fails when Chrome in background当 Chrome 在后台时,Selenium 定位元素失败
【发布时间】:2022-01-22 03:49:56
【问题描述】:

当您专注于窗口 (Chrome) 时,此程序运行良好,但当您切换到另一个窗口(如 Mozilla)或另一个应用程序继续工作时,Selenium 无法找到该元素。

无论我是否通过它打开其他应用程序、切换到其他窗口以及登录没有问题,它都应该完美地定位该元素 - 这就是我想要完成的,所以当它没有给我时我可以将它变成无头这个错误。

我也尝试使用驱动程序等待,但无济于事。

我得到的错误:

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]

代码:

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

import time

from time import sleep

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_width}x{app_height}+{int(x)}+{int(y)}')

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 = webdriver.Chrome("C:\Program Files (x86)\chromedriver.exe")

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

    loginuser = WebDriverWait(driver, 50).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="layers"]/div/div/div/div/div/div/div[2]/div[2]/div/div/div[2]/div[2]/div[1]/div/div[5]/label/div/div[2]/div/input')))
    loginuser.send_keys("Username")
    sleep(5)
    loginuser.send_keys(Keys.RETURN)

    loginuser = WebDriverWait(driver, 50).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="layers"]/div/div/div/div/div/div/div[2]/div[2]/div/div/div[2]/div[2]/div[1]/div/div[3]/div/label/div/div[2]/div[1]/input')))
    loginuser.send_keys("Password")
    sleep(5)
    loginuser.send_keys(Keys.RETURN)

    return driver

root.mainloop()

这真的很烦人,因为它有时有效,有时无效。由于切换到其他进程时发生的错误,我无法使其完全自动化。

【问题讨论】:

  • 您需要更好的定位器。
  • 我更新了我的帖子顺便说一句。你能详细说明一下吗?我是 Python 新手。
  • 请见下文。

标签: python selenium tkinter


【解决方案1】:

在跳转到 XPath 之前,您应该使用以下任一定位器。

  1. ID
  2. 姓名
  3. 类名
  4. 链接文本
  5. partialLinkText
  6. 标签名
  7. CSS 选择器
  8. xpath

另外,请确保您不应该使用absolute xpath,而应该使用relative xpath

所以,而不是这些

loginuser = WebDriverWait(driver, 50).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="layers"]/div/div/div/div/div/div/div[2]/div[2]/div/div/div[2]/div[2]/div[1]/div/div[5]/label/div/div[2]/div/input')))
loginuser.send_keys("Username")
sleep(5)
loginuser.send_keys(Keys.RETURN)

loginuser = WebDriverWait(driver, 50).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="layers"]/div/div/div/div/div/div/div[2]/div[2]/div/div/div[2]/div[2]/div[1]/div/div[3]/div/label/div/div[2]/div[1]/input')))
loginuser.send_keys("Password")
sleep(5)
loginuser.send_keys(Keys.RETURN)

使用这个:

wait = WebDriverWait(driver, 30)
loginuser  = wait.until(EC.visibility_of_element_located((By.NAME, "text")))
loginuser.send_keys("Username", Keys.RETURN)
loginPassword = wait.until(EC.visibility_of_element_located((By.NAME, "password")))
loginPassword.send_keys("password here", Keys.RETURN)

【讨论】:

  • 非常感谢。它现在似乎工作得更好,但我必须看看是否出现任何问题。我有一个与此类似的最后一个问题,但它的工作方式不同。
  • 我有这个跟随按钮的代码(点击跟随),但它也不能正常工作。我尝试像您在上面所做的那样搜索名称,但除了 xpath 之外找不到任何东西。代码:followuser = WebDriverWait(driver, 50).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="react-root"]/div/div/div[2]/main/div/ div/div/div/div/div[2]/div/div/div[1]/div/div[1]/div[2]/div[3]/div/div'))) followuser.click( )
  • 个人主页上的关注按钮,例如:twitter.com/elonmusk
  • 在这种情况下,请使用基于文本//span[text()='Follow'] 的XPath,您使用的定位器本质上应该是唯一的。 XPath 的优先级最低,但它是强大的定位器之一。
  • 我刚刚发现即使使用您的新代码并使用无头模式,错误仍然会发生。
【解决方案2】:

Selenium 需要关注两者:

当您将另一个窗口(如 Mozilla)或另一个应用程序带到前台并继续工作时,Selenium 会从 focus em>浏览器上下文。因此您会看到错误。


参考文献

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

【讨论】:

  • 哦?所以它不会在后台正常工作吗?有什么办法?
  • @Cassano 很多人会建议 Headless,但我会建议一个单独的测试平台。查看 answer 中更新的参考资料
猜你喜欢
  • 2021-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-04
相关资源
最近更新 更多