【问题标题】:cant enter credentials using selenium无法使用硒输入凭据
【发布时间】:2019-10-08 09:03:39
【问题描述】:

我正在尝试使用selenium 登录网站:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://www.eco-visio.net/v5/")
username = driver.find_element_by_id("login-username")
username.send_keys("midregcog.admin")

但我收到以下错误

ElementNotInteractableException           Traceback (most recent call last)
<ipython-input-9-975030640535> in <module>()
      8 driver.get("https://www.eco-visio.net/v5/")
      9 username = driver.find_element_by_id("login-username")
---> 10 username.send_keys("midregcog.admin")
     11 

C:\Anaconda2\lib\site-packages\selenium\webdriver\remote\webelement.pyc in send_keys(self, *value)
    477         self._execute(Command.SEND_KEYS_TO_ELEMENT,
    478                       {'text': "".join(keys_to_typing(value)),
--> 479                        'value': keys_to_typing(value)})
    480 
    481     # RenderedWebElement Items

C:\Anaconda2\lib\site-packages\selenium\webdriver\remote\webelement.pyc in _execute(self, command, params)
    631             params = {}
    632         params['id'] = self._id
--> 633         return self._parent.execute(command, params)
    634 
    635     def find_element(self, by=By.ID, value=None):

C:\Anaconda2\lib\site-packages\selenium\webdriver\remote\webdriver.pyc in execute(self, driver_command, params)
    319         response = self.command_executor.execute(driver_command, params)
    320         if response:
--> 321             self.error_handler.check_response(response)
    322             response['value'] = self._unwrap_value(
    323                 response.get('value', None))

C:\Anaconda2\lib\site-packages\selenium\webdriver\remote\errorhandler.pyc in check_response(self, response)
    240                 alert_text = value['alert'].get('text')
    241             raise exception_class(message, screen, stacktrace, alert_text)
--> 242         raise exception_class(message, screen, stacktrace)
    243 
    244     def _value_or_default(self, obj, key, default):

ElementNotInteractableException: Message: element not interactable
  (Session info: chrome=74.0.3729.131)
  (Driver info: chromedriver=74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29}),platform=Windows NT 10.0.17134 x86_64)

这是我试图获取的网站的 id 标签。

【问题讨论】:

    标签: python selenium


    【解决方案1】:

    正如here 解释的那样,您需要使用 javascript 人为地单击该元素,因为它是由 javascript 本身制作的(selenium 无法“看到”该元素)。另一个类似情况的例子是my answer on this question。像这样调整你的代码是可行的(我也实现了等待,但这可能不是必需的):

    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
    from selenium.webdriver.common import action_chains
    import time
    
    driver = webdriver.Chrome()
    driver.get("https://www.eco-visio.net/v5/")
    username_element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//form/div/input[@id='login-username']")))# driver.find_element_by_id("login-username")
    
    driver.execute_script("arguments[0].click();", username_element)
    time.sleep(1) # give the click a moment to register
    action = action_chains.ActionChains(driver)
    action.send_keys("midregcog.admin")
    action.perform()
    

    这可以填写我机器上的字段!希望这会有所帮助。

    更新

    @MarcelWilson 指出您只需要等待页面加载(不完全确定为什么,因为它是,并且通过几个测试我不确定为什么它不能仅通过显式等待来工作。显然第一个答案过于复杂,您可以通过以下方式达到预期的效果:

    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
    import time
    
    driver = webdriver.Chrome()
    driver.get("https://www.eco-visio.net/v5/")
    username_element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//form/div/input[@id='login-username']")))# driver.find_element_by_id("login-username")
    time.sleep(2) # give a longer wait than the explicit wait in the previous line
    username_element.click()
    username_element.send_keys("username")
    password_element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//form/div/input[@id='login-password'][@type='password']")))# driver.find_element_by_id("login-username")
    password_element.click()
    password_element.send_keys("password")
    

    我认为这可能是因为在生成页面的 javascript 中(而且我不是 javascript 专家)有诸如 if: loaded() 这样的行,这让我相信明确的 WebDriverWait 正在获取元素,但是javascript仍在加载它的过程中。所以WebDriverWait确保元素存在,time.sleep(2)确保它在尝试与之交互之前也被加载,此时看起来你可以交互将其作为正常页面没有问题。我什至要为这篇文章学习一些新东西 XD!

    【讨论】:

    • 你不需要使用javascript来点击元素。您只需要等待元素可见。
    • 我在做driver.execute_script("arguments[0].click(); arguments[1].click();", username_element, password_element) 然后action.send_keys("midregcog.admin", "passherer") 但两个输入都写在同一个盒子里。如何指定密码输入的密码?
    • 当网络中断或服务器滞后时,使用 time.sleep 的问题很明显。睡眠时间不够。增加更多时间只会在事情顺利进行时延迟测试。使用 WebDriverWait 通过只等待需要的时间来解决这个问题。你应该可以消除睡眠。但是,我会使用EC.visibility_of_element_located。如果有一个 ajax 调用正在进行,有一种方法可以等到 ajax 完成。
    • @MarcelWilson 当我只使用WebDriverWait 进行测试时,它导致我的机器出现错误。不过,当结合使用时,也许等待 1 秒就可以了。正如我在回答中评论的那样,我认为 selenium 能够识别元素存在,但没有等待就无法与之交互(至少在我的测试中)
    • 可见性与存在感会有所不同。存在可以在可见性之前触发。
    【解决方案2】:

    问题是 selenium 在元素完成加载到 DOM 之前尝试与元素交互。解决此问题的一种方法是将 WebDriverWait 与 expected_conditions 模块结合使用来“查找”元素并然后与它们进行交互。

    试试这样的。

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait
    
    driver = webdriver.Chrome()
    driver.get("https://www.eco-visio.net/v5/")
    wait = WebDriverWait(driver, 10)
    ec = EC.visibility_of_element_located((By.ID, "login-username"))
    try:
        username = wait.until(ec, f"Could not find {ec.locator}")
        username.send_keys("midregcog.admin")
    except Exception as exc:
        raise
    finally:
        driver.quit()
    

    【讨论】:

    • 这个答案在username = wait.until(ec, f"Could not find {ec.locator}") 处有语法错误,但信息量很大,可以了解硒和网站的交互
    • 我猜你不是 3.6 或更高版本。我在这里使用了一个 f-string,这是一个新事物。改用这条线; username = wait.until(ec, "Could not find {}".format(loc=ec.locator)
    猜你喜欢
    • 1970-01-01
    • 2016-09-03
    • 2012-09-10
    • 2022-01-22
    • 1970-01-01
    • 2021-07-09
    • 2018-06-14
    • 2018-09-02
    • 1970-01-01
    相关资源
    最近更新 更多