Selenium find_element_by_id fails after loading the page - python-3.x

Here's a simple example:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.dcor.state.ga.us/GDC/Offender/Query")
button = driver.find_element_by_id('submit2')
The last command fails no matter how long I wait (unlike previous questions and answers-a long time after the page loads), but when I'm going to the browser itself(the instance that Selenium created), the green "I agree" button has the id submit2(right click->Inspect element)...
What causes this behavior?
How can I make it work?

That's because form located inside an iframe, so you need to switch to that frame before locating element:
driver.switch_to.frame('iframe-content')

The desired element is within an <iframe> so you need to:
Induce WebDriverWait for the desired frame to be available and switch to it.
Induce WebDriverWait for the desired element to be clickable and you can use the following solution:
Code Block:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"iframe-content")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input.oq-sub.btn.btn-success#submit2"))).click()

Related

ElementClickInterceptedException Solutions in Selenium and Python

I'm going to press a button on a website as automated, but meanwhile, something called campaigns(kampanyalar) is preventing it. How can I solve this? I want the other element not to get click property
The error:
ElementClickInterceptedException: element click intercepted: Element <div class="styled__CampaignCardDescriptionTitle-sc-1n4y3hk-2 hulWUi" color="">...</div> is not clickable at point (531, 35). Other element would receive the click: <a class="styled__HeaderMenuItem-sc-126ws66-35 gEoUee" href="/kampanyalar" id="DPE_TR_HOME_BUTTON_HEADERITEM0">...</a>
ElementClickInterceptedException means that the element you want to interact with is not available in Selenium view port.
3 things :
1. Launch the browser in full screen :
driver.maximize_window()
2. scroll till that element using execute_script :
driver.execute_script("arguments[0].scrollIntoView();", driver.find_element_by_css_selector(.your_css_selector))
3. Use of ActionChains :
ActionChains(driver).move_to_element(driver.find_element_by_id('some id where you want to go')).perform()
Imports you would need :
from selenium.webdriver.common.action_chains import ActionChains
ElementClickInterceptedException can be caused by several reasons.
The most powerful is to click it with JavaScript instead of webdriver click. Like the following:
element = driver.find_element_by_xpath("xpath")
driver.execute_script("arguments[0].click();", element)
However it's better to see what causes this exception.
In case the element is out of the visible screen or some footer element element overlaps it, it is better to scroll that element into the view:
from selenium.webdriver.common.action_chains import ActionChains
element = driver.find_element_by_xpath("xpath")
driver.execute_script("arguments[0].scrollIntoView();", element)
In some other case this will occur because you are trying to click the element while page is still loading elements so as some other element is currently found on that element. In this case it is better to simply wait until this element becomes clickable. Like this:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "xpath"))).click()
So, it's better to use more user-similar actions according to the specific situation you are facing there and only if no alternatives to use JavaScript clicks

Python Selenium: how to switch frames after navigation?

I'm trying to download a link within a table after navigating to a page using Python3 + selenium. After using selenium to click through links, and inspecting the elements on the latest-loaded page, I can see that my element is within a frame called "contents". When I try to access this frame, however, upon calling:
DRIVER.switch_to_frame("contents")
I get the following error:
selenium.common.exceptions.NoSuchFrameException: Message: contents
To gain more context I applied an experiment. Both the page that I loaded using DRIVER.get(URL) and the one to which I navigated had a frame called "menu".
I could call DRIVER.switch_to_frame("menu") on the first page, but not on the second.
DRIVER = webdriver.Chrome(CHROME_DRIVER)
DRIVER.get(SITE_URL)
DRIVER.switch_to_frame("contents") # This works
target_element = DRIVER.find_element_by_name(LINK)
target_element.click()
time.sleep(5)
DRIVER.switch_to_frame("menu")
target_element = DRIVER.find_element_by_name(LINK2)
target_element.click()
target_element = DRIVER.find_element_by_name(LINK3)
target_element.click()
DRIVER.switch_to_frame("contents") # Code breaks here.
target_element = DRIVER.find_element_by_xpath(REF)
target_element.click()
print("Program complete.")
I expect the code to find the xpath reference for the link in the "contents" frame. Instead, when attempt to switch to the "contents" frame, python run-time errors and cannot find "contents".
selenium.common.exceptions.NoSuchFrameException: Message: contents
this is because you are staying in child level of iframe which is 'menu' so inside that it can't able to find the iframe 'contents'.
First Switch back to the parent frame which is "contents", by using
DRIVER.switch_to.default_content()
and then try to go to the 'contents' iframe and perform actions, Now it should work.
Since contents appears to be a top level frame try going back to the top before selecting the frame:
DRIVER.switch_to.default_content()
DRIVER.switch_to.frame("contents")
As a thumb rule whenever switching frames you need to induce WebDriverWait for frame_to_be_available_and_switch_to_it() and you need to:
Induce WebDriverWait for the desired frame to be available and switch to it.
Induce WebDriverWait for the desired element to be clickable.
You can use the following solution:
target_element.click()
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"frame_xpath")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "REF"))).click()
You can find a detailed discussion on frame switching in How can I select a html element no matter what frame it is in in selenium?
Here you can find a relevant discussion on Ways to deal with #document under iframe

