无头浏览器下pykeyboard模拟输入密码时,密码错误输入回了Python原代码区域

问题遇到的现象和发生背景

我在使用selenium(4.2.0)+pykeyboard模拟键盘(不能直接传入密码,有安全控件)登陆校园网的时候,使用常规有头浏览器方法,可以正常运行,但是当我改为无头浏览器运行的时候,无法正常输入密码,输入密码时密码被写入了源代码的鼠标位置

学校校园网界面如下

img

问题相关代码,请勿粘贴截图

正常有头浏览器(可以运行)

import selenium.webdriver
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By  # 最新的selenium用法
from selenium.webdriver.chrome.service import Service
from time import sleep
from pykeyboard import PyKeyboard  # 模拟键盘
from plyer import notification  #
s = Service("chromedriver.exe")
web = Chrome(service=s)
web.get("http://172.31.85.101")
# 定义XPATH是否存在的函数、捕获异常
def exceptionexis(xpath):
    try:
        web.find_element(By.XPATH, xpath)
        return True
    except:
        return False


if exceptionexis('//*[@id="username"]'):
    web.find_element(By.XPATH, '//*[@id="username"]').send_keys('2019xxxxxx')
    # 定位到密码输入框
    sleep(1)
    web.find_element(By.XPATH, '//*[@id="pwd"]')
    # 输入密码
    k = PyKeyboard()
    k.tap_key(k.tab_key)
    k.tap_key(k.numpad_keys[2], n=2)
    k.tap_key(k.numpad_keys[3])
    k.tap_key(k.numpad_keys[x])
    k.tap_key(k.numpad_keys[x])
    k.tap_key(k.numpad_keys[x])
    # 选择需要的网络类型
    k.tap_key(k.tab_key)
    sleep(1.5)
    web.find_element(By.XPATH, '//*[@id="_service_1"]').click()
    sleep(1)
    # 鼠标定位到登录按钮
    move = web.find_element(By.XPATH, '//*[@id="loginLink_div"]')
    selenium.webdriver.ActionChains(web).move_to_element(move).perform()
    web.execute_script("$(arguments[0]).click()", move)
    web.quit()
    notification.notify(
        title="校园网连接",
        message="校园网认证成功,请开始使用",
        timeout=5
    )
else:
    web.quit()
    notification.notify(
        title="校园网连接",
        message="校园网已经认证、无需再次连接",
        timeout=5
    )

无头浏览器运行失败

import selenium.webdriver
from selenium.webdriver.common.by import By  # 最新的selenium用法
from time import sleep
from pykeyboard import PyKeyboard  # 模拟键盘
from plyer import notification  #
# 无头浏览器
from selenium.webdriver.chrome.service import Service
from selenium import webdriver
from selenium.webdriver.chrome.options import Options


s = Service("chromedriver.exe")
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument("--window-size=1920,1080")
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
web = webdriver.Chrome(options=chrome_options)
# 规避检测
web.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": """
    Object.defineProperty(navigator, 'webdriver', {
      get: () => undefined
    })
  """
})
web.get("http://172.31.85.101")


# 定义XPATH是否存在的函数、捕获异常
def exceptionexis(xpath):
    try:
        web.find_element(By.XPATH, xpath)
        return True
    except:
        return False

if exceptionexis('//*[@id="username"]'):
    web.find_element(By.XPATH, '//*[@id="username"]').send_keys('2019xxxxxx')
    # 定位到密码输入框
    sleep(1)
    web.find_element(By.XPATH, '//*[@id="pwd"]')
    # 输入密码
    k = PyKeyboard()
    k.tap_key(k.tab_key)
    k.tap_key(k.numpad_keys[2], n=2)
    k.tap_key(k.numpad_keys[3])
    k.tap_key(k.numpad_keys[x])
    k.tap_key(k.numpad_keys[x])
    k.tap_key(k.numpad_keys[x])
    # 选择需要的网络类型
    k.tap_key(k.tab_key)
    sleep(1.5)
    web.find_element(By.XPATH, '//*[@id="_service_1"]').click()
    sleep(1)
    # 鼠标定位到登录按钮
    move = web.find_element(By.XPATH, '//*[@id="loginLink_div"]')
    selenium.webdriver.ActionChains(web).move_to_element(move).perform()
    web.execute_script("$(arguments[0]).click()", move)
    web.quit()
    notification.notify(
        title="校园网连接",
        message="校园网认证成功,请开始使用",
        timeout=5
    )
else:
    web.quit()
    notification.notify(
        title="校园网连接",
        message="校园网已经认证、无需再次连接",
        timeout=5
    )
# pyinstaller -F -w login_edge_2019223684.py --hidden-import plyer.platforms.win.notification
运行结果及报错内容

无头浏览器运行时:密码输入回了原代码区域,连接失败

img

报错信息

Traceback (most recent call last):
  File "D:/software_workspace/python_workspace/稀奇古怪/校园网/login_chrome_2019223684plus.py", line 54, in <module>
    web.find_element(By.XPATH, '//*[@id="_service_1"]').click()
  File "C:\Users\21145\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 1253, in find_element
    'value': value})['value']
  File "C:\Users\21145\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 430, in execute
    self.error_handler.check_response(response)
  File "C:\Users\21145\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 247, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id="_service_1"]"}
  (Session info: headless chrome=102.0.5005.115)
Stacktrace:
Backtrace:
    Ordinal0 [0x0041D953+2414931]
    Ordinal0 [0x003AF5E1+1963489]
    Ordinal0 [0x0029C6B8+837304]
    Ordinal0 [0x002C9500+1021184]
    Ordinal0 [0x002C979B+1021851]
    Ordinal0 [0x002F6502+1205506]
    Ordinal0 [0x002E44E4+1131748]
    Ordinal0 [0x002F4812+1198098]
    Ordinal0 [0x002E42B6+1131190]
    Ordinal0 [0x002BE860+976992]
    Ordinal0 [0x002BF756+980822]
    GetHandleVerifier [0x0068CC62+2510274]
    GetHandleVerifier [0x0067F760+2455744]
    GetHandleVerifier [0x004AEABA+551962]
    GetHandleVerifier [0x004AD916+547446]
    Ordinal0 [0x003B5F3B+1990459]
    Ordinal0 [0x003BA898+2009240]
    Ordinal0 [0x003BA985+2009477]
    Ordinal0 [0x003C3AD1+2046673]
    BaseThreadInitThunk [0x776FFA29+25]
    RtlGetAppContainerNamedObjectPath [0x77DB7A7E+286]
    RtlGetAppContainerNamedObjectPath [0x77DB7A4E+238]
我的解答思路和尝试过的方法

我尝试更改过定位的方法,比如xpath全路径,也修改过代码sleep()的时间,也尝试过用tab和上下方位键定位服务,但是都失败告终,不理解为什么加了无头浏览器后,密码就输入不对了,诚挚请教各位,问题的原因,还望不吝赐教

我想要达到的结果

在无头浏览器的情况下,能够达到登录效果

建议调用 JavaScript 完成
无头模式第 44-52 行改为:

web.execute_script("document.getElementById('pwd').value='"+<密码>+"';")

包括后面的很多鼠标、键盘操作,完全可以用 JavaScript 完成,效果更好,功能更强,差错更小。