HTML:
<button type = "submit" class = "car">
How should I search for this button in selenium python using both the attributes type and class in find_element_by_xpath()
To locate the element using both the attributes class and type you can club up them in a single locator and you can use either of the following Locator Strategies:
Using css_selector:
element = driver.find_element_by_css_selector("button.car[type='submit']")
Using xpath:
element = driver.find_element_by_xpath("//button[#class='car' and #type='submit']")
References
You can find a couple of relevant detailed discussions in:
How to identify an element through classname even though there are multiple elements with the same classnames using Selenium and Python
Try to use this XPATH
'//button[#type="submit" and #class="car"]'
Related
I am trying to retrieve the text of a specific element in a table with the following XPATH:
/html/body/form[2]/table/tbody/tr/td/table/tbody/tr[2]/td[7]/input
using
driver.maximize_window() # For maximizing window
driver.implicitly_wait(3) # gives an implicit wait for 20 seconds
driver.find_element(By.XPATH, value = "/html/body/form[2]/table/tbody/tr/td/table/tbody/tr[2]/td[7]/input").text()
but I get the following error:
NoSuchElementException: Message: Unable to locate element: /html/body/form[2]/table/tbody/tr/td/table/tbody/tr[2]/td[7]/input
I have also tried accessing the element by CSS selector and value, without success.
Unfortunately the link is secured so I cannot share it but here is a screenshot of the element
Instead of your absolute XPath, try relative XPath. Below is the expression:
//input[#name='AdjIncrementAmount_1']
from the screenshot, I am not really sure if the value of attribute name (after the text Amount) has one _ or two __. If the above with(one _) doesn't work, try with 2 as below:
//input[#name='AdjIncrementAmount__1']
To print the text $36,400.00 you can use either of the following locator strategies:
Using css_selector:
print(driver.find_element(By.CSS_SELECTOR, "td > input[name='AdjIncrementAmount__1']").get_attribute("value"))
Using xpath:
print(driver.find_element(By.XPATH, "//td/input[#name='AdjIncrementAmount__1']").get_attribute("value"))
Note : You have to add the following imports :
from selenium.webdriver.common.by import By
I need to find an element by ID "start-ads", but the numbers at the end change every time. Is it possible to search for an element not by the whole ID, but only by its part?
Full element id: <div id="start-ads-202308">
To identify the following element:
<div id="start-ads-202308">
considering the static part of the value of id attribute you can use either of the following Locator Strategies:
Using css_selector:
element = driver.find_element(By.CSS_SELECTOR, "div[id^='start-ads-']")
where ^ denotes starts-with
Using xpath:
element = driver.find_element(By.XPATH, "//div[starts-with(#id, 'start-ads-')]")
You can use find_element_by_css_selector and use a CSS selector that matches using a prefix
driver.find_element_by_css_selector("div[id^='start-ads-']")
I'm new to python and webscraping so I'm not sure what the name of the value inbetween the <div>'s in an element is called. Sorry for not being able to specify.
<div class="syllable">value</div>
Is there a way to have the value inbetween the <div>'s get assigned to a string variable in python using selenium using XPath?
For example, the "value" in the element would be a string and it would print out:
value
I'm new to python and selenium so I can't figure it out.
To print out the text of the element.
elem=driver.find_element_by_class_name("syllable")
print(elem.text)
xpath:
elem=driver.find_element_by_xpath("//div[#class='syllable']/text()")
print(elem)
it is called html innerText
you can retrieve this value using text in selenium , or get_attribute.
This returns the rendered text (means displayed text)
elem=driver.find_element_by_class_name("syllable")
print(elem.text)
This return the text with out checking the style attribute meaning returns value even if its not displayed in UI
elem=driver.find_element_by_class_name("syllable")
print(elem.get_attribute("textContent")
you can find elem using this text also:
// partial match
elem=driver.find_element_by_xpath("//div[contains(text(),'value')])
print(elem.text)
// exact match
elem=driver.find_element_by_xpath("//div[text()='value')])
print(elem.text)
// exact match of the elements text if there is any child element like span it won't return the element
elem=driver.find_element_by_xpath("//div[.='value')])
print(elem.text)
Also note:
Other things you could read about outerHTML , innerHTML
To print the text value you can use either of the following Locator Strategies:
Using class_name and get_attribute("textContent"):
print(driver.find_element_by_class_name("syllable").get_attribute("textContent"))
Using css_selector and get_attribute("innerHTML"):
print(driver.find_element_by_css_selector("div.syllable").get_attribute("innerHTML"))
Using xpath and text attribute:
print(driver.find_element_by_xpath("//div[#class='syllable']").text)
Ideally you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:
Using CLASS_NAME and get_attribute("textContent"):
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CLASS_NAME, "syllable"))).get_attribute("textContent"))
Using CSS_SELECTOR and text attribute:
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.syllable"))).text)
Using XPATH and get_attribute():
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//div[#class='syllable']"))).get_attribute("innerHTML"))
Console Output:
value
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
You can find a relevant discussion in How to retrieve the text of a WebElement using Selenium - Python
References
Link to useful documentation:
get_attribute() method Gets the given attribute or property of the element.
text attribute returns The text of the element.
Difference between text and innerHTML using Selenium
I recently recommended to my devs to add IDs to each element on the project I'm working to make automation more robust, they added in aria-uuid to each element. I cannot get anything to recognize these IDs! I'm wondering if it is even possible?
I'm using python/selenium.
I've tried identifying elements by ID, I've done CSS selectors and xpaths but they have had a history of breaking between new builds.
Relevant html:
input class="short ng-valid ng-not-empty ng-valid-min ng-valid-required" name="question_16" type="number" aria-uuid="question_16_input" ng-required="true" ng-min="0" ng-model="$ctrl.vault['question_16'].value"
def click_element_by_id(self, driver_init, id1, message1, delay1, halt):
try:
element = WebDriverWait(driver_init, delay1).until(EC.element_to_be_clickable((By.ID, id1)))
element.click()
except TimeoutException:
if halt:
assert_that(True, message1).is_false()
else:
print(message1)
Each time I get the assertion/timeout error
Ideally, yes you should have been able to recognize each individual elements with respect to their aria-uuid to be used with Selenium provided the generated aria-uuid were static.
As per the HTML you have shared the generated aria-uuid seems to be dynamic. So aria-uuid alone won't help you. In these cases you have to use the aria-uuid along with the other attributes to uniquely identify the elements. To identify this element you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver_init, delay1).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input.short.ng-valid.ng-not-empty.ng-valid-min.ng-valid-required[aria-uuid$='_input'][name^='question_']"))).click()
Using XPATH:
WebDriverWait(driver_init, delay1).until(EC.element_to_be_clickable((By.XPATH, "//input[#class='short ng-valid ng-not-empty ng-valid-min ng-valid-required' and contains(#aria-uuid, '_input')][starts-with(#name, 'question_')]"))).click()
It should be possible with a CSS selector [aria-uuid='question_16_input']
I am using selenium in python and cannot get it to find and select the ok button. Here is the code I am trying to use that is not finding the button.
SubmitElem = driver.find_element_by_name('ctl00$PlaceHolderMain$ctl01$RptControls$btnOK')
SubmitElem.submit()
And this is the webpage code
<input name="ctl00$PlaceHolderMain$ctl01$RptControls$btnOK"
value="OK"
onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$PlaceHolderMain$ctl01$RptControls$btnOK", "", true, "", "", false, false))"
id="ctl00_PlaceHolderMain_ctl01_RptControls_btnOK" accesskey="o"
class="ms-ButtonHeightWidth" type="submit">
Any advice on what I am doing wrong? I found some suggestions to add onclick*= but it did not seem to work.
As noted earlier, if the element is in an iframe, you need to switch contexts. Additionally, if the element takes time to show up on the DOM, due to it being dynamically rendered by JavaScript, you might need waits. You basically want to wait until the element shows up on the page before performing actions on it.
From the Selenium docs:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
Here is the Answer to your Question:
As per the HTML you have provided, you may consider the following options:
You can consider to construct a xpath based on name as follows:
SubmitElem = driver.find_element_by_xpath("//input[#name='ctl00$PlaceHolderMain$ctl01$RptControls$btnOK']")
SubmitElem.submit()
You can also try a different xpath based on id as follows:
SubmitElem = driver.find_element_by_xpath("//input[#id='ctl00_PlaceHolderMain_ctl01_RptControls_btnOK']")
SubmitElem.submit()
Alternatively, you can also consider to call click() method instead of submit() method.
SubmitElem.click()
Again, it seems to me that the id and name is dynamic due to presence of JavaScript and AJAX Calls. In that case you can consider to construct a dynamic xpath as follows:
SubmitElem = driver.find_element_by_xpath("//input[starts-with(#id, 'ctl00')]")
SubmitElem.submit()
You can consider to construct a dynamic css_selector as follows:
SubmitElem = driver.find_element_by_css_selector("input[id^='ctl00']")
SubmitElem.submit()
Finally, if you see a NoSuchElementException or ElementNotVisibleException you may consider to induce some WebDriverWait as follows:
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//input[starts-with(#name, 'ctl00')]")))
driver.find_element_by_css_selector("input[name^='ctl00']").click()
There are total 6 suggested locators to identify the element along with different other options.
Let me know if this Answers your Question.