Selenium find second element by Xpath - python

I want to find_element_by_xpath("//button[#class='sqdOP']") in python selenium , But i have 2 Button with that's class and i need the second one, so it takes me only the first one.
i've tried the code below
find_element_by_xpath("//button[#class='sqdOP'][2]")
find_element_by_xpath("//[button[#class='sqdOP']][2]")
find_element_by_xpath("//button[2][#class='sqdOP']")
find_element_by_xpath("//button[#class='sqdOP'[2]]")
None of above worked.

You're probably looking for this XPath expression :
find_element_by_xpath("(//button[#class='sqdOP'])[2]"
Just add () to get the second button element on the page which fulfill a specific attribute condition (#class='sqdOP').
Side note : your second try (//[button...) is not a valid XPath expression. You can't start an expression with a predicate. You need an element name or a wildcard (*).

Use find_elements_by_xpath instead of find_element_by_xpath to get a list of elements. Access a specific index in this list to get the required element.

You can try with JavaScript executor
WebElement buttton = driver.find_element_by_class_name("sqdOP")
driver.execute_script("arguments[1].click();",buttton)
arguments[1] means click on second element.

Related

Click a button in loop unless a new element gets added to the source of page - python selenium

I'm struggling to make code like:
click the button with the help of the selenium unless a new table get created and stop after the table exists. I'm using python with selenium.
i've tried to search everywhere but didn't find the solution. any help will be appreciated.
my code
while not driver.find_element(By.ID("tableID")):
submit_btn.click()
Change find_element with find_elements.
find_element will throw exception in case of no element exists while find_elements returns a list of web elements matching the passed locator. In case of matching elements existing it will return a non-empty list interpreted by Python as a Boolean True. Otherwise it will return an empty list interpreted by Python as a Boolean False.
Also you have a syntax problem in (By.ID("tableID")).
This should work:
while not driver.find_elements(By.ID, "tableID"):
submit_btn.click()
Also you may wish to put some delay inside the loop to not perform clicks too fast, so this may be better:
while not driver.find_elements(By.ID, "tableID"):
submit_btn.click()
time.sleep(0.1)

Python Selenium Find Element by X Path Only under that Class Name

I am trying to apply find_element_by_xpath only on specific classnames
textboxes = driver.find_elements_by_class_name("freebirdFormviewerViewNumberedItemContainer")
for element in textboxes:
a = element.find_element_by_xpath("//*[contains(#id, 'i')]")
I want to find the element by x path that contains the first item that has "id" in it, as there could be multiples in that node e.g "id1", "id2"
The problem is that it keeps returning the same id i.e "id1" despite me using the for loop.
Does it not loop through different element in the textboxes list? I want to apply the find_element_by_xpath only under that child node.
You are close to the right solution but missing a small point . :)
So inside the for loop you should use a = element.find_element_by_xpath(".//*[contains(#id, 'i')]")
I mean the . before the // at the beginning of the xpath expression.
Also possibly there is a problem with i inside the contains(#id, 'i') - I don't see where you are updating it's value.
To find the input element you can simply use the following css selector .freebirdFormviewerViewNumberedItemContainer input or if you prefer xpath you can use //div[#class='freebirdFormviewerViewNumberedItemContainer']//input
You are not augmenting i inside your loop, so it just stays the same for every iteration.

How to use wait expected condition to wait for the attribute in an element to contain certain value before clicking using python and selenium

Pls am trying to use the wait condition to wait for the value of an element to change before clicking it
this is the previous code;
driver.find_elements_by_xpath('//div[#data-markettypecategory="00000000-0000-0000-da7a-000000580001" and #data-pd="12.01"]')[0].click()
the code above only works when data-pd=12.01, i want to make it wait for data-pd is price (e.g $12.01), it could be any value(e.g 100.00,2.00,50.00 e.t.c), i just want it to be able to wait until the value turns to 12.01 until it clicks
first, copy FULL Xpath. NOT normal Xpath.
Full XPath looks like this:
xpath = '/html/body/div[3]/div[2]/div/div[1]/div[1]/h1/a'
You can then get the element's text value and check if it changed.
string = driver.find_elements_by_xpath(xpath).text
print(string)
if string == "12.01":
click()

Click (), send Keys () functions are not available for find element by x path option

I am using Python version 3.8.2 with selenium 3.14.1.
I am new to both Python and Selenium. I am using Pycharm to write my automation scripts.
When i try to use driver.find_elements_by_xpath().click() command, The click() option is not displayed in the drop down.
The same click() option is available if i use driver.find_element_by_name or driver.find_element_by_id commands.
Find elements by Name
Find elements by id
How can we resolve this issue?
To quote the Selenium documentation:
To find multiple elements (these methods will return a list):
find_elements_by_name
find_elements_by_xpath
...
You can't call .click on driver.find_elements_by_xpath() because driver.find_elements_by_xpath() returns a list of elements, rather than a single element.
Suppose driver.find_elements_by_xpath() returns 10 elements. What do you want to do with these 10 elements? Click on the first one? Click on the last one? Click on all of them?
If you only want to find a single element using XPath, use driver.find_element_by_xpath() (note, no s after element) instead.
The documentation page I linked to above lists 8 methods for finding a single element on the page. All of these methods apart from find_element_by_id have a corresponding method for returning multiple elements, whose name differs only by replacing element with elements. (There is no find_elements_by_id method because ids are supposed to be unique: there should never be more than one element with the same id.)
Adding for above answer.
You can use a List to store webelements and loop through them while doing actions. Something in java.
List<WebElement> elements = driver.findElements(By.id("001"));
for(WebElement ele:elements) {
ele.click();
}

what to do for dynamically changing xpaths in python using selenium?

I have a xpath as:
//*[#id="jobs-search-box-keyword-id-ember968"]
The number 968 constantly keeps on changing after every reload.
Rest of the string remains constant.
How to I find the constantly changing xpath?
You can use partial id with contains()
//*[contains(#id, "jobs-search-box-keyword-id-ember")]
You can try using starts-with below,
//*[starts-with(#id,'jobs-search-box-keyword-id-ember')]
The details provided is insufficient to to provide the accurate result. Still you can follow the below code references
In //*[#id="jobs-search-box-keyword-id-ember968"] the last number 968 keeps changing. but if you make this like //*[starts-with(#id,'jobs-search-box-keyword-id-ember')] then there might be possibility that you can have more then one element with the same partial is i.e. jobs-search-box-keyword-id-ember in this case it will locate on 1st matching element. that may not be your expected one
Use the tag name lets say element is an input tag whose id is jobs-search-box-keyword-id-ember968
Xpath - //input[starts-with(#id,'jobs-search-box-keyword-id-ember')]
CSS - input[id^='jobs-search-box-keyword-id-ember']
Use the relevant parent element to make this more specific. e.g the element is in parent tag <div class="container">
Xpath- //div[#class='container']//input[starts-with(#id,'jobs-search-box-keyword-id-ember')]
CSS - div.container input[id^='jobs-search-box-keyword-id-ember']
This worked for me:
Locator:
JOBS_SEARCH_BOX_XPATH = "//*[contains(#id,'jobs-search-box-keyword-id-ember')]"
Code:
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, JOBS_SEARCH_BOX_XPATH)))
.send_keys("SDET")

Categories