Selenium Webdriver Xpath id random - python

I have a problem,
when I look for the id of an xpath it changes every time I enter the web
how can i use selenium webdriver python
browser.find_element(By.ID,)
if the id changes every time I consult it
first
<span data-dojo-attach-point="containerNode,focusNode"
class="tabLabel" role="tab" tabindex="0"
id="icm_widget_SelectorTabContainer_0_tablist_dcf42e75-1d03-4acd-878c-722cbc8e74ec"
name="icm_widget_SelectorTabContainer_0_tablist_dcf42e75-1d03-4acd-878c-722cbc8e74ec"
aria-disabled="false"
title=""
style="user-select: none;"
aria-selected="true">Search</span>
second
<span data-dojo-attach-point="containerNode,focusNode"
class="tabLabel"
role="tab"
tabindex="0"
id="icm_widget_SelectorTabContainer_0_tablist_c9ba5042-90d2-4932-8c2d-762a1dd39982"
name="icm_widget_SelectorTabContainer_0_tablist_c9ba5042-90d2-4932-8c2d-762a1dd39982"
aria-disabled="false"
title=""
style="user-select: none;"
aria-selected="true">Search</span>
try with
browser.find_element(By.XPATH
browser.find_element(By.ID
browser.find_element(By.NAME
same problem, the id changes

Try to use below xpath
browser.find_element(By.XPATH(//span[contains(#id, 'icm_widget_SelectorTabContainer') and text()='Search']);

In case the first part of the id is unique and stable as it seems to be, you can use XPath or CSS Selector to locate this element.
XPath:
browser.find_element(By.XPATH, "//span[contains(#id,'icm_widget_SelectorTabContainer_0_tablist')]")
CSS Selector:
browser.find_element(By.CSS_SELECTOR, "span[id*='icm_widget_SelectorTabContainer_0_tablist']")

Related

Selenium + Python: Print the text attribute of an element

I would like to navigate through a website, find an element and print it.
Python version: 3.10; Selenium Webdriver: Firefox; IDE: PyCharm 2021.3.2 (CE);
OS: Fedora 35 VM
I am able to navigate to the appropriate page where the text is generated in a drop down menu.
When I locate the element by CSS Selector and attempt to print it, the output does print the text "None".
I would like it to print the Plan Name which in this case is "Dual Complete Plan 1".
The element is not always present so I also need to catch any exceptions.
The relevant HTML code of the element I am trying to print:
<span class="OSFillParent" data-expression="" style="font-size: 12px; margin-top: 5px;">Dual Complete Plan 1</span>
More of the HTML code of the element I am trying to print (element I am trying to capture is below the fourth div):
<td data-header="Plan Name">
<div id="b8-b40-l1_0-132_0-$b2" class="OSBlockWidget" data-block="Content.AccordionItem">
<div id="b8-b40-l1_0-132_0-b2-SectionItem" class="section-expandable open is--open small-accordion" data-container="" data-expanded="true" aria-expanded="true" aria-disabled="false" role="tab">
<div id="b8-b40-l1_0-132_0-b2-TitleWrapper" class="section-expandable-title" data-container="" style="cursor: pointer;" role+"button" aria-hidden="false" aria-expanmded="true" tabindex="0" aria-controls="b8-b40-l1_0-132_0-b2-Content" EVENT FLEX
<div id="b8-b40-l1_0-132_0-b2-Title" class="dividers full-width">
<span class="OSFillParent" data-expression="" style="font-size: 12px; margin-top: 5px;">Dual Complete Plan 1</span>
</div>
<div class="section-expandable-icon" data-container="" aria-hidden="true"
::after
</div>
</div>
<div id="b8-b40-l1_0-132_0-b2-ContentWrapper" class="section-expandable-content no-padding is--expanded" data-container="" tabindex="0" aria-hidden="false" aria-labelledby="b8-b40-l1_0-132_0-b2-TitleWrapper">
<div id="b8-b40-l1_0-132_0-b2-Content" role="tabpanel">
<a data-link="" href="https://www.communityplan.com" target="_blank" title="Click for more information"> EVENT
<span class="OSFillParent" data-expression="" style="font-size: 12px;">www.CommunityPlan.com</span>
</a>
<span class="OSFillParent" data-expression="" style="font-size: 12px:">Phone Number: 8005224700</span>
</div>
</div>
</div>
</div>
</td>
My relevant Selenium code:
# Find the Plan Name & if present set it to the variable "Advantage"
try:
Advantage = (WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#b8-b40-l1_0-132_0-b2-Title > span:nth-child(1)"))).get_attribute("value"))
except:
pass
print('\033[91;46m', Advantage, '\033[0m')
I expect the output to be "Dual Complete Plan 1", which is what I see on the screen and in the HTML. Instead I get the following:
None
Apparently the "Advantage" variable is being set to "None".
Why?
I can see the text "Dual Complete Plan 1" that I want to print in the HTML code above.
What am I doing wrong?
I feel like I need a primer on "get attribute"?
To get the text Dual Complete Plan 1 you need to use
element.text
or
element.get_attribute("innerHTML")
or
element.get_attribute("textContent")
Instead of presence_of_element_located() use visibility_of_element_located()
and following css selector to identify
div[id*='Title'] > span.OSFillParent
Or
div.dividers.full-width > span.OSFillParent
Code:
try:
Advantage = WebDriverWait(driver, 5).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "div[id*='Title'] > span.OSFillParent"))).text
except:
pass
print(Advantage )

Web element not found but appears when inspected manually

I am unable to access this menu in selenium the web element doesn't appear in inspector until manually done
<a id="cke_3275" class="cke_menubutton cke_menubutton__table cke_menubutton_off cke_menubutton__table" href="javascript:void('Table Properties')" title="Table Properties" tabindex="-1" _cke_focus="1" hidefocus="true" role="menuitem" aria-haspopup="false" aria-disabled="false" onmouseover="CKEDITOR.tools.callFunction(666,5);" onmouseout="CKEDITOR.tools.callFunction(667,5);" onclick="CKEDITOR.tools.callFunction(668,5); return false;">
<span class="cke_menubutton_inner">
<span class="cke_menubutton_icon">
<span class="cke_button_icon cke_button__table_icon" style="background-image:url(https://lms.testbook.com/vendor/ckeditor/plugins/icons.png?t=E6FD);background-position:0 -1896px;background-size:auto;">
</span>
</span>
<span class="cke_menubutton_label">
Table Properties
</span>
</span>
</a>
I tried accessing parent, click and actions.perform() nothing seems to work.
When i hover over the menu contents i see javascript:void('contentname'), i pasted this in the inspector and found the web element.
iframe=WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "/html/body/iframe")))
driver.switch_to.frame(iframe)
driver.find_element_by_tagname("a")
switch to iframe and then add rest of the code
driver.switch_to.default_content()
you need to switch to default content after you are done with the element and want to interact with an element outside the iframe

