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 кажется довольно солидным.