I'm trying to interact with a button on a page with the following structure. The button of interest is within a div in the body of an iframe, which is inside the main body. I've already read all the StackOverflow questions about how to switch to an iframe - as you can see below I have no issue with that. What I have an issue with is that regardless of that advice I am unable to interact with the iframe I switched to. The goal is to click a button inside a specific iframe.
EDIT: The issue seems to be related to the selenium-wire library. Here is the full code.
from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
import time
url = 'https://sahkovertailu.fi/'
options = {
'suppress_connection_errors': False,
'connection_timeout': None# Show full tracebacks for any connection errors
}
chrome_options = Options()
chrome_options.add_argument("--start-maximized")
chrome_options.add_argument('--auto-open-devtools-for-tabs')
chrome_options.add_argument('--log-level=2')
driver = webdriver.Chrome(ChromeDriverManager().install(), seleniumwire_options=options, chrome_options=chrome_options)
if driver.requests is not None:
del driver.requests
driver.get(url)
iframe = driver.find_element_by_xpath("//iframe[contains(@src, 'privacy')]")
driver.switch_to.frame(iframe)
iframeUniqueId = iframe.get_attribute('cd_frame_id_')
print(iframeUniqueId)
time.sleep(2)
button = driver.find_element_by_xpath("//button[contains(., 'OK')]")
button.click()
Here is an example of the page layout
<!doctype html>
<html ng-app="someApp" xmlns="http://www.w3.org/1999/html">
<head>
<script>a lot of scripts</script>
</head>
<body class="unwantedBody">
<iframe> some iframes</iframe>
<div> different divs </div>
<main>
some content
<iframe> multiple iframes on different nested levels </iframe>
</main>
<div> more divs </div>
<script> more scripts </script>
<div id='interesting div'>
<iframe src="uniqueString">
<!doctype html>
#document
<html>
<body>
<div>
<button id='bestButton'>
'Nice title'
</button>
</div>
</body>
</html>
</iframe>
</div>
</body>
</html>
Using Jupyter Notebook I've been able to locate the iframe and switch to it. The problem is not related to trying to interact with the iFrame too fast, because I control the speed. I've tried using Expected conditions and waiting until the iframe can be switched to, but it is irrelevant to my problem.
driver.switch_to.default_content # Making sure no other frame is selected
iframe = driver.find_element_by_xpath("//iframe[contains(@src, 'uniqueString')]")
driver.switch_to.frame(iframe)
print(iframe.get_attribute('id'))
The above code prints out "interesting div", so it successfully finds the div where the iframe is and apparently selects the div? When I switch to the iframe, the webpage changes and an unique GUID is given to the iframe:
<iframe src="uniqueString" cd_frame_id_ = "uniqueGuidThatAlwaysChanges"> ... </iframe>
I am able to access the unique id with
iframe.get_attribute('cd_frame_id_')
Then I try to parse the iframe like this:
bestButton = driver.find_element_by_xpath("//button[@id = 'bestButton']")
bestButton.click()
This gives the error:
Message: element not interactable
If I replace the above driver. with iframe.find_element_by_xpath... I get the following error:
Message: no such element: Unable to locate element: {"method":"xpath","selector":"//button[@id="bestButton"]"}
I also tried to interact with the body within the iframe after switching to it with the above switch_to.frame(iframe), so in this example driver is already at the iframe:
document = driver.find_element_by_xpath('//html/body')
info = document.get_attribute('class')
print(info)
This prints out
unwantedBody
So somehow the driver has not switched to the iFrame I specified and instead is still stuck on the main HTML. When loading the webpage on chrome I can find the button I want with just this XPath //button[contains(@id='bestButton')] but in Selenium it doesn't work, because it is split by the #document within the iframe.
What am I missing? If it helps, the iFrame I am interested in is actually a modal window about cookie consent, which I am trying to get rid of to interact with the site.