Unable to locate element error while trying to locate an input box element using Selenium through Python - python-3.x

I´m trying to find a text box with Python and Selenium.. I Tried by_css_selector, bY XPATH, by ID, by name but the message is always the same:
Unable to locate element: #x-auto-225-input
this is the piece of html. I Want to find the textbox to fill it.
<td class="x-table-layout-cell" role="presentation" style="padding: 2px;">
<div role="presentation" class=" x-form-field-wrap x-component" id="x-auto-225" style="width: 150px;"></div>
<input type="text" class=" x-form-field x-form-text " id="x-auto-225-input" name="PURCHASE_ORDER_CODE_NAME" tabindex="0" style="width: 150px;">
</td>
My last attempt was:
pc = browser.find_element_by_css_selector("#x-auto-225-input").click()
pc.send_keys("7555425-1")

Looking at the html, id mentioned can be dynamic, so you can't put the static id in your identifier.
However, as name attribute is present in the html, you can use that to identify your element, like:
browser.find_element_by_name("PURCHASE_ORDER_CODE_NAME").click()
Updated answer as per discussion with the OP
As an iframe is present on the UI, you need to first switch to the iframe and then click on the element.
To switch to iframe you can use:
browser.switch_to.frame(browser.find_element_by_tag_name('iframe'))
and then use:
pc = browser.find_element_by_name("PURCHASE_ORDER_CODE_NAME")
pc.click()
pc.send_keys("7555425-1")
if you want to switch back to the default content, you can use:
browser.switch_to.default_content()

The desired element is a dynamic element so to invoke click() on the element you have to induce WebDriverWait for the element to be clickable and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input.x-form-field.x-form-text[id$='-input'][name='PURCHASE_ORDER_CODE_NAME']"))).click();
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#class=' x-form-field x-form-text ' and contains(#id,'-input')][#name='PURCHASE_ORDER_CODE_NAME']"))).click();
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

Maybe you can try another "selector" approach. Ex(Javascript):
selenium.By.xpath('//*[#data-icon="edit"]')
driver.findElement(by).click()

Related

ElementNotInteractableException: Message: element not interactable: [object HTMLDivElement] has no size and location error using Selenium and Python

I am trying to click show results button after selecting filter on linkedin. I have correctly found the button element but it is giving me this error:
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable: [object HTMLDivElement] has no size and location
Here is my piece of code that I have tried:
element = WebDriverWait(self, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div[class="artdeco-hoverable-content__shell"]')))
box = self.find_element_by_css_selector('div[class="artdeco-hoverable-content__shell"]')
ele = box.find_element_by_css_selector('button[data-control-name="filter_show_results"]')
ActionChains(self).move_to_element(ele).click(ele).perform()
I have also tried:
self.execute_script("arguments[0].click();", ele)
What's the reason behind this?
HTML of the results button:
<div class="reusable-search-filters-buttons display-flex justify-flex-end mt3 ph2">
<button data-test-reusables-filter-cancel-button="true" data-control-name="filter_pill_cancel" aria-label="Cancel Locations filter" id="ember429" class="artdeco-button artdeco-button--muted artdeco-button--2 artdeco-button--tertiary ember-view" type="button"><!---->
<span class="artdeco-button__text">
Cancel
</span></button>
<button data-test-reusables-filter-apply-button="true" data-control-name="filter_show_results" aria-label="Apply current filter to show results" id="ember430" class="artdeco-button artdeco-button--2 artdeco-button--primary ember-view ml2" type="button"><!---->
<span class="artdeco-button__text">
Show results
</span></button>
</div>
Edit 2: Here is the image of the button , I am trying to click.
https://ibb.co/4Y7VN0j
Edit 3: Image with dev tools open : https://ibb.co/CJdtNM1
The desired element is a Ember.js enabled element, so to click on the Show results button instead of presence_of_element_located() you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-control-name='filter_show_results'][aria-label='Apply current filter to show results'] span.artdeco-button__text"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#data-control-name='filter_show_results' and #aria-label='Apply current filter to show results']//span[contains(., 'Show results')]"))).click()
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

Unable to get_attribute('src') from iframe tag in selenium

