问题
I am trying to click on the following button on a linkedin page using selenium
:
<button id="ember607" class="share-actions__primary-action artdeco-button artdeco-button--2 artdeco-button--primary ember-view" data-control-name="share.post"><!---->
<span class="artdeco-button__text">
Post
</span></button>
I have tried to use:
driver.find_element_by_id
, but the id of the button seems to keep changing numberdriver.find_element_by_xpath
, but this contains the button number, so also failsdriver.find_element_by_class_name('share-actions__primary-action artdeco-button artdeco-button--2 artdeco-button--primary ember-view')
, this fails even though the class name is correct ?
Basically, all methods generate the same error message:
Exception has occurred: NoSuchElementException
Message: no such element: Unable to locate element:{[*the_error_is_here*]}
I have also tried the xpath contains() method, but this does not find the button.
What would be the correct way to click on this button please ?
I am using python version 3.9
on windows
with driver = webdriver.Chrome
回答1:
The element is an Ember.js enabled element. So to click()
on the element with text as Post you can use either of the following Locator Strategies:
Using
css_selector
:driver.find_element_by_css_selector("button.share-actions__primary-action[data-control-name='share.post']>span.artdeco-button__text").click()
Using
xpath
:driver.find_element_by_xpath("//button[contains(@class, 'share-actions__primary-action') and @data-control-name='share.post']/span[@class='artdeco-button__text' and contains(., 'Post')]").click()
Ideally, to click on 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
:WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.share-actions__primary-action[data-control-name='share.post']>span.artdeco-button__text"))).click()
Using
XPATH
:WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(@class, 'share-actions__primary-action') and @data-control-name='share.post']/span[contains(., 'Post')]"))).click()
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
References
You can find a couple of relevant detailed discussions in:
- Selenium - Finding element based on ember
- Automate Ember.js application using Selenium when object properties are changed at run-time
- Ember: Best practices with Selenium to make integration tests in browser
- Ember dropdown selenium xpath
回答2:
Sometimes there are problems with buttons that are not clickable at the moment. Try this:
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
wait = WebDriverWait(driver, 10)
button = wait.until(EC.element_to_be_clickable((By.XPATH, '[YOUR X_PATH TO THE BUTTON]')))
driver.execute_script("arguments[0].click()", button)
It's not the cleanest way to click any Button with selenium, but for me this method works mostly everytime.
回答3:
//button[@class="share-actions__primary-action artdeco-button artdeco-button--2 artdeco-button--primary ember-view"].
Or
//button[contains(@id,'ember')]
回答4:
Find the span with Post and click it's button tag.
//span[contains(text(), 'Post')]/parent::button
回答5:
By xpath this should work:
//button/span[contains(text(), "Post")]
Combine it with a wait for the element:
button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//button/span[contains(text(), "Post")]"))
)
The problem with your by class selectors is the multiple class names. See this question: How to get elements with multiple classes for more details on how to overcome that.
来源:https://stackoverflow.com/questions/65160757/click-on-ember-js-enabled-element-using-selenium