Selenium is unable to find an element on a webpage, here is the python code
element = driver.find_element(By.CLASS_NAME, "_13NKt copyable-text selectable-text")
Here is an image of the element it is supposed to find, class highlighted
And here is the important line of the error message:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"._13NKt copyable-text selectable-text"}
(Session info: chrome=103.0.5060.134)
CodePudding user response:
The By-strategy By.CLASS_NAME
internally uses By.CSS_SELECTOR
and simply prefixes the locator with .
- which is also visible in your error message
{"method":"css selector","selector":"._13NKt copyable-text selectable-text"}
But that's not a valid CSS selector for an element that includes all those classes, instead you have to "concatenate" them with .
(simply replace the spaces between the classes with ".")
So either:
driver.find_element(By.CLASS_NAME, "_13NKt.copyable-text.selectable-text")
or use By.CSS_SELECTOR directly:
driver.find_element(By.CSS_SELECTOR, "._13NKt.copyable-text.selectable-text")
the only difference being the leading .
CodePudding user response:
You have to take care of a couple of things here:
By.CLASS_NAME
accepts only one argument. So you won't be able to pass multiple classes.- The classnames e.g.
_13NKt
are dynamically generated and is bound to chage sooner/later. They may change next time you access the application afresh or even while next application startup. So can't be used in locators. - The
<div>
is having the attributecontenteditable="true"
.
Solution
To identify the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using CSS_SELECTOR:
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div[data-testid='pluggable-input-body'][role='textbox']")))
Using XPATH:
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@data-testid='pluggable-input-body' and @role='textbox']")))
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC
CodePudding user response:
Selenium can't identify multiple class name of an element using CLASS_NAME
, instead use CSS_SELECTOR
.
element = driver.find_element(By.CSS_SELECTOR, "._13NKt.copyable-text.selectable-text")
The class name
can be dynamic,I would suggest use data-testid
property.
element = driver.find_element(By.CSS_SELECTOR, "[data-testid='pluggable-input-body']")
CodePudding user response:
When using By.CLASS_NAME
the given string is matched against each class name of you element. Your element has three different classes:
_13NKt
copyable-text
selectable-text
So the string "_13NKt copyable-text selectable-text"
does not match any one of them.
If you really need to find the element that has all of these classes, you can use driver.find_element(By.CSS_SELECTOR, "._13NKt.copyable-text.selectable-text")
instead (see docs). You may also be able to use XPath or something else, if that is more up your alley.
CodePudding user response:
Try:
element = WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CSS_SELECTOR, '._13NKt.copyable-text.selectable-text')))
You will also need to import:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
If it doesn't work, post your url.