pythonselenium-webdriverundetected-chromedriver

Finding an element within iframes on a webpage, py + undetected_chromedriver


I want to write a method that can help me locate an element on a webpage that contains multiple iframes. Currently, I have to manually search through these iframes every time I need to find a specific element. I want to automate this process so that I only need to know the name of the element I am looking for.

I have written a method to accomplish this

def find_elem(self, xpath):
    try:
        sleep(2)
        # Try to find the element using the given XPath
        element = self.driver.find_element(By.XPATH, xpath)
        return element
    except  (NoSuchElementException, InvalidSelectorException) as e:
        # If the element is not found, search for it recursively in all iframes on the page
        element = None
        sleep(2)
        iframes = self.driver.find_element(By.XPATH, "//iframe") 
        for iframe in iframes:
            try:
                self.driver.switch_to.frame(iframe)
                element = self.find_elem(xpath)
                if element is not None:
                    break
            except NoSuchElementException:
                pass
            finally:
                self.driver.switch_to.default_content()
        # If the element is not found after searching all iframes, raise an exception
        if element is None:
            raise NoSuchElementException("Element not found: " + xpath)
        return element
...
self.driver.switch_to.default_content()
found_elem = self.find_elem('//span[@id="gotItButton"]')
found_elem.send_keys(Keys.TAB) # execute some action on the element

but it is crashing with an error: pydevd warning getting attribute webelement.screenshot_as_base64 was slow

Can anyone help me figure out how to locate an element when I do not know exactly which frame it is in? (I mean to help write a method using python)

P.S. I have also tried using the DevTools -> Recorder tool in Google Chrome, but it does not work with frames. An error occurred while attempting to interact with the element: 'waiting for target failed, timeout of 5000ms exceeded'.


Solution

  • def find_elem(self, xpath):
        sleep(1)
        iframes = self.driver.find_elements(By.TAG_NAME,'iframe')
        if iframes:
            for iframe in iframes:
                sleep(1)
                try:
                    self.driver.switch_to.frame(iframe)
                except:
                    continue
    
                try:
                    elem = WebDriverWait(self.driver, 1).until(EC.presence_of_element_located((By.XPATH, xpath)))
                    if elem is not None:
                        return elem, iframe
                except:
                    ''
    
                elem, tempF = self.find_elem(xpath)
                if elem is not None:
                    #self.driver.switch_to.default_content()
                    return elem, tempF
                sleep(1)
                self.driver.switch_to.default_content()
        try:
            elem = WebDriverWait(self.driver, 1).until(EC.presence_of_element_located((By.XPATH, xpath)))
            return elem, None
        except:
            return None, None
    

    ...

    elem, iframe = self.find_elem("//*[@id='nextTipButton']/span") 
    elem.click()