硒仅在使用无头镀铬时无法定位元素(Python)

时间:2020-10-12 04:32:10

标签: python selenium google-chrome-headless

我刚开始学习Selenium,需要使用没有GUI的云中的jenkins机器来验证登录网页。我设法在具有UI的系统上成功运行脚本。但是,当我将脚本修改为无头运行时,它无法显示无法找到元素。 我的脚本如下:

#!/usr/bin/env python3

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from webdriver_manager.chrome import ChromeDriverManager
import time
import argparse


chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--window-size=1120, 550')
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--allow-running-insecure-content')

driver = webdriver.Chrome(ChromeDriverManager().install(), chrome_options=chrome_options)
driver.implicitly_wait(5)

lhip = '13.14.15.16'
user = 'username'
paswd = 'password'


parser = argparse.ArgumentParser()

parser.add_argument('-i', '--lh_ip',    type=str, metavar='', default=lhip,     help='Public IP of VM' )
parser.add_argument('-u', '--usr',      type=str, metavar='', default=user,     help='Username for VM')
parser.add_argument('-p', '--pwd',      type=str, metavar='', default=paswd,    help='Password for VM')

args = parser.parse_args()


lh_url = 'https://' + args.lh_ip + '/login/'
driver.get(lh_url)
try:
    if driver.title == 'Privacy error':
        driver.find_element_by_id('details-button').click()
        driver.find_element_by_id('proceed-link').click()
except:
    pass

driver.find_element_by_id('username').send_keys(args.usr)
driver.find_element_by_id('password').send_keys(args.pwd)
driver.find_element_by_id('login-btn').click()
driver.implicitly_wait(10)
try:
    if driver.find_element_by_tag_name('span'):
        print('Login Failed')
except:
    print('Login Successful')
driver.close()

在不使用chrome_options的情况下,python脚本在我的系统上可以正常工作。但是,将它们添加到以无头模式运行时,它将失败,并显示以下输出:

[WDM] - Current google-chrome version is 85.0.4183
[WDM] - Get LATEST driver version for 85.0.4183
[WDM] - Driver [/home/ramesh/.wdm/drivers/chromedriver/linux64/85.0.4183.87/chromedriver] found in cache
Traceback (most recent call last):
  File "/home/ramesh/practice_python/test_headless.py", line 44, in <module>
    driver.find_element_by_id('username').send_keys(args.usr)
  File "/home/ramesh/.local/lib/python3.6/site-packages/selenium/webdriver/remote/webdriver.py", line 360, in find_element_by_id
    return self.find_element(by=By.ID, value=id_)
  File "/home/ramesh/.local/lib/python3.6/site-packages/selenium/webdriver/remote/webdriver.py", line 978, in find_element
    'value': value})['value']
  File "/home/ramesh/.local/lib/python3.6/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "/home/ramesh/.local/lib/python3.6/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="username"]"}
  (Session info: headless chrome=85.0.4183.121)

由于我大约有一天要学习硒,所以我做的事情可能很愚蠢,所以如果有人向我展示我做错了事,将不胜感激。我已经在Google上搜索了很多,尝试了很多东西,但是都没有用。 当我仅使用ID作为用户名时,为什么还说“ css选择器”?

2 个答案:

答案 0 :(得分:2)

如果脚本在没有无头模式的情况下运行良好,则可能是窗口大小有问题。在指定 --no-sandbox 选项的同时,尝试更改传递给 webdriver 的窗口大小

chrome_options.add_argument('--window-size=1920,1080')

这个窗口大小适用于我的情况。

即使这不起作用,您也可能需要添加之前回答的等待计时器,因为与 UI 模式下的浏览器相比,无头模式下的渲染工作方式不同。

无头模式渲染参考 - https://www.toolsqa.com/selenium-webdriver/selenium-headless-browser-testing/

答案 1 :(得分:0)

我将以某种方式重构代码,以等待元素出现在网页上:

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

WebDriverWait(wd, 10).until(EC.presence_of_element_located((By.ID, 'username'))).send_keys(args.usr)
WebDriverWait(wd, 10).until(EC.presence_of_element_located((By.ID,'password'))).send_keys(args.pwd)
WebDriverWait(wd, 10).until(EC.presence_of_element_located((By.ID, 'login-btn'))).click()

通常最好将WebDriverWait与某些条件结合使用,而不是隐式等待或time.sleep()Here详细说明了原因。

要再次检查的另一件事是,元素是否具有用于搜索的ID,以及这些元素是否不在iframe中。