I have the following HTML code:
...
<div class="media ipad_media" style="padding-top: 0;">
<iframe src="//www.youtube.com/embed/XXXXXXXX" frameborder="0" allowfullscreen="allowfullscreen" width="618" height="330" data-gtm-yt-inspected-7182449_30="true">
</iframe>
<div>
...
<div class="media ipad_media hidden-xs">
<iframe src="//www.youtube.com/embed/XXXXXXXX" frameborder="0" allowfullscreen="allowfullscreen" width="618" height="330" data-gtm-yt-inspected-7182449_30="true">
</iframe>
</div>
I want the src attribute which is actually the same in both iframes. I just locate the first element by using the following command:
elem = driver.find_element_by_class_name("media.ipad_media").find_element_by_tag_name("iframe")
I then excute the following:
print(elem.get_attribute('width'))
print(elem.get_attribute('frameborder'))
print(elem.get_attribute('allowfullscreen'))
print(elem.get_attribute('src'))
print(elem.get_attribute('source'))
print(elem.text)
print(elem.tag_name)
I get the following in the console:
618
0
true
None
iframe
How is it possible to get nothing executing print(elem.get_attribute('src'))? As you understand, executing the $$("div.media.ipad_media>iframe") command in the console gives 2
The <div> tag is the immediate ancestor of the desired <iframe> tag.
To print the value of the src attribute of the <iframe> you can use either of the following Locator Strategies:
Using css_selector:
print(driver.find_element_by_css_selector("div.media.ipad_media > iframe").get_attribute("src"))
Using xpath:
print(driver.find_element_by_xpath("//div[#class='media ipad_media']/iframe").get_attribute("src"))
Ideally you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.media.ipad_media > iframe"))).get_attribute("src"))
Using XPATH:
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//div[#class='media ipad_media']/iframe"))).get_attribute("src"))
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

Find different element inside rows using selenium python

I am trying to get the values of available license inside the table using selenium in python3. I am able to get the values using XPATH, and iterate through each rows. But XPATH is not ideal, since the table might change and include an additional column, thus will fail to get the correct value.
The values I want, is 98,50,etc...
<div class="slick-cell l6 r6 licensesUsedValueGrid">
<div class="slick-cell odd" style="padding: 0px;width:100%;height: 44px;">
<div style="padding: 15% 4px 0px 0%;float: right;">98</div>
</div>
</div>
<div class="slick-cell l6 r6 licensesUsedValueGrid">
<div class="slick-cell odd" style="padding: 0px;width:100%;height: 44px;">
<div style="padding: 15% 4px 0px 0%;float: right;">50</div>
</div>
</div>
This is using XPATH, and it worked:
for i in range(1, rows, 2):
pak_id = browser.find_element_by_xpath(f'//*[#id="scrollBarDiv"]/div/div[{i}]/div[3]/div/div/div[1]').text
used_license = browser.find_element_by_xpath(f'//*[#id="scrollBarDiv"]/div/div[{i}]/div[7]/div/div').text
available_license = browser.find_element_by_xpath(f'//*[#id="scrollBarDiv"]/div/div[{i}]/div[8]/div/div').text
I would like to use class name or some other means so that even if they add another column to the table, i will be able to capture the right value of 'license used' and 'license available'
Picture of how it looks like on chrome:
Probably just:
browser.find_elements_by_css_selector('.licensesUsedValueGrid')
To extract all the values of available licenses using Selenium and Python you have to induce WebDriverWait for the visibility_of_all_elements_located() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
print([my_elem.text for my_elem in WebDriverWait(driver, 5).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "div.licensesUsedValueGrid>div.slick-cell.odd>div")))])
Using XPATH:
print([my_elem.text for my_elem in WebDriverWait(driver, 5).until(EC.visibility_of_all_elements_located((By.XPATH, "//div[contains(#class, 'licensesUsedValueGrid')]/div[#class='slick-cell odd']/div")))])
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

Selenium selecting link within table - with all the same name

