【问题标题】:Pycharm: Selenium with Python: Unable to find web elements using headless chromePycharm:使用 Python 的 Selenium:无法使用无头 chrome 找到 Web 元素
【发布时间】:2019-10-26 12:58:34
【问题描述】:

当我使用 headless chrome 运行以下代码时,我在识别元素时遇到了问题。通过使用 head full 模式注释以下行,相同的代码运行良好。

# chrome_options.add_argument('--headless')

# chrome_options.add_argument('--disable-gpu')

测试详情:

操作系统: Windows10

ChromeDriver: 75.0.3770.8

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
driver = webdriver.Chrome(ChromeDriverManager().install(), options=chrome_options)
wait = WebDriverWait(driver,30)
driver.maximize_window()
driver.get('https://learn.letskodeit.com/')
print(driver.title)
wait.until(EC.element_to_be_clickable((By.LINK_TEXT, 'Login'))).click()
wait.until(EC.visibility_of_element_located((By.ID, 'user_email'))).send_keys("test@email.com")
wait.until(EC.visibility_of_element_located((By.ID, 'user_password'))).send_keys("abcabc")
wait.until(EC.visibility_of_element_located((By.NAME, 'commit'))).click()
print(driver.title)
driver.close()
driver.quit()

输出:

"C:\Program Files (x86)\Python37-32\python.exe" C:/PycharmProjects/seleniumwd2/basics/RunHeadlessChromeTests.py

Checking for win32 chromedriver:75.0.3770.8 in cache
Driver found in C:\Users\vishr\.wdm\chromedriver\75.0.3770.8\win32/chromedriver.exe
Home | Let's Kode It
Traceback (most recent call last):
  File "C:/PycharmProjects/seleniumwd2/basics/RunHeadlessChromeTests.py", line 15, in <module>
    wait.until(EC.element_to_be_clickable((By.LINK_TEXT, 'Login'))).click()
  File "C:\Users\vishr\AppData\Roaming\Python\Python37\site-packages\selenium\webdriver\support\wait.py", line 80, in until
    raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message: 


Process finished with exit code 1

【问题讨论】:

  • 您的堆栈跟踪表明在定位 id 属性为 user_email 的元素时出现问题。被测页面上有这样的元素吗?

标签: python selenium xpath css-selectors webdriverwait


【解决方案1】:

对于无头浏览器,您必须设置窗口大小以触发事件。因为无头浏览器无法识别没有窗口大小的点击位置。

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

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('window-size=1920x1080')

driver = webdriver.Chrome(executable_path='path/to/chrome driver',options=chrome_options)
wait = WebDriverWait(driver,30)
driver.maximize_window()
driver.get('https://learn.letskodeit.com/')
print(driver.title)
wait.until(EC.element_to_be_clickable((By.LINK_TEXT, 'Login'))).click()
wait.until(EC.visibility_of_element_located((By.ID, 'user_email'))).send_keys("test@email.com")
wait.until(EC.visibility_of_element_located((By.ID, 'user_password'))).send_keys("abcabc")
wait.until(EC.visibility_of_element_located((By.NAME, 'commit'))).click()
print(driver.title)
driver.close()
driver.quit()

在无头模式下在控制台上打印输出。

Home | Let's Kode It
Let's Kode It

