0

Unable to click on a button inside an iframe with seleinum in Python

Trying to figure out how to click button within a canvas.renderview. there appears to be no clear element that links to the button I want to click. Whenever I inspect element of any of the buttons on page it leads to the following code:

<iframe id="frameTest" class="trudyiframe" src="/trudydaily/game.phtml?id=1YHiRMqN9D7rpkR0iyA9FDJrdDhEc%2Bbj2v7hhLa%2FlpI%3D&amp;slt=1&amp;ver=2020" name="frameTest" frameborder="0" marginwidth="0" marginheight="0" scrolling="auto" onload="" allowtransparency="true">
    
<html><head>
        <title>Slots</title>
        <style>
            body {
                padding: 0;
            }
            .rendererView {
                margin: auto;
                display: block;
                width: 100%; 
                height: auto; 

            }
            #closeButton{
                position:absolute;
                top:0;
                right:0;
                width:30;
                height:30;
                display: none;
 
            }

            @media screen and (max-width:576px) {
                div#trudyContainer iframe,
                div#tempcontent iframe{
                    height: 230px;
                }
            }
        </style>
        <script src="/trudydaily/js/lib/pixi.js"></script>

        <script> var slt_check_trudy = 1; </script>

        <script src="/trudydaily/js/game.js?v=20200806"></script>
        <script src="https://images.neopets.com/js/jquery-1.7.1.min.js" type="text/javascript"></script>

<script>
$( document ).ready(function() {
            
            // Note moved into ready
            var ajaxurl = '/trudydaily/ajax/claimprize.php';
            var data = {
                'action': 'getslotstate','key': '1YHiRMqN9D7rpkR0iyA9FDJrdDhEc%2Bbj2v7hhLa%2FlpI%3D'};
            var resp;
            parent.$.post(ajaxurl, data, function (response) {
                resp = JSON.parse(response);
                if(resp.error == "") {
                    SlotsGame.LoadAssets(AssetLoadComplete, "https://images.neopets.com");
                } else {
                    parent.CloseSlotsGame(); // @todo restore this 2020?
                }
            });

            // 2020 H5 version: pass config object so we can switch context in game.js based on slt value. Original classic version included 3 different nearly duplicated .js files
            trudy_config = { "html5": "1",  "slt_check_trudy": "1"};
            SlotsGame.Initialize(trudy_config);

            function AssetLoadComplete(){
                SlotsGame.Start(resp);
            }

            function CloseGame(){
                parent.CloseSlotsGame(); //@todo restore this 2020
            };
});
</script>
    <link href="chrome-extension://nffaoalbilbmmfgbnbgppjihopabppdk/inject.css" type="text/css" rel="stylesheet"></head>
                <body marginwidth="0" marginheight="0" class="vsc-initialized"><a href="#" onclick="parent.CloseSlotsGame();">
            <img src="https://images.neopets.com/dailyslots/closebtn.png" id="closeButton">
        </a>
        
<canvas width="800" height="600" class="rendererView" style="cursor: inherit;"></canvas></body></html>
</iframe>

Code I have tried to location "Play" button the screen when it appears

from selenium import webdriver
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
import time
driver.get('https://www.neopets.com/trudys_surprise.phtml')
time.sleep(4)
iframeElement = driver.find_element(By.ID, "frameTest")
driver.switch_to.frame("frameTest")
time.sleep(2)
action = webdriver.common.action_chains.ActionChains(driver)
action.move_to_element_with_offset(iframeElement, 527, 672).click()
time.sleep(30)
driver.switch_to.default_content()

Whenever I hover over the button I want to click style="cursor: inherit;" changes to style="cursor: pointer;" There does not appear to be a clear button that links the the "Play" Button on screen

storyr4
  • 15
  • 5

1 Answers1

0

To click on the desired <a> element, as the element is within an <iframe> so you have to:

  • Induce WebDriverWait for the frame_to_be_available_and_switch_to_it.

  • Induce WebDriverWait for the desired element to be clickable.

  • You can use either of the following locator strategies:

    • Using CSS_SELECTOR:

      WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe.trudyiframe#frameTest")))
      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a[onclick*='CloseSlotsGame'] > img#closeButton"))).click()
      
    • Using XPATH:

      WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@class='trudyiframe' and @id='frameTest']")))
      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[contains(@onclick, 'CloseSlotsGame')]/img[@id='closeButton']"))).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
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Tried the above and get error message: line 95, in until raise TimeoutException(message, screen, stacktrace) selenium.common.exceptions.TimeoutException: Message: – storyr4 May 31 '23 at 22:21
  • Selenium didn't seem to be the answer used pyautogui instead – storyr4 Jun 01 '23 at 04:18