Cant click on the link due to the fact, all of the value I keep trying to select has the same name as well within the tables.
Tried xpath,by link, by text, by css none of it works. My current code:
driver.find_element_by_xpath('//[#id="homeapp"]/div/div/div[3]/div[1]/table/tbody/tr[3]/td[2]/div[1]/div[2]/span[1]/a').click()
Here is the relevant html code:
<tr class="bui-table__row"><td class="peg-table__cell--no-label bui-table__cell" data-heading="ID" scope="row"><a href="../../extranet_ng/manage/index.html?ses=8594ddf0718dec240a0c9e7991e108a8&name_id=11111" class="bui-link bui-link--secondary" target="_blank" data-track-ga="Groups: Home,Active Properties,Property ID">
1111(number i can click aswell)
</a></td> <td class="peg-table__cell--no-label bui-table__cell" data-heading="Name" scope="row"><div class="bui-avatar-block"><div class="peg-_-avatar-shrink bui-avatar"><img src="https://q-xx.bstatic.com/xdata/images/extra/square60/189090859.jpg?k=cc455d4d570f0e0c86a1b8329b16d53fdba96d78677cc87151d6181e45d38ec5&o=" alt="text i want to click" class="bui-avatar__image"></div> <div class="bui-avatar-block__text"><span class="bui-avatar-block__title"><a href="../../extranet_ng/manage/index.html?ses=8594ddf0718dec240a0c9e7991e108a8&name_id=11111" class="peg-property-link bui-link bui-link--secondary" target="_blank" data-track-ga="Groups: Home,Active Properties,Property Name">
Text i want to click
<!----> <!----></a></span> <span class="bui-avatar-block__subtitle"><!----> </span></div></div> <div class="bui-spacer--smaller"></div> <div class="peg-score-bar__inline bui-score-bar"><div class="bui-score-bar__item"><div class="bui-score-bar__header"><h2 class="bui-score-bar__title"></h2> <span class="bui-score-bar__score">93%</span></div> <div class="bui-score-bar__bar"><span data-value="9.3" class="bui-score-bar__value" style="width: 93%;"></span></div></div></div></td> <td class="peg-table__cell--no-label bui-table__cell" data-heading="Location"><div class="peg-address-wrapper"><span class="peg-flag-wrapper"><div class="peg-flag bui-flag"><img src="https://q.bstatic.com/backend_static/common/flags/16/nl/314ce6500532e846e25d6e3a7c824ef17c968446.png" class="bui-flag__flag" style="height: auto;"> <!----></div></span>
TEXT2
</div></td> <td class="peg-table__cell--no-label bui-table__cell" data-heading="Status"><span>Open/Bookable</span></td> <td class="bui-table__cell bui-table__cell--center" data-heading="Arrivals/departures & tomorrow"><span class="peg-counter--arrivals"><a href="../../extranet_ng/manage/search_reservations.html?ses=8594ddf0718dec240a0c9e7991e108a8&name_id=11111" data-track-ga="Groups: Home,Active Properties,Arrivals" target="_blank" class="peg-counter peg-counter--has"><span aria-label="80 unread" class="bui-bubble">
VALUE1
</span></a></span> <span class="peg-counter--departures"><a href="../../extranet_ng/manage/search_reservations.html?ses=8594ddf0718dec240a0c9e7991e108a8&name_id=11111&type=departure" data-track-ga="Groups: Home,Active Properties,Departures" target="_blank" class="peg-counter peg-counter--has"><span aria-label="80 unread" class="bui-bubble">
VALUE2
</span></a></span></td> <td class="bui-table__cell bui-table__cell--center" data-heading="Guest Messages"><a href="../../extranet_ng/manage/messaging_inbox.html?ses=8594ddf0718dec240a0c9e7991e108a8&name_id=11111" data-track-ga="Groups: Home,Active Properties,Guest Messages" target="_blank" class="peg-counter peg-counter--has"><span aria-label="102 unread" class="bui-bubble">
VALUE3
</span></a></td> <td class="bui-table__cell bui-table__cell--center" data-heading="extranet.com Messages"><a href="../../extranet_ng/manage/inbox.html?ses=8594ddf0718dec240a0c9e7991e108a8&name_id=11111" data-track-ga="Groups: Home,Active Properties,extrabnet.com Messages" target="_blank" class="peg-counter"><span aria-label="0 unread" class="bui-bubble">
0
</span></a></td></tr>
If you want to click the link which contains avatar in its class attribute use the following XPath expression:
//div[contains(#class,'avatar')]/descendant::a[contains(text(), 'text i want to click')]
where:
contains() is XPath Function allowing partial match on the attributes values and/or text
descendant - XPath Axis which matches children of the current node and their respective children
last part limits the search to hyperlinks which contain text you're looking for
The desired element is a ReactJS enabled element, so you have to induce WebDriverWait for the element to be clickable() and you can use either of the following solutions:
Using PARTIAL_LINK_TEXT:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, "text i want to click"))).click()
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a.peg-property-link.bui-link.bui-link--secondary[href*='/extranet_ng/manage/index'][data-track-ga*='Active Properties']"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[#class='peg-property-link bui-link bui-link--secondary' and contains(#href, '/extranet_ng/manage/index')][starts-with(#data-track-ga, 'Groups')]"))).click()
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

