为了账号安全,请及时绑定邮箱和手机立即绑定

Selenium 仅在使用无头 Chrome 时无法定位元素(Python)

Selenium 仅在使用无头 Chrome 时无法定位元素(Python)

芜湖不芜 2023-10-31 15:58:48
我刚刚开始学习 Selenium,需要使用云中的 jenkins 机器验证登录网页,该机器没有 GUI。我设法在具有 UI 的系统上成功运行该脚本。但是,当我修改脚本以无头运行时,它无法显示无法定位元素。我的脚本如下:#!/usr/bin/env python3from selenium import webdriverfrom selenium.webdriver.chrome.options import Optionsfrom selenium.webdriver.support.ui import WebDriverWaitfrom webdriver_manager.chrome import ChromeDriverManagerimport timeimport argparsechrome_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:    passdriver.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()由于我学习了大约一天的 Selenium,我可能会做一些相当愚蠢的事情,所以如果有人告诉我我做错了什么,我将非常感激。我用谷歌搜索了很多,尝试了很多东西,但都没有成功。另外,当我只使用 id 作为用户名时,为什么它说“css 选择器”?
查看完整描述

5 回答

?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

我遇到了同样的问题,它最初可以工作,但在我们使用 Selenium 的网站进行更新后,它停止在无头模式下工作,但继续在非无头模式下工作。经过 2 天的研究网络最深和最黑暗的深度以及大量的试验和错误,终于找到了问题所在。

我尝试了网上列出的所有方法以及更多方法,但在我找到这个方法之前都没有任何效果。

在无头 chrome 模式下,用户代理如下所示: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML,如 Gecko) HeadlessChrome /60.0.3112.50 Safari/537.36

服务提供商更新了他们的代码以识别 HeadlessChrome 部分,这会导致选项卡崩溃,进而破坏 Selenium 用户会话。

这导致上述问题在其中一个异常中触发。

为了解决这个问题,我使用了一个名为 fake_headers 的插件(https://github.com/diwu1989/Fake-Headers):

from fake_headers import Headers


header = Headers(

    browser="chrome",  # Generate only Chrome UA

    os="win",  # Generate only Windows platform

    headers=False # generate misc headers

)

customUserAgent = header.generate()['User-Agent']


options.add_argument(f"user-agent={customUserAgent}")

虽然这只是解决方案的一半,因为我只想要 Windows 和 Chrome 标头,并且 fake_headers 模块不包含最新的 Chrome 浏览器,并且列表中包含许多旧版本的 Chrome,如在此文件中所示 https: // github.com/diwu1989/Fake-Headers/blob/master/fake_headers/browsers.py。我运行 Selenium 的特定网站的某些功能仅适用于较新版本的 Chrome,因此当旧版本的 Chrome 通过用户代理标头传递时,该网站上的某些功能实际上会停止工作。因此,我需要更新 fake_headers 模块中的 browsers.py 文件,以仅包含我想要包含的 Chrome 版本。因此,我删除了 Chrome 的所有旧版本,并创建了一个精选版本列表(每个版本都经过单独测试以在相关网站上运行,并删除了不能运行的版本)。最终得到了以下列表,我可以对其进行扩展,但暂时还没有。

chrome_ver = [
    '90.0.4430', '84.0.4147', '85.0.4183', '85.0.4183', '87.0.4280', '86.0.4240', '88.0.4324', '89.0.4389', '92.0.4515', '91.0.4472', '93.0.4577', '93.0.4577']

希望这可以帮助人们减轻两天的压力和混乱。


查看完整回答
反对 回复 2023-10-31
?
Cats萌萌

TA贡献1805条经验 获得超9个赞

如果脚本在没有无头模式的情况下工作得很好,则窗口大小可能存在问题。除了指定 --no-sandbox 选项外,尝试更改传递给网络驱动程序的窗口大小

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

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

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

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


查看完整回答
反对 回复 2023-10-31
?
一只萌萌小番薯

TA贡献1795条经验 获得超7个赞

chrome_options.add_argument('--window-size=1920,1080') 这对我有用,谢谢



查看完整回答
反对 回复 2023-10-31
?
红颜莎娜

TA贡献1842条经验 获得超12个赞

我也遇到过类似的情况。我在网上尝试了很多解决方案,例如指定分辨率,但没有任何效果,直到这:

self.chrome_options.add_argument('user-agent="MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"')

所以看来你需要将UA添加到chrome选项中,这样selenium驱动程序就不会在无头模式下崩溃。


查看完整回答
反对 回复 2023-10-31
?
猛跑小猪

TA贡献1858条经验 获得超8个赞

我会以某种方式重构代码,直到元素出现在网页上:


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()。这里详细解释一下原因。


其他需要仔细检查的事情是元素是否具有用于搜索的 ID,以及这些元素是否位于 iframe 内。


查看完整回答
反对 回复 2023-10-31
  • 5 回答
  • 0 关注
  • 168 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信