Selenium : Unable to locate element

So I'm trying to identify this button to press it, but I get the exception:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element
The image below shows the button:
The weird thing, is that I already did identify the login button in the login page, but after I got to the following page, it's like identifying an element isn't possible anymore, could that be because the page doesn't allow for that?
#This one works
driver.find_element_by_class_name("urBtnStdNew").click()
#This one give the exception
driver.find_element_by_id("sapbi_snippet_TABSTRIP_CONTAINER_ITEM_1").click()
#This is the HTML of that element
<span class="urTbsTxtOff">DPD Trend</span></td>
Edit: Thank you guys, I didn't know about iframe's existence, so switching it solved my problem.
iframe = driver.find_element_by_xpath("//iframe[#name='iframe_Roundtrip_9223342']")
driver.switch_to.frame(iframe)
Use WebDriverWait and following xpath to click on the DPD Trend tab.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//td[#class='urTbsLabelOff urBorderBox']/span[#class='urTbsTxtOff'][contains(.,'DPD Trend')]"))).click()
Hamza,
WebDriverWait will not work. As you have stated you have tried using Thread.sleep() and WebDriver still cannot locate the element.
The issue looks to me like it is down to an incorrect element locator being used.
If the button in your screenshot is the one in the red box, and the code in the red box in the element inspector relates to it, then it looks to me like the ID should be TABSTRIP_CONTAINER_ITEM_1_tabStrip_tabstrip-itm-5.
So based on your example above the following code should locate the DPD Trend button and click it:
driver.find_element_by_id("TABSTRIP_CONTAINER_ITEM_1_tabStrip_tabstrip-itm-5").click()
The correct XPath locator would be as simple as:
//span[text()='DPD Trend']
If you will still not be able to locate the element:
double check that it is not in an iframe, if it is - you will need to switch to it prior to finding
double check that it is not hidden in the shadow DOM, if it is - you will need to locate ShadowRoot via execute_script function and cast the result to a WebElement
a good practice is using WebDriverWait for locating the elements as it might be the case they're not immediately available in DOM, check out How to use Selenium to test web applications using AJAX technology article for more details.

How to click an element within an iframe

Currently I am trying to click the "entry-level" link in an iframe, for this website:https://a127-jobs.nyc.gov/index_new.html?category=CAS
Unfortunately, the url does not change if I click entry level, so therefore I am forced to automate.
I am not sure what to do, if the problem is that I have entered the wrong iframe? there seems to be only one, but I could be wrong.
from selenium import webdriver
import time
#webdriver
driver = webdriver.Firefox(executable_path="/Users/alexandrubordei/Desktop/geckodriver")
#get the website
driver.get ("https://a127-jobs.nyc.gov/index_new.html?category=CAS")
time.sleep(10)
#switch to iframe
iframes = driver.find_elements_by_tag_name("iframe")
driver.switch_to.frame(iframes[0])
time.sleep(10)
#click element "entry level"
driver.find_element_by_xpath('//*[#id="ti_S13"]').click()
When I run my code everything seems to function, except the link is not clicked. My search results are not narrowed.
However I do not get any errors. I get an error as:
Process finished with exit code 0
you have to click the a element inside that ID
driver.find_element_by_xpath('//*[#id="ti_S13"]/a').click()
To click() on the element with text as entry-level as the the desired elements are within an <iframe> so you have to:
Induce WebDriverWait for the desired frame to be available and switch to it.
Induce WebDriverWait for the desired element to be clickable.
You can use the following solution:
Code Block:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Firefox(executable_path=r'C:\Utility\BrowserDrivers\geckodriver.exe')
driver.get("https://a127-jobs.nyc.gov/index_new.html?category=CAS")
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#id='ptifrmtgtframe' and #name='TargetContent']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, "Entry-Level"))).click()
Browser Snapshot:
Here you can find a relevant discussion on Ways to deal with #document under iframe

click() method not working inside a frame in selenium python

i have written parameters in webpage & applying them by selecting apply button.
1. apply button is getting clicked for web elements outside frame using below command
browser1.find_element_by_name("action").click()
apply button not getting clicked when saving the paramters inside a frame of web page using same command
browser1.find_element_by_name("action").click()
you need to switch to iframe
fist you need to find the iframe then switch to it then click
driver.switch_to_frame(driver.find_element_by_tag_name("iframe"))
or you could use xpath to locate the element
driver.find_element_by_xpath("//iframe[]")
I do not know the Python syntax, but in Selenium you have to switch to the frame much like you would switch to a new tab or window before performing your click.
The syntax in Java would be: driver.switchTo().frame();
As mentioned by the others:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[]"))) #elements are in a iframe, have to select it first
If there is a chance that it doesn't show up immediately you might want to build in this wait function.
Tells python to wait for max 10 secs, until frame is available and switches to it right away. I use Xpath to track down the iframe
Dont know how new you are, so provided the imports below:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
Credit for this solution goes to #Andersson
Finding xpaths on pages running script
Upvote him there.
Couldn't find the duplicate report button. Title of this post makes it easier to find then the above mentioned question. (full disclosure, the link links to one of my own questions)

Resources