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
Related
I can't select values in a list. I tried using find_element_by_class_name() to open the menu but when I need to select a <li> returns that element doesn't have a function click().
Here the code:
click_menu = driver.find_element_by_class_name("periodSelector")
click_menu[1].click()
Here is the HTML that I am trying to parse:
<div data-period-selector="" data-period="periodFilter">
<div class="periodSelectorContainer">
<div class="btn-group periodSelector">
<button class="flat-btn dropdown-toggle periodToggle ng-binding" data-toggle="dropdown"> 20/02/2021 - 22/03/2021 <span class="dropdown-arrow"></span> </button>
<ul class="dropdown-menu">
<li>
<a href="javascript:void(0);" class="new-financ" ng-click="selectToday()"><i></i>
<span class="pull-left">Hoje</span>
<span class="pull-right"></span>
</a>
</li>
<li>
<a href="javascript:void(0);" class="new-financ" ng-click="selectThisWeek()"><i>
</li>
There are multiple class names you have to use a css selector.
click_menu = driver.find_element_by_css_selector("button.flat-btn.dropdown-toggle.periodToggle.ng-binding")
click_menu.click()
Clicks 1st li tag.
driver.find_element_by_xpath("ul[#class='dropdown-menu']/li[1]").click()
periodSelector is a class on a DIV
<div class="btn-group periodSelector">
I'm assuming that you need to click on the BUTTON
<button class="flat-btn dropdown-toggle periodToggle ng-binding" data-toggle="dropdown">
Most of those classes seem generic (probably not unique) but I'm guessing that periodToggle might be unique given the date range. Try
driver.find_element_by_css_selector("button.periodToggle").click()
NOTE:
You have an error in your code. You are using .find_element_by_class_name() (singular) but have array notation on the next line, click_menu[1]. In this case, you can just use click_menu.click(). You'd only need the array notation if you were using .find_elements_by_*() (note the plural, elements).
<div class="class-one">
<div class="class-two">
sample text
<div class="class-three">
<i class="fal fa-fw fa-file-word"></i><span class="button__title">search</span>
</div>
</div>
</div>
When i do driver.find_elements_by_css_selector('div.class-two') it prints sample text and search too, how can i get only sample text using selenium in python?
You need only write "text" in end.
driver.find_element_by_css_selector('div.class-two').text
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()
I'm trying to collect the text using Bs4, selenium and Python I want to get the text "Lisa Staprans" using:
name = str(profilePageSource.find(class_="hzi-font hzi-Man-Outline").div.get_text().encode("utf-8"))[2:-1]
Here is the code:
<div class="profile-about-right">
<div class="text-bold">
SF Peninsula Interior Design Firm
<br/>
Best of Houzz 2015
</div>
<br/>
<div class="page-tags" style="display:none">
page_type: pro_plus_profile
</div>
<div class="pro-info-horizontal-list text-m text-dt-s">
<div class="info-list-label">
<i class="hzi-font hzi-Ruler">
</i>
<div class="info-list-text">
<span class="hide" itemscope="" itemtype="http://data-vocabulary.org/Breadcr
umb">
<a href="http://www.houzz.com/professionals/c/Menlo-Park--CA" itemprop="url
">
<span itemprop="title">
Professionals
</span>
</a>
</span>
<span itemprop="child" itemscope="" itemtype="http://data-vocabulary.org/Bre
adcrumb">
<a href="http://www.houzz.com/professionals/interior-designer/c/Menlo-Park-
-CA" itemprop="url">
<span itemprop="title">
Interior Designers & Decorators
</span>
</a>
</span>
</div>
</div>
<div class="info-list-label">
<i class="hzi-font hzi-Man-Outline">
</i>
<div class="info-list-text">
<b>
Contact
</b>
: Lisa Staprans
</div>
</div>
</div>
</div>
Please let me know how it would be.
I assumed you are using Beautifulsoup since you are using class_ attribute dictionary-
If there is one div with class name hzi-font hzi-Man-Outline then try-
str(profilePageSource.find(class_="hzi-font hzi-Man-Outline").findNext('div').get_text().split(":")[-1]).strip()
Extracts 'Lisa Staprans'
Here findNext navigates to next div and extracts text.
I can't test it right now but I would do :
profilePageSource.find_element_by_class_name("info-list-text").get_attribute('innerHTML')
Then you will have to split the result considering the : (if it's always the case).
For more informations : https://selenium-python.readthedocs.org/en/latest/navigating.html
Maybe something is wrong with this part:
find(class_="hzi-font hzi-Man-Outline")
An easy way to get the right information can be: right click on the element you need in the page source by inspecting it with Google Chrome, copy the xpath of the element, and then use:
profilePageSource.find_element_by_xpath(<xpath copied from Chorme>).text
Hope it helps.
I'm writing scripts in Python using Selenium WebDriver to test a web application.
The web application allows users to ask questions, which are added to a div as they are asked. Each question div has their own "upvote" and "downvote" link/image. The image changes when the "upvote" icon is clicked, from active to inactive, or vice versa. I know that the xpath to this upvote icon is:
"//div[#id='recent-questions-container']/div/div/div/div/div[2]/div/ul/li/a/i"
This "i" at the end of the path is a class, and will either be
<i class="fa fa-2x fa-thumbs-o-up"></i>
or
<i class="fa fa-2x fa-thumbs-up clicked"></i>
depending on whether or not it is clicked. I want to verify that the correct image is in place upon being clicked. How can I do that? Ideally, I'd like to perform this verification using assertions, a la:
self.assertTrue(self.is_element_present( ... ))
Here is the html for what I'm talking about
<div id="recent-questions-container">
<div question_id="randomly generated blah" class="q row recent-question animated pulse" data-score="0">
<div class="col-xs-12">
<div class="question-content">
<p>3</p>
<div class="row question-controls">
<div class="owner-view hidden">
...
<div class="student-view">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 question-controls-left">
<ul class="list-inline">
<li>
<a href="#" class="student-view thumbs-up-to-active">
<i class="fa fa-thumbs-o-up fa-2x"></i></a>
</li>
<li>
<span class="num-votes">0</span>
</li>
<li class="thumbs-down-li">
<a href="#" class="student-view thumbs-down-to-active">
<i class="fa fa-thumbs-o-down fa-2x"></i></a>
</li>
</ul>
</div>
</div>
</div>
<hr>
</div>
</div>
</div>
... other questions ...
</div>
<hr>
</div>
</div>
</div>
</div>
You can use get_attribute to get the class attribute and then do a search if the class contains clicked to make sure it was in fact clicked
#make sure the selector is correct
xpath = "//div[#id='recent-questions-container']/div/div/div/div/div[2]/div/ul/li/a/i"
element = driver.find_element(By.XPATH, xpath)
attr = element.get_attribute('class')
if 'clicked' in attr:
print("clicked")
else:
print("was not clicked")
Edit
I would click the element and now should be expecting to change the class to active. Then find the count which should be more than 0
driver = self.driver
#perform click here
#the idea is to avoid the NoSuchElement exception
# and see if the element count is greater than 0
assert (len(driver.find_elements_by_css_selector(".student-view.thumbs-up-to-active")) > 0)