How I can select previous element in Selenium based of condition after? - python

I have a bellow HTML:
<div class="row">
<div><span class="checkbox"></span></div>
<a title="something"></div>
</div>
<div class="row">
<div><span class="checkbox"></span></div>
<a title="somethingelse"></div>
</div>
I would like to click on the checkbox if the a's title is something. I do not know how many rows are there so I need to check every row and if there the title == 'something' click the previous checkbox.
I tried to implement this in Python and Selenium, but so far could not succeed. I can check for a like:
driver.find_element_by_xpath(f"//div[contains(#class, 'row')]//a[#title='something']")
But how I can select the previous element?
Does anybody have a recommendation?

I am using get_attribute and trying to extract title and then putting a if clause that if title attribute text matches with your expected string then click on the above check box.
try this :
actual_text = driver.find_element_by_xpath(f"//div[contains(#class, 'row')]//a[#title='something']")
if actual_text.get_attribute('title') == 'your expected string here':
driver.find_element(By.XPATH, "//div[contains(#class, 'row')]//a[#title='something']/../child::span")

Try this:
driver.find_element_by_xpath("//div[#class='row']/a[#title='something']/..//span[#class='checkbox']").click()

Related

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..

How can I find an element looping through a list of divs using Selenium?

In an HTML file structured like this:
<div class="card">
<div class="id">
ID: 123456
</div>
<div class="title">
Title 1
</div>
<div class="description">
Description 1
</div>
</div>
<div class="card">
<div class="id">
ID: 89123
</div>
<div class="title">
Title 2
</div>
</div>
Let's say that I have a variable number of divs with the class "card", using Selenium I would like to loop through these divs and if there is div with the class description, I would like to print his text.
I tried to do something like code below, but using find_element_by_xpath. I will always get the first element that has the class "description". How can I fix this and properly-getting elements by looping through divs? Thanks a lot.
cards = webdriver.find_elements_by_xpath("//div[#class='main-div']")
for card in cards:
try:
description = card.find_element_by_xpath("//div[#class='description']")
print(description.text)
except:
print("No description")
You need to get all divs with class "card" and search the div "description" inside them:
cards = webdriver.find_elements_by_css_selector(".card")
for card in cards:
try:
description = card.find_element_by_css_selector(".description")
print(description.text)
except:
print("No description.")
PS: Or change your first XPath to //div[#class='card'] and second XPath to .//div[#class='description'] as proposed guys from another answers.
I hope it helps you!
Just use . for intermediate child tag.So it should be like that
card.find_element_by_xpath(".//div[#class='description']")
Code here:
cards = webdriver.find_elements_by_xpath("//div[#class='card']")
for card in cards:
try:
description = card.find_element_by_xpath(".//div[#class='description']")
print(description.text)
except:
print("No description")
You can do this with one locator and a single loop.
for description in driver.find_elements_by_css_selector("div.card > div.description"):
print(description.text)
NOTE: If you want a fix for your current code, you are just missing the self . axis in your second XPath. Change "//div[#class='description']" to ".//div[#class='description']" to indicate that you want to start searching at the current card element.
For more info on the self axis, see mdn which has a lot of great XPath and CSS selector related info.

Clicking button within span with no ID using Selenium

I'm trying to have click a button in the browser with Selenium and Python.
The button is within the following
<div id="generate">
<i class="fa fa-bolt"></i>
<span>Download Slides</span>
<div class="clear"></div>
</div>
Chrome's dev console tells me the button is within <span> but I have no idea how to reference the button for a .click().
Well, if you just want to click on an element without an id or name, I'd suggest three ways to do it:
use xpath:
driver.find_element_by_xpath('//*[#id="generate"]/span')
use CSS selector:
driver.find_element_by_css_selector('#generate > span')
Just try .find_element_by_tag_name() like:
driver.find_element_by_id('generate').find_elements_by_tag_name('span')[0]
Note that this way first try to get the generate <div> element by it's id, and then finds all the <span> elements under that <div>.
Finally, gets the first <span> element use [0].

Python Selenium Webdriver - Grab div after specified one

I am trying to use Python Selenium Firefox Webdriver to grab the h2 content 'My Data Title' from this HTML
<div class="box">
<ul class="navigation">
<li class="live">
<span>
Section Details
</span>
</li>
</ul>
</div>
<div class="box">
<h2>
My Data Title
</h2>
</div>
<div class="box">
<ul class="navigation">
<li class="live">
<span>
Another Section
</span>
</li>
</ul>
</div>
<div class="box">
<h2>
Another Title
</h2>
</div>
Each div has a class of box so I can't easily identify the one I want. Is there a way to tell Selenium to grab the h2 in the box class that comes after the one that has the span called 'Section Details'?
If you want grab the h2 in the box class that comes after the one that has the span with text Section Details try below xpath using preceding :-
(//h2[preceding::span[normalize-space(text()) = 'Section Details']])[1]
or using following :
(//span[normalize-space(text()) = 'Section Details']/following::h2)[1]
and for Another Section just change the span text in xpath as:-
(//h2[preceding::span[normalize-space(text()) = 'Another Section']])[1]
or
(//span[normalize-space(text()) = 'Another Section']/following::h2)[1]
Here is an XPath to select the title following the text "Section Details":
//div[#class='box'][normalize-space(.)='Section Details']/following::h2
yeah, you need to do some complicated xpath searching:
referenceElementList = driver.find_elements_by_xpath("//span")
for eachElement in referenceElementList:
if eachElement.get_attribute("innerHTML") == 'Section Details':
elementYouWant = eachElement.find_element_by_xpath("../../../following-sibling::div/h2")
elementYouWant.get_attribute("innerHTML") should give you "My Data Title"
My code reads:
find all span elements regardless of where they are in HTML and store them in a list called referenceElementList;
iterate all span elements in referenceElementList one by one, looking for a span whose innerHTML attribute is 'Section Details'.
if there is a match, we have found the span, and we navigate backwards three levels to locate the enclosing div[#class='box'], and find this div element next sibling, which is the second div element,
Lastly, we locate the h2 element from its parent.
Can you please tell me if my code works? I might have gone wrong somewhere navigating backwards.
There is potential difficulty you may encounter, the innerHTML attribute may contain tab, new line and space characters, in that case, you need regex to do some filtering first.

How to click on checkbox using selenium? (python)

I'm trying to figure out the answer to a problem I've recently discovered. I have some HTML as indicated below and what I want to do, is send an HTML snipped to selenium so it can click on the checkbox. However, I don't want to lookup by id because as you can see, the id is ugly. Instead, I am looking for an alternative method.
HTML:
<li class= "zone odd open night">...</li>
<li class= "zone even open night">...</li>
<li class= "zone odd open night">...</li>
<label for="srr-2-1397538000">Room 226 1:00 AM</label>
<input type="checkbox" name="srr-2-1397538000" id="srr-2-1397538000" value="Y" class="interactive">
<span class-"drag-handle">...</span>
</li>
<li class="zone even open night">...</li>
As you can see, I'm trying to lookup that specific checkbox to click but I don't want to do it by looking up via id. I would rather look up by "Room" or something more generic.
Does anyone have any suggestions as to how to do this? With using selenium, or some other webdriver?
Also, I've tried the classic:
element = driver.find_element_by_id("srr-2-1397538000")
element.click()
But as I said, this is not what I want.
Thank You
Can you use the tag name?
element = driver.find_element_by_tag_name('input')
element.click()
If you want to look it up by Room, you can use xpath:
element = driver.find_element_by_xpath("//label[contains(text(),'Room')]/following-sibling::input")
element.click()

Categories