I am trying to grab the value of the version info, 1.0, in this case.
If I right click and Inspect Element, I see the following:
<span class="ng-binding" ng-bind="$ctrl.Version">1.0</span>
If I copy CSS Selector in Firefox, it shows me the following:
.version-numbers > div:nth-child(1) > span:nth-child(2)
I am trying the following Python code:
print(driver.find_element_by_css_selector(".version-numbers[value='$ctrl.backendVersion']").text)
I haven't been able to get it to work with XPath either. I get an Unable to locate Element error.
Any suggestions?
As per the given HTML to retrieve the text 1.0 you need to induce WebDriverWait with expected_conditions clause as visibility_of_element_located and you can use the following line of code :
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//span[#class='ng-binding']"))).get_attribute("innerHTML"))
I used CSS Selector and it appears to be working now. Thank you for your suggestions.
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 want to use selenium to find a div:
My code is :
self.browser.find_element_by_xpath('//div[#class="bh-headerBar-nav-item"]').click()
But I got the error:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//div[#class="bh-headerBar-nav-item"]"}
What should I do to find this div?
You can try changing the style value of the element to block using javascript.
self.driver.execute_script("document.getElementsByClassName("class-name")[0].style.display = 'block';")
Then try to access the element.
Short:
Your xpath looks correct for the exampled page html, but the class on screenshot ends with the space char. (it could be the reason).
Longer:
If you getting NoSuchElementException there can be 3 cases:
your div present in iframe, so you need to switch to iframe with driver.switch_to.iframe command before invoke find_element.
you looking for div with the exact class match. class attribute sometimes changed after some actions, some classes could be added or removed. So, try to use //div[contains(#class, 'your_class')]. I see, your class ends with the space char on screenshot, it may affect.
the element really not present on the page.
Try to take screenshot, or print pagesource and look for the element, may be this will bring more information regarding the real reason.
The DIV tag is a descendant of the A tag.
To click on the descendant DIV you can use either of the following Locator Strategies:
Using css_selector:
self.browser.find_element(By.CSS_SELECTOR, "a[href='#/sportVenueBookBC'] div.bh-headerBar-nav-item.").click()
Using xpath:
self.browser.find_element(By.XPATH, "//a[#href='#/sportVenueBookBC']//div[#class='bh-headerBar-nav-item ']").click()
However, the desired element is a dynamic element, so 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(self.driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a[href='#/sportVenueBookBC'] div.bh-headerBar-nav-item."))).click()
Using XPATH:
WebDriverWait(self.driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[#href='#/sportVenueBookBC']//div[#class='bh-headerBar-nav-item ']"))).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 discussions on NoSuchElementException in:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium
selenium in python : NoSuchElementException: Message: no such element: Unable to locate element
I have a very complex website which I am trying to test with Selenium. But when I try to get the XPath, I get like this for example.
//*[#id="datatable1595356931082"]/div[1]/div[2]/table/tbody/tr[3]/td[2]/div/select/option[8]
Absolute XPath:
/html/body/div[4]/div[2]/div[2]/div/div[2]/div[2]/div/div/div[1]/div[2]/table/tbody/tr[3]/td[2]/div/select/option[8]
in Selenium I tried with absolute path like
driver.find_element_by_xpath("/html/body/div[4]/div[2]/div[2]/div/div[2]/div[2]/div/div/div[1]/div[2]/")
and it tries to error out saying it is unable to find XPath. The datatable seems to create a dynamic number during runtime.
What here I am trying to do is to select a drop down which looks like this
<div role="columnheader" class="webix_hcell webix_ss_filter">
<select>
<option value=""></option>
<option value="A">A</option>
<option value="B">B</option>
.
.
.
</select>
</div>
I have also tried
driver.find_element_by_class_name('webix_hcell webix_ss_filter')
But that too errors out
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".webix_hcell webix_ss_filter"}
For the above one
selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: Unable to locate an element with the xpath expression /html/body/div[4]/div[2]/div[2]/div/div[2]/div[2]/div/div/div[1]/div[2]/ because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string '/html/body/div[4]/div[2]/div[2]/div/div[2]/div[2]/div/div/div[1]/div[2]/' is not a valid XPath expression.
(Session info: chrome=84.0.4147.89)
This won't work, because *_by_class_name is only for single class name:
driver.find_element_by_class_name('webix_hcell webix_ss_filter')
Try using *_by_css_selector:
element = driver.find_element_by_css_selector('div.webix_hcell.webix_ss_filter select')
There are a couple of things you need to consider as follows:
From your first attempt the WebElement appears as a dynamic element due to presence of the id attribute value as datatable1595356931082, which possibly will change on every access or periodically:
//*[#id="datatable1595356931082"]/div[1]/div[2]/table/tbody/tr[3]/td[2]/div/select/option[8]
In your second attempt you have used an absolute xpath. As the website is dynamic, elements will be repositioned on every access or periodically:
/html/body/div[4]/div[2]/div[2]/div/div[2]/div[2]/div/div/div[1]/div[2]/table/tbody/tr[3]/td[2]/div/select/option[8]
In your third attempt the xpath ends with / which isn't desired. Hence you face InvalidSelectorException
In your forth attempt you have passed multiple classes through driver.find_element_by_class_name('webix_hcell webix_ss_filter') where as driver.find_element_by_class_name() accepts only one classname as an argument.
You can find a detailed discussion in Invalid selector: Compound class names not permitted error using Selenium
Finally, it's a <select> node, so you need to use the Select class.
You can find a detailed discussion in How to select a drop-down menu value with Selenium using Python?
Solution
The relevant text based HTML would have helped us to construct a canonical answer. However as per the HTML provided to click on the option with text as A you can use the following either of the following Locator Strategies:
Using XPATH and select_by_visible_text():
select = Select(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#class='webix_hcell webix_ss_filter' and #role='columnheader']//following::select[1]"))))
select.select_by_visible_text('A')
Using CSS_SELECTOR and select_by_value():
select = Select(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "div.webix_hcell.webix_ss_filter[role='columnheader'] +select"))))
select.select_by_value('A')
Note : You have to add the following imports :
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
I am automating a function where the user needs to click on the link highlighted in the below link.
HTML
I tried a contains on the xpath which is //*[#id="lc"], and an onclick option from Here neither of which work and error with the element doesn't exist error.
I know I am in the right iframe, because when using the xpath with no contains the script clicks the first xpath link with no issue.
To click() on the desired element as the element is a dynamic element you have 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, "td.EMROtherEpsEven>table tr>td.EMROtherEpsEven#lc[onclick*='Hemoglobin']"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//td[#class='EMROtherEpsEven']/table//tr/td[#class='EMROtherEpsEven' and #id='lc'][contains(#onclick, 'Hemoglobin')]"))).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
I have not use Selenium with Python, but I have with java, and in Java you have to use simple quote (') instead the double quote ("), or you can just a simpler locator id=lc without any quotes, if you're sure the ID is correct this should work.
i have done this in java hope you find the answer
yes in static or in dynamic tables the id will be the same but if you try using absolute xpath
this are two absolute path of the table element resides each other in first row
/html[1]/body[1]/section[1]/section[1]/div[1]/data[1]/div[1]/div[4]/div[1]/div[1]/div[1]/div[1]/div[2]/div[2]/div[1]/div[1]/div[1]/div[1]
/html[1]/body[1]/section[1]/section[1]/div[1]/data[1]/div[1]/div[4]/div[1]/div[1]/div[1]/div[1]/div[2]/div[2]/div[1]/div[1]/div[1]/div[2]/div[1]
This are the relative xpath of the same elements
//a[contains(text(),'AF17OT41603')]
//div[#id='1547533504703-0-uiGrid-000C-cell']//div[#class='ui-grid-cell-contents ng-binding ng-scope'][contains(text(),'AKSHAY PATIL')]
Table
I am dealing with a situation where every time I login a report is displayed in a table whose ID is dynamically generated with random text ending with "table".
I am automating this table with selenium python web driver. It has Syntax
driver.find_element_by_xpath('//*[#id="isc_43table"]/tbody/tr[1]/td[11]').click();
help me editing this syntax to match it with table ending id with "table".
(only one table is generated).
The ends-with XPath Constraint Function is part of XPath v2.0 but as per the current implementation Selenium supports XPath v1.0.
As per the HTML you have shared to identify the element you can use either of the Locator Strategies:
XPath using contains():
driver.find_element_by_xpath("//*[contains(#id,'table')]/tbody/tr[1]/td[11]").click();
Further, as you have mentioned that table whose ID is dynamically generated so to invoke click() on the desired element you need to induce WebDriverWait for the element to be clickable and you can use the following solution:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//*[contains(#id,'table')]/tbody/tr[1]/td[11]"))).click()
Alternatively, you can also use CssSelector as:
driver.find_element_by_css_selector("[id$='table']>tbody>tr>td:nth-of-type(11)").click();
Again, you can also use CssSelector inducing WebDriverWait as:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[id$='table']>tbody>tr>td:nth-of-type(11)"))).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
I hope, either these 2 will work for you
driver.find_element_by_xpath("//table[ends-with(#id,'table')]/tbody/tr[1]/td[11]").click();
OR
driver.find_element_by_xpath("//table[substring(#id,'table')]/tbody/tr[1]/td[11]").click();
If not getting, remove the tags from tbody.
For such situations, when you face randomly generated ids, you can use the below functions with XPATH expression
1) Contains,
2) Starts-with &
3) Ends-with
4) substring
Syntax
//table[ends-with(#id,'table')]
//h4/a[contains(text(),'SAP M')]
//div[substring(#id,'table')]
You need to identify the element which is having that id, whether its div or input or table. I think its a table.
You can try below XPath to simulate ends-with() syntax:
'//table[substring(#id, string-length(#id) - string-length("table") +1) = "table"]//tr[1]/td[11]'
You can also use CSS selector:
'table[id$="table"] tr>td:nth-of-type(11)'