Selenium not waiting for element to be visible causing error: invalid element state
Selenium not waiting for element to be visible causing error: invalid element state
错误:元素当前不可交互,可能无法操作。
所以我用 selenium 请求页面,然后填写几个输入框,然后单击按钮提交表单。
我遇到的问题是 selenium 没有等待元素可见,所以我必须手动放置一个 time.sleep(2) 来解决这个问题,但我更愿意使用等待直到它们出现,以防加载时间更长或更短,或者它们根本不加载。
我目前有这样的设置来请求页面,找到输入字段,检查元素是否存在并在其中输入文本,我在 element.clear() 部分收到此错误当我在请求 url:
后包含 time.sleep(2) 时不会发生
错误
Traceback (most recent call last):
File "C:\Users\example\AppData\Roaming\JetBrains\PyCharmCE2021.2\scratches\example.py", line 125, in <module>
completeForm(
File "C:\Users\example\AppData\Roaming\JetBrains\PyCharmCE2021.2\scratches\example.py", line 89, in completeForm
typeText(Field, text)
File "C:\Users\example\AppData\Roaming\JetBrains\PyCharmCE2021.2\scratches\example.py", line 50, in typeText
element.clear()
File "C:\Users\example\Desktop\selenium-program\venv\lib\site-packages\selenium\webdriver\remote\webelement.py", line 92, in clear
self._execute(Command.CLEAR_ELEMENT)
File "C:\Users\example\Desktop\selenium-program\venv\lib\site-packages\selenium\webdriver\remote\webelement.py", line 693, in _execute
return self._parent.execute(command, params)
File "C:\Users\example\Desktop\selenium-program\venv\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 400, in execute
self.error_handler.check_response(response)
File "C:\Users\example\Desktop\selenium-program\venv\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 236, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.InvalidElementStateException: Message: invalid element state: Element is not currently interactable and may not be manipulated
(Session info: chrome=93.0.4577.63)
代码
from seleniumwire.undetected_chromedriver.v2 import Chrome, ChromeOptions
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
import random
import time
#Setup selenium chrome browser with options
def setupBrowser():
global driver
options = {}
chrome_options = ChromeOptions()
driver = Chrome(seleniumwire_options=options, options=chrome_options)
#Type like a human
def typeText(element, text):
success = False
if doesElementExist(element):
while success == False:
actions = ActionChains(driver)
actions.move_to_element(element)
actions.click()
element.clear()
for character in text:
actions.send_keys(character)
actions.perform()
time.sleep(random.uniform(0.13, 0.4))
if element.get_attribute("data-initial-value") == text:
success = True
#check if element exists, times out after some time and returns error
def doesElementExist(element):
timeout = 10
try:
element_present = EC.visibility_of_element_located(element)
WebDriverWait(driver, timeout).until(element_present)
except TimeoutException:
print("Error: Timed out after {} seconds waiting for element to load!".format(timeout))
return False
finally:
return True
driver.get(url)
driver.implicitly_wait(60)
Field = driver.find_element_by_xpath('//*[@id="mG61Hd"]/div[2]/div/div[2]/div[1]/div/div/div[2]/div/div[1]/div/div[1]/input')
text = "exampletexttowrite123"
typeText(Field, text)
您的 typeText
需要更正。它没有 .perform()
所以发生的是所有项目都将存储在 Actioncahins 队列中,并且在您编写 .perform()
的那一刻,它们将被一个一个地释放。
代码:
def typeText(element, text):
success = False
if doesElementExist(element):
while success == False:
actions = ActionChains(driver)
actions.move_to_element(element).perform()
element.click()
element.clear()
for character in text:
actions.send_keys(character).perform()
time.sleep(random.uniform(0.13, 0.4))
if element.get_attribute("data-initial-value") == text:
success = True
PS :
此方法直接接受一个web element
,确保网页元素正确呈现。
更新:
driver = webdriver.Chrome(driver_path)
driver.maximize_window()
#driver.implicitly_wait(50)
driver.get("https://docs.google.com/forms/d/e/1FAIpQLSfMJRFOPF0qeJG3DHrbzbDR7nETPF0qE2D-r_F3kjjqdP9B1w/viewform")
wait = WebDriverWait(driver, 20)
ActionChains(driver).move_to_element(wait.until(EC.visibility_of_element_located((By.XPATH, "//div[text()='Your answer']/preceding-sibling::input")))).perform()
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[text()='Your answer']/preceding-sibling::input"))).send_keys('cruise')
错误:元素当前不可交互,可能无法操作。
所以我用 selenium 请求页面,然后填写几个输入框,然后单击按钮提交表单。
我遇到的问题是 selenium 没有等待元素可见,所以我必须手动放置一个 time.sleep(2) 来解决这个问题,但我更愿意使用等待直到它们出现,以防加载时间更长或更短,或者它们根本不加载。
我目前有这样的设置来请求页面,找到输入字段,检查元素是否存在并在其中输入文本,我在 element.clear() 部分收到此错误当我在请求 url:
后包含 time.sleep(2) 时不会发生错误
Traceback (most recent call last):
File "C:\Users\example\AppData\Roaming\JetBrains\PyCharmCE2021.2\scratches\example.py", line 125, in <module>
completeForm(
File "C:\Users\example\AppData\Roaming\JetBrains\PyCharmCE2021.2\scratches\example.py", line 89, in completeForm
typeText(Field, text)
File "C:\Users\example\AppData\Roaming\JetBrains\PyCharmCE2021.2\scratches\example.py", line 50, in typeText
element.clear()
File "C:\Users\example\Desktop\selenium-program\venv\lib\site-packages\selenium\webdriver\remote\webelement.py", line 92, in clear
self._execute(Command.CLEAR_ELEMENT)
File "C:\Users\example\Desktop\selenium-program\venv\lib\site-packages\selenium\webdriver\remote\webelement.py", line 693, in _execute
return self._parent.execute(command, params)
File "C:\Users\example\Desktop\selenium-program\venv\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 400, in execute
self.error_handler.check_response(response)
File "C:\Users\example\Desktop\selenium-program\venv\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 236, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.InvalidElementStateException: Message: invalid element state: Element is not currently interactable and may not be manipulated
(Session info: chrome=93.0.4577.63)
代码
from seleniumwire.undetected_chromedriver.v2 import Chrome, ChromeOptions
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
import random
import time
#Setup selenium chrome browser with options
def setupBrowser():
global driver
options = {}
chrome_options = ChromeOptions()
driver = Chrome(seleniumwire_options=options, options=chrome_options)
#Type like a human
def typeText(element, text):
success = False
if doesElementExist(element):
while success == False:
actions = ActionChains(driver)
actions.move_to_element(element)
actions.click()
element.clear()
for character in text:
actions.send_keys(character)
actions.perform()
time.sleep(random.uniform(0.13, 0.4))
if element.get_attribute("data-initial-value") == text:
success = True
#check if element exists, times out after some time and returns error
def doesElementExist(element):
timeout = 10
try:
element_present = EC.visibility_of_element_located(element)
WebDriverWait(driver, timeout).until(element_present)
except TimeoutException:
print("Error: Timed out after {} seconds waiting for element to load!".format(timeout))
return False
finally:
return True
driver.get(url)
driver.implicitly_wait(60)
Field = driver.find_element_by_xpath('//*[@id="mG61Hd"]/div[2]/div/div[2]/div[1]/div/div/div[2]/div/div[1]/div/div[1]/input')
text = "exampletexttowrite123"
typeText(Field, text)
您的 typeText
需要更正。它没有 .perform()
所以发生的是所有项目都将存储在 Actioncahins 队列中,并且在您编写 .perform()
的那一刻,它们将被一个一个地释放。
代码:
def typeText(element, text):
success = False
if doesElementExist(element):
while success == False:
actions = ActionChains(driver)
actions.move_to_element(element).perform()
element.click()
element.clear()
for character in text:
actions.send_keys(character).perform()
time.sleep(random.uniform(0.13, 0.4))
if element.get_attribute("data-initial-value") == text:
success = True
PS :
此方法直接接受一个web element
,确保网页元素正确呈现。
更新:
driver = webdriver.Chrome(driver_path)
driver.maximize_window()
#driver.implicitly_wait(50)
driver.get("https://docs.google.com/forms/d/e/1FAIpQLSfMJRFOPF0qeJG3DHrbzbDR7nETPF0qE2D-r_F3kjjqdP9B1w/viewform")
wait = WebDriverWait(driver, 20)
ActionChains(driver).move_to_element(wait.until(EC.visibility_of_element_located((By.XPATH, "//div[text()='Your answer']/preceding-sibling::input")))).perform()
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[text()='Your answer']/preceding-sibling::input"))).send_keys('cruise')