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
Related
I want to use selenium to loop over a few divs on a webpage and find the content of the divs
The basic setup of the webpage looks like this:
<html>
<div data-testid="property-card">
<div data-testid="title">content 1</div>
</div>
<div data-testid="property-card">
<div data-testid="title">content 2</div>
</div>
<div data-testid="property-card">
<div data-testid="title">content 3</div>
</div>
</html>
and here is my code:
def report_results(self):
hotel_boxes = self.find_elements(By.XPATH, '//div[#data-testid="property-card"]')
for hotel in hotel_boxes:
hotel_name = hotel.find_element(By.XPATH, '//div[#data-testid="title"]').get_attribute('innerHTML')
print(hotel_name)
However, the problem is that this only prints "content 1" for three times. What am I doing wrong here?
You are almost there, the only 1 thing you are missing is a dot . at the front of XPath expression.
It should be
hotel_name = hotel.find_element(By.XPATH, './/div[#data-testid="title"]').get_attribute('innerHTML')
When using '//div[#data-testid="title"]' XPath expression it will search for the matching locator from the top of the page until it finds the first match.
While when we have that dot . it means to start searching inside the current node i.e. inside the parent element hotel
So, your entire code can be:
def report_results(self):
hotel_boxes = self.find_elements(By.XPATH, '//div[#data-testid="property-card"]')
for hotel in hotel_boxes:
hotel_name = hotel.find_element(By.XPATH, './/div[#data-testid="title"]').get_attribute('innerHTML')
print(hotel_name)
As per the given HTML:
<html>
<div data-testid="property-card">
<div data-testid="title">content 1</div>
</div>
<div data-testid="property-card">
<div data-testid="title">content 2</div>
</div>
<div data-testid="property-card">
<div data-testid="title">content 3</div>
</div>
</html>
To print the innerText of the descendant <div> tags you can use list comprehension and you can use either of the following locator strategies:
Using CSS_SELECTOR and text attribute:
print([my_elem.text for my_elem in driver.find_elements(By.CSS_SELECTOR, "div[data-testid='property-card'] > [data-testid='title']")])
Using XPATH and .get_attribute('innerHTML'):
print([my_elem..get_attribute('innerHTML') for my_elem in driver.find_elements(By.XPATH, "//div[#data-testid='property-card']/div[#data-testid='title']")])
XPATH newbie... I am trying to find text, then find the following button in a code block like below.
The ember numbers change so can't use those. Need to find text within a span, then the next (following) button after that text is found. Then click on that button. In this case it's a contact button.
I've tried:
//*[text()[contains(.,'Jason')]]/div/div/button
Also tried:
//*[text()[contains(.,'Jason')]]/following-sibling::button
A code block example I am trying to search.
<div data-test="e-list-item" data-e-id="Fdh348uF" class="material-list-tile e-list-item">
<div class="e-name">
<a href="/embed/Gdfsdjfhd25d88/gallery/Fdh348uF" id="ember2539" class="ember-view"> <span data-test="e-name">Jason Alamoa</span>
</a><!----> </div>
<!----> <div id="ember2539" class="c-info ember-view"> <div class="c-icons">
<!---->
<!---->
<!---->
<!---->
</div>
</div>
<div class="e-actions">
<div class="e-action-buttons">
<!----> <div class="e-action">
<button class="ssButton ssButtonPrimary v-button v " type="button" data-ember-action="" data-ember-action-2540="2540">
<i class="ssIcon-ok-sign ssIcon-large"></i>
Contact
</button>
<!---->
</div>
</div>
</div>
</div>
Based on HTML snippet provided following XPath could be used:
//div[./a/span[contains(.,'Jason')]]/following::div[#class="e-actions"]//button
Explanation:
//div[./a/span[contains(.,'Jason')]] => selects "div" with child "a" containing child "span" containing text "Jason"
/following::div[#class="e-actions"] => selects following "div" after the first one having attribute "class" with value "e-actions"
//button => selects "button" inside of the previous "div"
If you want to find span with specific text and following button, the easiest way
//span[contains(text(), 'Jason')]/following::button
So here is the following HTML code
<div>
<div id='parent-1'>
<div classname="fiasd">
<div classname="ehuh">
<div classname ="target-me-1">
</dv>
</div>
</div>
</div>
<div id='parent-1'>
<div classname="fiasd">
<div classname="ehuh">
<div classname ="target-me-1">
</dv>
</div>
</div>
</div>
<div id='parent-1'>
<div classname="fiasd">
<div classname="ehuh">
<div classname ="target-me-1">
</dv>
</div>
</div>
</div>
</div>
MY APPROACH
I am using selenium to find all the elements with classname="parent-1" which gives me a list of 3 elements. Now what I want to do is target the element 'target-me-1' using the reference from the parent element.
As in I want to find 'target-me-1' element within and only within the specific 'parent-1' elements.
Is it possible to find an element only within a selected element?
elements found in browser are also searchable
from selenium import webdriver
URL = 'url'
browser = webdriver.Chrome()
browser.get(URL)
lst = browser.find_elements_by_id("parent 1")
for parent in lst:
target = parent.find_element_by_class_name("target-me-1")
# print(target.text)
I am using BeautifulSoup.
I would like to extract a coordinates from the website. The code of web looks like:
<a class="button button--outline link link--emphasis button-full-width js-choose-store" href="/sklep?StoreID=R034" title="Informacje o sklepie">Informacje o sklepie</a>
</div>
</div>
</div>
</div>
<div class="storelist__item ui-expandable js-accordion-store js-store" data-lat="52.225155" data-lng="20.998965" data-icon="/on/demandware.static/Sites-Hebe-Site/-/default/dw081970e9/images/map_markers/hebe.png" data-id="R379" data-coming-soon="false" data-index="81">
<div class="visually-hidden" data-popup-html>
<div class="store-popup">
<div class="store-popup__name text--uppercase">Drogeria Hebe</div>
<div class="store-popup__address">Lindleya 16</div>
<div class="store-popup__city">Warszawa, 02-013</div>
<div class="store-popup__directions">
I need to get 'data-lat' and 'data-lng'.
I had no problem to get address or name of object (it was a text), using for example:
find("div",{"class","store-popup__city"}).text
Try something along the lines of:
dat = soup.select_one('div[data-lat]')
print(dat['data-lat'],dat['data-lng'])
Output:
52.225155 20.998965
I have recently started using selenium with python and stuck with the below problem. It may be simple but I have tried a lot while searching through different answers but could not solve it.
I want to click the 2nd text box with class name 'param-text-input text-input numeric-value'
<div class="bet-widget-main-row-right">
<div class="bet-widget-main-content">
<div class="bet-params">
<div class="param-wrapper">
<span class="param-label">Label1</span>
<div class="param-input -desktop">
<div class="param with-error">
<span class="param-input-wrapper">
<span class="param-currency numeric-value">£</span>
<input type="text" class="param-text-input text-input numeric-value" value=".04" tabindex="0" size="3" maxlength="11">
</span>
</div>
<div class="param-input_ticks"></div>
</div>
</div>
<div class="param-wrapper">
<span class="param-label">Label2</span>
<div class="param-input -desktop">
<div class="param">
<span class="param-input-wrapper">
<input type="text" class="param-text-input text-input numeric-value" value="2.18" tabindex="0" size="4" maxlength="8">
</span>
</div>
<div class="param-input_ticks"></div>
</div>
</div>
</div>
</div>
<div class="bet-submit"><button class="confirm-bet-button -accented micro-button" type="submit" disabled="" tabindex="0"><span>Button1</span></button></div></div>
I have tried multiple solutions but none work:
self.driver.find_element_by_xpath("//[#class='param-text-input.text-input.numeric-value'][2]").clear()
self.driver.find_element_by_css_selector("[input.param-text-input.text-input.numeric-value][2]").clear()
self.driver.find_element_by_xpath("//input[#class='param-text-input'][2]").clear()
Any pointers/help is appreciated.
In the case that you would prefer to use a CSS selector, the following will choose that second input:
div.param-wrapper:nth-of-type(2) input.param-text-input.text-input.numeric-value
we're looking for the second "param-wrapper" because that is the thing which will correctly count the parameters.
It's pretty easy:
self.driver.find_elements_by_xpath('//input[#Class="param-text-input.text-input.numeric-value"]')[1].clear()
or
from selenium.webdriver.common.keys import Keys
self.driver.find_elements_by_xpath('//input[#Class="param-text-input.text-input.numeric-value"]')[1].send_keys(Keys.BACKSPACE)
You need to make an object list in the first place. So you should find all the placeholders with the same name. Then get said item, which is the second element(list are zero based, so 1 is second)
Cheers
It is possible in XPath to select the n-th object that corresponds to your XPath expression.
To achieve this you use the [n] at the end of of your expression.
What you forgot is to put () around your expression before adding the [n].
So your XPath should be (//input[#class='param-text-input'])[2].
To click the 2nd text box with class name 'param-text-input text-input numeric-value' you can use the following code block :
self.driver.find_element_by_xpath("//div[#class='bet-params']//following-sibling::input[2]").clear()