Тема: Пошук елемента в iframe на веб-сторінці, py + undetected_chromedriver

Я хочу написати метод, який допоможе мені знайти елемент на веб-сторінці, яка містить кілька iframe. Зараз мені доводиться вручну шукати крізь ці iframe кожного разу, коли мені потрібно знайти певний елемент. Я хочу автоматизувати цей процес так, щоб мені потрібно було знати лише назву шуканого елемента.

Я написав метод, щоб досягти цієї мети

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

але він вилітає з помилкою: pydevd warning getting attribute webelement.screenshot_as_base64 was slow.

Чи може хтось допомогти мені знайти елемент, якщо я не знаю в якому саме фреймі він знаходиться? (Я маю на увазі написання методу за допомогою Python)

P.S. Я також спробував використовувати інструмент DevTools -> Recorder в Google Chrome, але він не працює з фреймами. Виникла помилка при спробі взаємодії з елементом: "waiting for target failed, timeout of 5000ms exceeded".

2 Востаннє редагувалося Firefox is dead (09.03.2023 12:08:01)

Re: Пошук елемента в iframe на веб-сторінці, py + undetected_chromedriver

ви шукаєте всі iframe на сторінці, незалежно від того, чи є вони вкладені один в одного
ваш метод рекурсивно викликає себе в нескінченному циклі

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys

def find_elem(self, xpath):
    self.driver.switch_to.default_content() # переключення в основний фрейм, якщо потрібно
    frames = self.driver.find_elements_by_tag_name('iframe') # знаходження всіх фреймів на сторінці
    for frame in frames:
        self.driver.switch_to.frame(frame) # переключення до поточного фрейму
        try:
            elem = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, xpath))) # пошук елемента в поточному фреймі
            return elem
        except:
            pass
        finally:
            self.driver.switch_to.default_content() # переключення в основний фрейм
    return None # якщо елемент не знайдено

або спробуйте переписати свою функцію через стек з відповідними перевірками

Подякували: Betterthanyou1

3 Востаннє редагувалося Betterthanyou (09.03.2023 19:50:29)

Re: Пошук елемента в iframe на веб-сторінці, py + undetected_chromedriver

    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:
                    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() 

поверне elem і driver вже буде налаштований на потрібний iframe тому його не доведеться переключати

Подякували: Firefox is dead1