Find an element with Python Selenium - python

Somebody can help me to find a way to click on an img with Python Selenium?
I need to find the div class="A" which has a div class="B" and then, click on his img in class="D"
<div class="A">
...
</div>
...
<div class="A">
<div class="B"> <!-- HERE IS WHAT I NEED TO CHECK-->
<span class="E"> <!-- HERE IS WHAT I NEED TO CHECK-->
<span class="F"> <!-- HERE IS WHAT I NEED TO CHECK-->
</div> <!-- HERE IS WHAT I NEED TO CHECK-->
<div class="C"> </div>
<div class="D">
<img class="Y" src="..."> <!-- HERE IS WHAT I NEED TO CLICK IF class="B" DOES EXIST (EVERY class="A" has an IMG in div class="D")-->
</div>
</div>
...
<div class="A">
...
</div>
I know I have to use XPath or CSS selector, but here it's not a rel/abs XPath... Please help me.

To check if the element exists you can use driver.find_elements.
It returns a list of web elements matching the passed locator.
In case the element exists it returns non-empty list treated as Boolean true in Python, otherwise it returns an empty list recognized as false in Python.
UPD:
According to the latest requirements your code can be something like this:
a_list = driver.find_elements_by_xpath("//div[#class='A']")
for a_el in a_list:
if a_el.find_elements_by_xpath(".//div[#class ='B']"):
a_el.find_element_by_xpath(".//img[#class ='Y']").click()

You can try this:
if driver.find_elements_by_xpath("//div[#class = 'A']/div[#class ='B']"): # Finding the element in case it exists.
image_to_click = driver.find_element_by_xpath("//div[#class = 'D']//img[#class ='Y']")
image_to_click.click() # Clicking on the image.

Thanks for your help !
The final code is :
skin_list = driver.find_elements_by_class_name("B")
if len(skin_list) != 0:
skin_list[0].find_element_by_xpath("..//div[#class='D']").click()
But now, my new problem is the "skin_list = driver.find_elements_by_class_name" take a long time to search...

Related

How to select an input according to a parent sibling label

The input element that I have does not have anything to identify it because is my page is built through a react framework. So I want to select the appropriate input by its label above it. My HTML looks like the following:
<div>
<label>Project</label>
</div>
<div>
<div>
<input>
</div>
</div>
<div>
<label>Type</label>
</div>
<div>
<div>
<input>
</div>
</div>
If you try to perform an action on a label which has associated input element Playwright will automatically retarget the action to the input.
If the DOM structure is always the same you can try something like this
page.locator('div:has( > :text-matches("Project")) + div input')
Otherwise layout selector is your best bet.
You could try with layout selectors:
const div = page.locator('input:right-of(:text("Project"))');

How to access multiple text boxes in selenium

