Selenium - get all iframes on a page (even nested)?

I am trying to search all the html sites that I use using selenium webdriver. In selenium, when I have an iframe, I have to switch to an iframe and then go back to the main html to look for other iframes.

However, with nested iframes, this can be quite complicated. I have to switch to iframe, look for it for iframes, then switch to one iframe found, look for IT for iframe, then go to another iframe. I have to switch to the main frame and then save my path in order to return back to where I was before, etc.

Unfortunately, many of the pages I found have an iframe inside an iframe inside an iframe (and so on).

Is there a simple algorithm for this? Or is the best way to do this?

+6
source share
3 answers

I could not find a website with several layers of nested frames to fully test this concept, but I was able to test it on the site with only one layer of nested frames. Thus, this may require a bit of debugging to work with a deeper nesting. In addition, this code assumes that each of the frames has a name attribute.

I believe that using a recursive function on these lines will solve the problem for you, and here is an example of a data structure to go with it:

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

You release it by calling:, frametree = iframe_search([])and framedictin the end it will look something like this:

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

. , , , find_elements, - , . Selenium , . , , xpath. , .

+5

iframe HTML- ( ID) .

, iframe .

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.switch_to.parent_frame()
+2

You can embed one iFrame in another iFrame, remembering a simple line of code for the position, then move the cursor back to the same area of ​​the screen, using as in the following COMPLETE code, remember that always put a larger iFrame FIRST, then determine the position of the SMALLER iFrame SECOND as in the following FULL example: ---

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

<html>
<head>
<title>Daneiella Oddie, Austrailian Ballet Dancer, dancing to Bach-Gounod 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>
0
source

Source: https://habr.com/ru/post/1537523/


All Articles