How to get click on 'href' link using selenium

how do i click on the href link: href="/in/x-y-07976b159/" using selenium?
<a data-control-id="SOR2sXWgS8mDhCUEgFncpQ==" data-control-name="search_srp_result" href="/in/x-y-
07976b159/" id="ember1502" class="search-result__result-link ember-view"> <h3 id="ember1503"
class="actor-name-with-distance search-result__title single-line-truncate ember-view"> <span
class="name-and-icon"><span class="name-and-distance">
<span class="name actor-name">x y</span>
<span data-test-distance-badge="" id="ember1504" class="distance-badge separator ember-view">
<span class="visually-hidden">
1st degree connection
</span>
<span class="dist-value">1st</span>
</span>
</span><!----></span>
</h3>
</a>
You can click it with the help of below command.
driver.find_elements_by_xpath("//a[#id='ember1502']").click();
Where driver is the web driver instance.
You can do it both ways.
1) Find this element (eg. by id) and invoke method .click() on it.
2) Go to page (using driver.get(youcurrenturl + yourextracted href))
Another way of doing using find_element_by_idmethod.
driver = webdriver.Chrome()
driver.get('http://www.YourUrl.com')
driver.find_element_by_id('ember1502').click()

Can find element within an iframe using Firefox but not Chrome

