Get the buttons number - python

This is my HTML code. I am using selenium.
<button class= "message-anywhere-button mn-connection-card__message-btn button-secondary-medium" aria-label="hello" data-ember-action="" data-ember-action-62="62">
<span aria-hidden="true"> Msg</span>
<span class="visually-hidden"> hello</span>
I have a list of more buttons like this one, and I need to get the number of the "Msg" Buttons.
driver = webdriver.Firefox()
message=drive.find_element_by_WHAT? (I tried id, class,css selector,but no one worked..)

If the same classname is present more than once.Try using find_elements and then count the length.
print(len(driver.find_elements_by_css_selector(".button-secondary-medium")))
Or try with area-lable if it is exists more than once.
print(len(driver.find_elements_by_xpath("//button[#aria-label='hello']")))

Related

Is there a way to select an item on a webpage with Selenium with no unique ID?

My objective is to open a webpage, and click the app button for a specific app, like Anaplan. In the past, I've used get element by CSS selector with the combination of class, and ID, as shown in this past post.
first_item = driver.find_element_by_id("anaplan")
I've come across a webpage where the buttons seem to have literally no ID whatsoever, or unique values:
HTML output of the Anaplan App button:
<a
aria-label="launch app Anaplan"
class="chiclet a--no-decoration"
data-se="app-card"
href="https://gartner.okta.com/home/anaplan/0oaforg08lyATdLuw4x6/2487"
draggable="true"
><article class="chiclet--article">
<button
class="chiclet--action"
tabindex="0"
aria-label="Settings for Anaplan"
data-se="app-card-settings-button"
>
<svg
class="chiclet--action-kebab"
width="20"
height="4"
viewBox="0 0 20 4"
fill="#B7BCC0"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="2" cy="2" r="2"></circle>
<circle cx="10" cy="2" r="2"></circle>
<circle cx="18" cy="2" r="2"></circle>
</svg>
</button>
<section class="chiclet--main" data-se="app-card-main">
<img
class="chiclet--main-logo"
src="https://ok11static.oktacdn.com/fs/bcg/4/gfs1ev15ab63zqgZ91d8"
alt="Anaplan logo"
/>
</section>
<footer class="chiclet--footer" data-se="app-card-footer">
<o-tooltip content="Anaplan" position="bottom" class="hydrated"
><div slot="content"></div>
<div aria-describedby="o-tooltip-0">
<h1 class="chiclet--app-title" data-se="app-card-title">Anaplan</h1>
</div>
</o-tooltip>
</footer>
</article>
</a>
I grabbed the Xpath of the Anaplan button, which shows the following:
/html[#class='hydrated wf-proximanova-n4-inactive wf-
inactive']/body[#class='default']/div[#id='root']
/div[#class='enduser-app ']/section[#class='content-frame']
/main[#class='main-container has-top-bar']/div[#class='dashboard--main']/section[#id='main-
content']/section[#class='chiclet-area']
/section[#class='chiclet-grid--container']
/section/section[#class='chiclet-grid section-appear-done section-enter-done']
/a[#class='chiclet a--no-decoration'][1]/article[#class='chiclet--article']
The only differences between apps is the number in the bracket:
/a[#class='chiclet a--no-decoration'][1], where 1 seems to be Anaplan, 3 is G Drive, and so on. Is there a way to select elements such as this where there appears to be no unique identifier at all?
To locate the first button you can use one of the following xpaths //a[#aria-label='launch app Anaplan'] or //a[contains(#href,'anaplan')] and there are many other unique combinations. The same can be done with css selectors
Similarly to the above there are several combinations for all the other navigation buttons you provided here.
In case the element located inside <iframe> you have to switch to that <iframe> first and get out of it after that.
Locate the <iframe> with
iframe = driver.find_element_by_xpath("//iframe[#name='iframeName']") or whatever locator that it matches
Then switch_to the <iframe>:
driver.switch_to.frame(iframe)
If after that you need to continue anywhere out of the <iframe> switch out of it with
driver.switch_to.default_content()
It is possible both with xpath and css.
Example of xpath:
Anaplan:
//a[contains(#aria-label, 'Anaplan')]/article/button
Or:
//button[contains(#aria-label, 'Settings for Anaplan')]
Spam Quarantine:
//a[contains(#aria-label, 'Spam Quarantine')]
G-suite
//a[contains(#aria-label, 'G Suite Drive')]
The main idea is that you can find an element by writing a partial name of an attribute.
Update:
If an element is located inside an iframe, you should wait for it to load and switch to it. Selenium has very convenient method for it: frame_to_be_available_and_switch_to_it
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
driver = webdriver.Chrome()
driver.get(url)
wait = WebDriverWait(driver, 15)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[data-testid=shell-content]")))
After switching to iframe you work with elements inside it.

Using Python 3.7 and Webdriver, how do I find a specific button inside a "<li", which is in turn found inside a "<div" element?

I am including portions of the HTML below. I believe I have found the larger element using the command:
driver.find_element_by_xpath('//div[#id="day-number-4"]')
That div ID is unique on the web page, and the command above did not create an exception nor error.
The HTML code that defines that element is:
<div id="day-number-4" class="c-schedule-calendar__class-schedule-content tabcontent js-class-schedule-content u-is-none u-is-block" data-index="3">
Now, the hard part. Inside that div element are a number of "<li"'s that take the form of:
<li tabindex="0" class="row c-schedule-calendar__class-schedule-listitem-wrapper c-schedule-calendar__workout-schedule-list-item" data-index="0" data-workout-id="205687" data-club-id="229">
and then followed a clickable button in this format:
<button class="c-btn-outlined class-action" data-class-action="book-class" data-class-action-step="class-action-confirmation" data-workout-id="205687" data-club-id="229" data-waitlistable="true"><span class="c-btn__label">Join Waitlist</span></button>
I always want to click on the 3rd button inside that <div element. The only thing unique would be the data-index, which starts at 0 for the 1st <li", and 2 for the 3rd So I want to find the clickable button that will follow this HTML code:
<li tabindex="0" class="row c-schedule-calendar__class-schedule-listitem-wrapper c-schedule-calendar__workout-schedule-list-item" data-index="2" data-workout-id="206706" data-club-id="229">
I cannot search on data-index as "data-index="2"" appears many times on the web page.
How do I do this?
I answered my own question. I used multiple searches within the specific element using this code:
Day_of_Timeslot = driver.find_element_by_xpath('//div[#id="day-number-4"]')
Precise_Timeslot = Day_of_Timeslot.find_element_by_xpath(".//li[#data-index='1']")
Actual_Button = Precise_Timeslot.find_element_by_xpath(".//button[#data-class-action='book-class']").click()

How locate the pseudo-element ::before using Selenium Python

I'm using Selenium Python to locate label element.I want to use ::before to locate it,because this is a pop window.
<div class="crow" grp="0" grpname="Pizza Size">
::before
<label class="label0" cid="1">
<input type="radio" name="0" coname="M" sname="" price="9.99" value="392">M<b class="ip">9.99</b>
</label>
<label class="label0" cid="1"><input type="radio" name="0" coname="L" sname="" price="11.99" value="393">L<b class="ip">11.99</b>
</label><div style="clear:both">
</div>
</div>
I have no idea how to use ::before to locate it,any friend can help?
Pseudo Elements
A CSS pseudo-element is used to style specified parts of an element. It can be used to:
Style the first letter, or line, of an element
Insert content before, or after, the content of an element
::after
::after is a pseudo element which allows you to insert content onto a page from CSS (without it needing to be in the HTML). While the end result is not actually in the DOM, it appears on the page as if it is, and would essentially be like this:
CSS:
div::after {
content: "hi";
}
::before
::before is exactly the same only it inserts the content before any other content in the HTML instead of after. The only reasons to use one over the other are:
You want the generated content to come before the element content, positionally.
The ::after content is also "after" in source-order, so it will position on top of ::before if stacked on top of each other naturally.
Demonstration of extracting properties of pseudo-element
As per the discussion above you can't locate the ::before element within the DOM Tree but you can always be able to retrieve the contents of the pseudo-elements, i.e. ::before and ::after elements. Here's an example:
To demonstrate, we will be extracting the content of ::after element (snapshot below) within this website:
Code Block:
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options, executable_path=r'C:\WebDrivers\chromedriver.exe')
driver.get('https://meyerweb.com/eric/css/tests/pseudos-inspector-test.html')
script = "return window.getComputedStyle(document.querySelector('body>p.el'),':after').getPropertyValue('content')"
print(driver.execute_script(script).strip())
Console Output:
" (fin.)"
This console output exactly matches the value of the content property of the ::after element as seen in the HTML DOM:
This usecase
To extract the value of the content property of the ::before element you can use the following solution:
script = "return window.getComputedStyle(document.querySelector('div.crow'),':before').getPropertyValue('content')"
print(driver.execute_script(script).strip())
Outro
A couple of relevant documentations:
Document.querySelector()
Window.getComputedStyle()
If I am not wrong, then, selenium doesn't provide any function or API call for this.
You can try parsing the html and then finding the tag using a simple regular expression.
Hope this helps :)

How can i click the element on webpage using selenium with python

HTML information is :
<a title="Create an Account" class="button" href="http://demo.magentocommerce.com/customer/account/create/">
<span>
<span>Create an Account
</span>
</span>
</a>
Create an Account
I am trying with :
create_account_button = driver.find_element_by_xpath("//button[#title='Create an Account']")
create_account_button.click()
but it is not working
Actually assign the WebElement variable, u use the following code
WebElement button = driver.findElement(By.xpath("//a[#title='Create an Account']");
button.click();
Steps
Creating a WebElement variable button and assigning the value to it.
Performing click() on that webelement
For Java follow above steps, for Python use below
driver.find_element_by_xpath('//a[#title='Create an Account']').click()
Xpath you need To use be in <a> not in <button>
So try this Xpath //a[#title='Create an Account']

Is it possible to select button with only class values in Selenium Python?

Is it possible to select button with only class values in Selenium Python?
The html is as follows:
<button class="secondary option-action ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false"
from selenium import webdriver
browser = webdriver.Firefox()
browser.get(any_url)
Any idea to select that button?
Yes, it is possible.
Use find_element_by_class_name (or find_elements_by_class_name to get multiple matched elements):
browser.find_element_by_class_name('secondary')
You can also use find_element_by_css_selector (or ..s variant):
browser.find_element_by_css_selector('.secondary')
Alternatively you can also use find_element_by_xpath, but it requires a verbose xpath expression to be precise:
xpath = "descendant-or-self::*[#class and contains(concat(' ', normalize-space(#class), ' '), ' secondary ')]"
browser.find_element_by_xpath(xpath)
you can use css selctors:
driver.find_element_by_css_selector(".secondary")
multiple classes:
driver.find_element_by_css_selector(".secondary.option-action.ui-button.ui-widget")
you can also use:
driver.find_element_by_css_selector("[role=button]")
in case theres multiple buttons with the same classes you can do this:
<div id="button-is-here">
<button class="secondary option-action ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false">
</div>
driver.find_element_by_css_selector("#button-is-here .secondary.option-action.ui-button.ui-widget")
If you only use classes most likely there will be another button in the page with the same classes so sometimes you have to be more specific
I'll give you a similar answer to the one I gave you on your previous question:
browser.find_element_by_xpath('//input[#class="secondary option-action..."]').click()
You'll have to fill the ... yourself though, or instead, use:
browser.find_element_by_xpath('//input[starts-with(#class,"secondary option")]').click()
If you don't have any other input element whose class attribute starts with "secondary option"...

Categories

Resources