【讨论】:

    【解决方案2】:

    VISHVAMBRUTHJAVAGALTHIMMEGOWDA,

    我尝试了您的代码并遇到了同样的异常,首先我认为 usernameFrameiframe 中,但事实并非如此。

    然后我尝试引入 webdriver wait 并且效果很好:

    代码:

    wait = WebDriverWait(driver,10)
    
    driver.maximize_window()
    
    driver.get("https://learn.letskodeit.com/")
    
    print(driver.title)
    
    driver.find_element_by_xpath("//a[contains(text(),'Login')]").click()
    
    wait.until(EC.visibility_of_element_located((By.ID, 'user_email'))).send_keys("test@email.com")
    
    #driver.find_element_by_id("user_email").
    
    driver.find_element_by_id("user_password").send_keys("abcabc")
    
    driver.find_element_by_name("commit").click()
    
    print(driver.title)  
    

    记得导入这些:

    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC 
    

    编辑 1:

    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    import time
    
    options = Options()
    options.add_argument('--headless')
    options.add_argument('--disable-gpu')  # Last I checked this was necessary.
    driver = webdriver.Chrome("C:/Users/XXXX/Downloads/BrowserDriver/chromedriver_win32/chromedriver.exe", chrome_options=options)
    wait = WebDriverWait(driver,10)
    
    driver.get("https://learn.letskodeit.com/")
    
    print(driver.title)
    
    
    wait.until(EC.element_to_be_clickable((By.LINK_TEXT, 'Login'))).click()
    
    wait.until(EC.visibility_of_element_located((By.ID, 'user_email'))).send_keys("test@email.com")
    
    wait.until(EC.visibility_of_element_located((By.ID, 'user_password'))).send_keys("abcabc")
    
    wait.until(EC.visibility_of_element_located((By.NAME, 'commit'))).click()
    
    print(driver.title)
    

    【讨论】:

    • 我按照您的建议更改了代码。但它适用于全头浏览器,但不适用于无头浏览器。请让我知道如何使代码与无头 chrome 一起使用。
    • 使用无头浏览器,您可以编写带有等待的相同代码。让我给你代码。
    • 在edit1部分更新,请检查。我还没有测试过。
    • 尝试了 edit1 部分下的代码,但仍然无法使用 headless chrome 运行它。该代码在头部完整模式下工作正常。请帮忙。
    【解决方案3】:

    要在文本为 Login 的元素上 click(),您必须为 element_to_be_clickable() 诱导 WebDriverWait,您可以使用以下任一解决方案:

    • 使用PARTIAL_LINK_TEXT

      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, "Login"))).click()
      
    • 使用CSS_SELECTOR

      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a.navbar-link.fedora-navbar-link[href='/sign_in']"))).click()
      
    • 使用XPATH

      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[@class='navbar-link fedora-navbar-link' and @href='/sign_in']"))).click()
      
    • 注意:您必须添加以下导入:

      from selenium.webdriver.support.ui import WebDriverWait
      from selenium.webdriver.common.by import By
      from selenium.webdriver.support import expected_conditions as EC
      

    【讨论】:

    • 你能看看我的代码并帮助我通过 headless chrome 运行它吗?
    • 您的代码绝对没有问题。您只需将 EC visibility_of_element_located() & ID 替换为 element_to_be_clickable & Xpath / Css跨度>
    • 更改为仍然没有运气。 wait.until(EC.element_to_be_clickable((By.LINK_TEXT, 'Login'))).click() wait.until(EC.element_to_be_clickable((By.ID, 'user_email')))).send_keys("test@email. com") wait.until(EC.element_to_be_clickable((By.ID, 'user_password'))).send_keys("abcabc") wait.until(EC.element_to_be_clickable((By.NAME, 'commit'))).click ()
    • 你从哪里得到LINK_TEXT?在我的回答中是PARTIAL_LINK_TEXT
    • 更改为 PARTIAL_LINK_TEXT 也有用:wait.until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, 'Login'))).click()
    【解决方案4】:

    您正在单击一个加载另一个页面的按钮。 您必须等待其他页面加载。这很难做到完美。

    最简单的解决方案:

    sleep(3)
    

    使用隐式等待的更好解决方案:

    driver.implicitly_wait(3)
    

    使用显式等待的更好解决方案:

    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.ID, "user_email")))
    

    更好的解决方案是捕获异常,并将所有这些解决方案分层。

    【讨论】:

      猜你喜欢
      • 2020-08-28
      • 2022-09-30
      • 2020-12-16
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-13
      • 2016-08-31
      • 1970-01-01
      相关资源
      最近更新 更多