Selenium-получить все iframes на странице (даже вложенные)?

Я пытаюсь выполнить поиск по всем html веб-сайтов, которые я достигаю с помощью selenium webdriver. В selenium, когда у меня есть iframe, я должен переключиться на iframe, а затем вернуться к основному html для поиска других iframes.

однако с вложенными iframes это может быть довольно сложно. Я должен переключиться на iframe, искать его для iframes, затем переключиться на один iframe, найти его для iframe, затем перейти к другому iframe я должен переключиться на основной фрейм, а затем мой путь сохранен, чтобы вернуться туда, где я был раньше, и т. д.

к сожалению, многие страницы, которые я нашел, имеют iframes внутри iframes внутри iframes (и так далее).

есть ли простой алгоритм для этого? Или лучший способ сделать это?

3 ответов


Я не смог найти веб-сайт с несколькими слоями вложенных кадров, чтобы полностью протестировать эту концепцию, но я смог протестировать ее на сайте только с одним слоем вложенных кадров. Таким образом, это может потребовать немного отладки для решения более глубокой вложенности. Кроме того, этот код предполагает, что каждый из фреймов имеет атрибут name.

Я считаю, что использование рекурсивной функции вдоль этих линий решит проблему для вас, и вот пример структуры данных, чтобы пойти вместе с это:

def frame_search(path):
    framedict = {}
    for child_frame in browser.find_elements_by_tag_name('frame'):
        child_frame_name = child_frame.get_attribute('name')
        framedict[child_frame_name] = {'framepath' : path, 'children' : {}}
        xpath = '//frame[@name="{}"]'.format(child_frame_name)
        browser.switch_to.frame(browser.find_element_by_xpath(xpath))
        framedict[child_frame_name]['children'] = frame_search(framedict[child_frame_name]['framepath']+[child_frame_name])
        ...
        do something involving this child_frame
        ...
        browser.switch_to.default_content()
        if len(framedict[child_frame_name]['framepath'])>0:
            for parent in framedict[child_frame_name]['framepath']:
                parent_xpath = '//frame[@name="{}"]'.format(parent)
                browser.switch_to.frame(browser.find_element_by_xpath(parent_xpath))
    return framedict

вы бы начать его, позвонив:frametree = iframe_search([]) и framedict будет выглядеть примерно так:

frametree = 
{'child1' : 'framepath' : [], 'children' : {'child1.1' : 'framepath' : ['child1'], 'children' : {...etc}}, 
 'child2' : 'framepath' : [], 'children' : {'child2.1' : 'framepath' : ['child2'], 'children' : {...etc}}}

Примечание: причина, по которой я написал это, чтобы использовать атрибуты фреймов для их идентификации, а не просто использовать результат метода find_elements, заключается в том, что я нашел в некоторых сценариях Selenium будет выбрасывать устаревшее исключение данных после того, как страница была открыта слишком долго, и эти ответы больше не полезны. Очевидно, что рамка атрибуты не будут меняться, поэтому использование xpath немного более стабильно. Надеюсь, это поможет.


вы можете вложить один iFrame в другой iFrame, запомнив простую строку кода в положение, а затем переместите курсор обратно в ту же область экрана, используя as в следующем полном коде, всегда помня, что сначала нужно поместить больший iFrame, а затем определить положение меньшего iFrame во-вторых, как в следующем полном примере: - - -

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>Daneiella Oddie, Austrailian Ballet Dancer, dancing to Bach-Gounod's Ave Maria</title>
</head>
<body bgcolor="#ffffcc">

<DIV style="position: absolute; top:0px; left:0px; width:0px; height:0px"></div>
<DIV style="position: absolute; top:10px; left:200px; width:900px; height:500px">

<iframe width="824" height="472" src="http://majordomoers.me/Videos/DanielaOddiDancingToBack_GounodsAveMaria.mp4" frameborder="0" allowfullscreen></iframe>
</div>

<DIV style="position: absolute; top:0px; left:0px; width:0px; height:0px"></div>
<DIV style="position: absolute; top:10px; left:0px; width:50px; height:50px">

<iframe src="http://majordomoers.me/Videos/LauraUllrichSingingBach_GounodsAveMaria.mp4" frameborder="0" allowfullscreen></iframe>

</div>

<DIV style="position: absolute; top:0px; left:0px; width:0px; height:0px"></div>
<DIV style="position: absolute; top:470px; left:10px; width:1050px; height:30px">

<br><font face="Comic Sans MS" size="3" color="red">  
<li><b>Both Videos will START automatically...but the one with the audio will preceed the dancing by about 17 seconds.  You should keep
<li>both videos at the same size as presented here.  In all, just lean back and let it all unfold before you, each in its own time.</li></font>
</div>
<br>

</body>
</html>

def find_all_iframes(driver):
    iframes = driver.find_elements_by_xpath('//iframe')
    for index, iframe in enumerate(iframes):
        # Your sweet business logic applied to iframe goes here.
        driver.switch_to.frame(index)
        find_all_iframes(driver=driver)
        driver.switch_to.parent_frame()

ID, name или любое другое предположение об атрибутах оказывается ненадежным. Хотя полагаться на индекс iframe кажется довольно солидным.