How to Click Link Being Covered by Another Element? Python 3.6 and Selenium

Having trouble figuring out how to click the Next button at the bottom of the table on this page:
https://www.zacks.com/stocks/industry-rank/reit-and-equity-trust-other-266/stocks-in-industry
This is what I've tried:
from bs4 import BeautifulSoup
import requests
import csv, random, time
from pandas.io.html import read_html
from selenium import webdriver
from selenium.webdriver.support.ui import Select
url = 'https://www.zacks.com/stocks/industry-rank/reit-and-equity-trust-other-266/stocks-in-industry'
# Open Chrome
driver = webdriver.Chrome()
# Send Chrome to the URL
page = driver.get(url)
# Wait for page to load a few seconds
timeDelay = random.randrange(4, 8)
time.sleep(timeDelay)
# Try to click the darn button
element = driver.find_element_by_xpath('//*[#id="industry_rank_table_next"]')
driver.execute_script("arguments[0].click();", element)
...and
element = driver.find_element_by_xpath('//*[#id="industry_rank_table_next"]')
element.send_keys("\n")
...found from other answers but not working for me. Simply using .click() does not work. I've also tried selecting the button using css_selector, partial_link_text, and class_name but still no success. I've ran into this on a few sites. Any ideas?
To click() on the element with text as Next you have to induce WebDriverWait for the element to be clickable and you can use either of the following solutions:
Using LINK_TEXT:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.LINK_TEXT, "Next"))).click()
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a.paginate_button next#industry_rank_table_next"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[#class='paginate_button next' and #id='industry_rank_table_next']"))).click()
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
if the element which you have to click have parent element then you can find parent by findElements method and after than you just need to pass the index of the element like 0 or 1 or so on.. and then you can perform click action on that
Want to click on third li from second ul:
<ul id="select-123" style="width: 1180px; display: none;">
<li class="" style="display:none;">
<li class="">
<li class="">
<li class="">
</ul>
<ul id="select-123" style="width: 1180px; display: none;">
<li class="" style="display:none;">
<li class="">
<li class="">
<li class="">
</ul>
Code I am trying is to select third li from second ul which does not work:
driver.findElements(By.css(ul[id*='select-123'])).then(function(elems) {
elems[2].then(function(lis) {
driver.findElement(By.css("ul[id*='select-123'] li:nth-child(3)")).click();
});
});
Another way if you don't wish to add additional wait(s) to your code and just click the button:
using javascript click:
element = driver.find_element_by_xpath("//a[#class='paginate_button next' and #id='industry_rank_table_next']")
driver.execute_script("arguments[0].click();", element)
UPDATE:
I didn't notice this earlier, but
element = driver.find_element_by_xpath('//*[#id="industry_rank_table_next"]')
driver.execute_script("arguments[0].click();", element)
...works as it clicks the link successfully, but gives me a
selenium.common.exceptions.WebDriverException: Message: unknown error: call function result missing 'value'
...error after it clicks the link. So to get around this, I've just added a try/except to handle the error. ie:
try:
element = driver.find_element_by_xpath('//*[#id="industry_rank_table_next"]')
driver.execute_script("arguments[0].click();", element)
except:
pass
...which seems to work. Seems like such a stupid observation on my part, but thank you to everyone for your help. Hopefully something in here will help someone else in the future.

Resources