So I'm trying to write a test for a webpage which has some elements within an iframe. I've been able to successfully run the test using webdriver.Firefox() without any problems but if I switch it over to webdriver.Chrome() I get a timeout exception on the following lines of code:
self.driver.switch_to.frame(0)
self.activity_status = WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#overview > div.details.w-66 > div > div.duration-and-status > span.status.stat_incomplete#')))
It'd be great to get a solution to this as I'm all out of ideas.
Thanks for your help.
edit, partial html for the page:
<iframe id="iframe_course_details" allowfullscreen="" src="../Course/Details.aspx?HidePageNav=true&IsInIframe=true"></iframe>
Close
Edit (Inactive)
Edit
<span id="ctl00_cph_main_content_area_ucCourseDetails_spn_favourite" class="favourite button tooltipstered" style="display: none;">Favourite</span>
<span id="ctl00_cph_main_content_area_ucCourseDetails_spn_basket_dull" class="add-to-basket button delete tooltipstered" style="display: none;">Enrolled (Remove From Enrolments)</span>
<span id="ctl00_cph_main_content_area_ucCourseDetails_spn_basket" class="add-to-basket button tooltipstered">Add to Enrolments</span>
<span id="ctl00_cph_main_content_area_ucCourseDetails_spn_print" class="print button tooltipstered">Print</span>
</div>
<section id="overview" style="opacity: 1;">
<div id="fullname" class="fullname w-100" style="display: none;">
</div>
<div class="image w-33" style="cursor: pointer;">
<div style="background-image:url(/App_Themes/MainTheme-responsive/Images/Course/webcast.jpg);"></div></div>
<div class="details w-66">
<div class="inner">
<h2>testing activity</h2>
<div class="star-rating-num-ratings">
<div class="star-rating">
<span></span><span></span><span></span><span></span><span></span>
</div>
<span class="num-of-ratings">0 Ratings</span>
</div>
<div class="duration-and-status">
<span class="duration">
<label>
Duration:
</label>
<span>0</span>
</span>
<span class="status stat_incomplete">Started</span>
</div>
Edit 2:
So we've managed to find a solution to this and its even more confusing than the original problem
WebDriverWait(self.driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'iframe_course_details')))
time.sleep(0)
self.activity_status = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, '//*[#id="overview"]/div[3]/div/div[2]/span[2]')))
I'd be really curious to hear some theories on why this works, it times out without the 'time.sleep(0).
If you reference the iframe directly rather then an integer that will work between Firefox/Chrome.
self.driver.switch_to.frame(driver.find_element_by_name("iframe"))
You can find the iframe element any way you wish e.g by css/xpath etc
As the the desired element is within an <iframe> so to invoke click() on the element you have to:
Induce WebDriverWait for the desired frame to be available and switch to it.
Code Block:
# as per your comment assuming -> there is only one frame on the page
WebDriverWait(self.driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.TAG_NAME,"iframe")))
self.element = self.activity_status = WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#overview > div.details.w-66 > div > div.duration-and-status > span.status.stat_incomplete#')))
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Reference
You can find a relevant detailed discussion in:
Ways to deal with #document under iframe

Unable to locate element Selenium webdriver || Python

<div class="container-fluid ">
<div class="navbar-header">
<span id="problem_hide_search" class="nav navbar-left">
<span id="ca660735dba5d3003d7e5478dc9619b2_title" class="list_search_title navbar-text " style="float: left; display:inherit">Go to</span>
<div style="float: left; display:inherit">
<div class="input-group" style="width: 300px;">
<span class="input-group-addon input-group-select">
<label class="sr-only" for="ca660735dba5d3003d7e5478dc9619b2_text">Search</label>
<input id="ca660735dba5d3003d7e5478dc9619b2_text" class="form-control" name="ca660735dba5d3003d7e5478dc9619b2_text" style="width: 150px;" placeholder="Search"/>
</div>
</div>
<script data-comment="widget search load event">addLoadEvent(function () { new GlideWidgetSearch('ca660735dba5d3003d7e5478dc9619b2', 'problem', 'true'); });</script>
Am trying to locate the Search box by switching into iframe and selecting by
search_box = driver.find_element_by_xpath('//*#id="ca660735dba5d3003d7e5478dc9619b2_text"]')
But i get error unable to locate Message: no such element: Unable to locate element:
Even thought I find one matching node.
As you mentioned in your question that you are trying to locate the Search box by switching into iframe and selecting as per the best practices you should :
Induce WebDriverWait for the frame to be available to switch as follows :
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it(By.ID,"id_of_iframe"))
Here you will find a detailed discussion How can I select a html element no matter what frame it is in in selenium?
While you look out for an element within an <iframe> tag induce WebDriverWait with proper expected_conditions. Considering the fact that you intend to send text to the element you can use the following line of code :
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#class='navbar-header']//input[#class='form-control' and contains(#id,'_text')]"))).send_keys("hello")

Categories

Resources