i am trying fill the text boxes. Each time you get into the page the the number of text boxes will be different and the name of them will be different.
<div class="fb-single-line-text">
<div class="display-flex" data-test-single-line-text-input-wrap="true">
<!---->
<input name="urn:li:fs_easyApplyFormElement:(urn:li:fs_normalized_jobPosting:2620509178,30257397,numeric)" id="urn:li:fs_easyApplyFormElement:(urn:li:fs_normalized_jobPosting:2620509178,30257397,numeric)" class="ember-text-field ember-view fb-single-line-text__input" aria-required="true" aria-describedby="urn:li:fs_easyApplyFormElement:(urn:li:fs_normalized_jobPosting:2620509178,30257397,numeric)-error-message" data-test-single-line-text-input="" type="text">
</div>
</div>
the above lines are the html code of first text box
<div class="fb-single-line-text">
<div class="display-flex" data-test-single-line-text-input-wrap="true">
<!---->
<input name="urn:li:fs_easyApplyFormElement:(urn:li:fs_normalized_jobPosting:2620509178,30257389,numeric)" id="urn:li:fs_easyApplyFormElement:(urn:li:fs_normalized_jobPosting:2620509178,30257389,numeric)" class="ember-text-field ember-view fb-single-line-text__input" aria-required="true" aria-describedby="urn:li:fs_easyApplyFormElement:(urn:li:fs_norm
alized_jobPosting:2620509178,30257389,numeric)-error-message" data-test-single-line-text-input="" type="text">
</div>
</div>
So i see all of them class name in comman so i tried to get all the eemphasized textlemnts inside the class . but i could not find a possible way for it. can someone help me with that
There are multiple ways to deal with this situation.
use find_elements to find out how many input boxes are present in UI, also you could send different message to those input box.
total_no_of_input_with_div_single_line_text = len(driver.find_elements(By.CSS_SELECTOR, "div.fb-single-line-text input"))
print(total_no_of_input_with_div_single_line_text)
Now you can send_keys to individual elements like this :-
total_no_of_input_with_div_single_line_text[0].send_keys('some string')
you can always change the index above from 0 to 1, 2 etc.
second in a loop like this :
for ele in driver.find_elements(By.CSS_SELECTOR, "div.fb-single-line-text input"):
ele.send_keys('some value here')
other way would be to use xpath indexing to locate the element.
(//div[#class='fb-single-line-text']/descendant::input)[1]
should locate the first web element input in the page, also you have the access to change that to [2], [3] and so on..

Unable to locate element with Python Selenium fin_element_by_xpath

I have a HTML code like :
<div class="A">
<div class="B"></div>
<div class="B">
<div class="C"></div>
<div class="C">
<p class="D"> Element 1 </p>
<div class="C"></div>
</div>
</div>
<div class="A">
<div class="B"></div>
<div class="B">
<div class="C"></div>
<div class="C">
<p class="D"> Element 2 </p>
<div class="C"></div>
</div>
</div>
(this is an example, there is more class "A")
I want to extract the text "Element 2" with Python Selenium.
I tried a lot of things but always the same result : No such element: Unable to locate element...
I tried :
elem = driver.find_element_by_xpath("//div[#class='A:last-child']/p[#class='D']").text
same result...
Try this:
"(//div[#class='A']//p)[2]"
This should get the second instance of Class = "A" and then the p element beneath that
Try this xpath:
"(//div[#class='A']//p)[last()]"
The main problem with your xpath, I think, is that the single slash before the p element means to only look for direct children of the div. You want the double slash to find any descendant.
In this structure Xpath
(//div[#class="A"]//p[#class="D"])[2]
if this is a second hierarchy or
(//div[#class="A"]//p[#class="D"])[last()]
if it is a last should work

using nth-type or nth-child to select n element

Q: What XPath or CSS selector I can use to select 2nd <div class="checkbox">?
I have tried to use:
XPath - //div[#class="checkbox"][2]
CSS - div.checkbox:nth-child(2)
However none of them worked on chrome developer tool.
I can use $x('//div[#class="checkbox"]') to see all three checkboxes
I can use $x('//div[#class="checkbox"]')[0] to specify the 1st div.checkbox
I can use $x('//div[#class="checkbox"]')[1] to specify the 2nd div.checkbox
Here's an example of my HTML Structure
<div class="fs">
<div class="f">
<div class="checkbox">
<input type="radio" value="A">
<label for="A">A</label>
</div>
</div>
<div class="f">
<div class="checkbox">
<input type="radio" value="B">
<label for="B">B</label>
</div>
</div>
<div class="f">
<div class="checkbox">
<input type="radio" value="C">
<label for="C">C</label>
</div>
</div>
</div>
Rather than trying to find the second element by index, another possibility would be to get it by the value on the INPUT or the text in the LABEL that is contained in that DIV. A couple XPaths would be
//div[#class='checkbox'][./input[#value='B']]
//div[#class='checkbox'][./label[.='B']]
You need 2nd element from the results. Which can be done by using below
(//div[#class="checkbox"])[2]
I think CSS doesn't allow such a thing to select from a result
Since JeffC and Tarun Lalwani already suggested XPath way of doing it, I'd like to suggest a different approach.
In CSS, one can use :nth-child selector to choose 2nd <div class="f"> and grab the nested div from there. (> can be omitted)
div.f:nth-child(2) > div.checkbox
Similarly, the following works in XPath:
//div[#class='f'][2]/div[#class='checkbox']
One can choose an element based on the attribute value with CSS selector using Attribute selectors, but one cannot select the parent, unfortunately.

Selenium - driver.find_element_by_css_selector can't find the element (python)

I got a problem to use "find_element_by_css_selector" to get the element "Select" (a href).
I tried the methods below but all of them didn't work:
driver.find_element_by_css_selector("div.plan.right > a.select.").click()
driver.find_element_by_xpath("//div[#class='plan right']/div[2]/a/select").click()
Could anyone kindly give me some suggestions? Thanks!!
<div class="choose_plan">
<h1>Sign up now for <strong>UNLIMITED</strong> access <br/>to all </h1>
<div class="plans">
<div class="plan left">
<div class="head">
<p>MONTHLY</p>
</div>
<div class="body">
<p>annually</p>
</div>
<hr />
SELECT
</div>
<div class="plan right">
<img alt="Popular-right" class="popular" src="/assetse8.png" />
<div class="head">
<p>14</p>
</div>
<div class="body">
<p>Unlimited</p>
</div>
<hr />
SELECT
</div>
</div>
</div>
I know you already have an answer but there's a simple alternative that may be helpful in the future. From the HTML you provided, it looks like the data-planId attribute is unique for each A tag. You can take advantage of that using the code below.
driver.find_element_by_css_selector("a[data-planId='31']")
See this CSS Selector reference for more info.
It would help to have well formed HTML, as line 15 (<div class="choose_plan">) appears to be unclosed. This solution below was done with this line removed, but the rest of the HTML as shown. You can test online XPath here.
driver.find_element_by_xpath("//div[#class='plan right']/a").click()
yields the following:
Element='SELECT'
I would try to make it simple:
driver.find_element_by_css_selector("div.right a.select")
Or:
driver.find_elements_by_link_text("SELECT")[-1]
Here we are basically getting the last a element having SELECT text.

Categories