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_NAMEaccepts only one argument. So you won't be able to pass multiple classes.- The classnames e.g.
_13NKtare 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:
_13NKtcopyable-textselectable-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.
