web-dev-qa-db-fra.com

Sélectionnez iframe en utilisant Python + Selenium

Donc, j'étais absolument perplexe quant à la façon de le faire dans le sélénium, et je n'ai trouvé la réponse nulle part, alors je partage mon expérience.

J'essayais de sélectionner un iframe et je n'avais pas de chance (ou pas répétable de toute façon). Le HTML ressemblait à ceci:

<iframe id="upload_file_frame" width="100%" height="465px" frameborder="0" framemargin="0" name="upload_file_frame" src="/blah/import/">
<html>
    <body>
        <div class="import_devices">
            <div class="import_type">
                <a class="secondary_button" href="/blah/blah/?source=blah">
                    <div class="import_choice_image">
                        <img alt="blah" src="/public/images/blah/import/blah.png">
                    </div>
                    <div class="import_choice_text">Blah Blah</div>
                </a>
            </div>
        </div>
    </body>
</html>

Le Python (utilisant la bibliothèque Selenium) essayait de trouver cet iframe en utilisant ceci:

    @timed(650)
def test_pedometer(self):
    sel = self.Selenium
    ...
    time.sleep(10)
    for i in range(5):
        try:
            if sel.select_frame("css=#upload_file_frame"): break
        except: pass
        time.sleep(10)
    else: self.fail("Cannot find upload_file_frame, the iframe for the device upload image buttons")

Les échecs répétés avec chaque combinaison de commandes Selenium que j'ai pu trouver. Le succès occasionnel ne serait pas reproductible, alors peut-être était-ce une sorte de condition raciale ou quelque chose? Je n'ai jamais trouvé le bon moyen de l'obtenir en sélénium proprement dit.

30
rossdavidh

Ce qui a finalement fonctionné pour moi était:

        sel.run_script("$('#upload_file_frame').contents().find('img[alt=\"Humana\"]').click();")

En gros, n'utilisez pas Selenium pour trouver le lien dans l'iframe et cliquez dessus; utilisez jQuery. Selenium a la capacité d'exécuter un morceau arbitraire de javascript apparemment (c'est python-Selenium, je suppose que la commande Selenium d'origine est runScript ou quelque chose), et une fois que je peux utiliser jQuery, je peux faire quelque chose comme ceci: Sélection un formulaire qui est dans un iframe en utilisant jQuery

9
rossdavidh

Cela a fonctionné pour moi avec Python (v. 2.7), webdriver et Selenium lors des tests avec des iframes et en essayant d'insérer des données dans un iframe:

self.driver = webdriver.Firefox()

## Give time for iframe to load ##
time.sleep(3)
## You have to switch to the iframe like so: ##
driver.switch_to.frame(driver.find_element_by_tag_name("iframe"))
## Insert text via xpath ##
elem = driver.find_element_by_xpath("/html/body/p")
elem.send_keys("Lorem Ipsum")
## Switch back to the "default content" (that is, out of the iframes) ##
driver.switch_to.default_content()
46
Michael Whitman

Si iframe est un nœud dynamique, il est également possible d'attendre explicitement l'apparence de iframe puis de le basculer en utilisant ExpectedConditions :

from Selenium.webdriver.support import expected_conditions as EC
from Selenium.webdriver.support.ui import WebDriverWait as wait

driver = webdriver.Chrome()
driver.get(URL)
wait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it("iframe_name_or_id"))

Si iframe n'a pas @id Ou @name, Il peut être trouvé comme WebElement commun en utilisant driver.find_element_by_xpath(), driver.find_element_by_tag_name(), etc. .:

wait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it(driver.find_element_by_xpath("//iframe[@class='iframe_class']")))

Pour revenir de iframe:

driver.switch_to.default_content()
9
Andersson

Vous n'avez pas besoin d'utiliser JavascriptExecutor. Tout ce que vous aviez à faire était de basculer dans le cadre puis de revenir en arrière, comme ceci:

// do stuff on main window
driver.switch_to.frame(frame_reference)
// then do stuff in the frame
driver.switch_to.default_content()
// then do stuff on main window again

Tant que vous faites attention à cela, vous n'aurez jamais de problème. La seule fois où j'utilise toujours un JavascriptExecutor est d'obtenir le focus de la fenêtre car je pense que l'utilisation de Javascript est plus fiable dans ce cas.

4
djangofan

La commande selectFrame de Selenium accepte tous les localisateurs standard comme css=, Mais elle dispose également d'un ensemble supplémentaire de localisateurs qui fonctionnent spécifiquement avec les éléments FRAME et IFRAME.

Comme le doc dit:

selectFrame (locator) Sélectionne un cadre dans la fenêtre actuelle. (Vous pouvez invoquer cette commande plusieurs fois pour sélectionner des cadres imbriqués.) Pour sélectionner le cadre parent, utilisez "relative = parent" comme localisateur; pour sélectionner le cadre supérieur, utilisez "relative = haut". Vous pouvez également sélectionner une image par son numéro d'index basé sur 0; sélectionnez la première image avec "index = 0" ou la troisième image avec "index = 2".

Vous pouvez également utiliser une expression DOM pour identifier directement le cadre souhaité, comme ceci: dom=frames["main"].frames["subframe"]

Arguments: locator - un localisateur d'élément identifiant une trame ou une iframe

En général, vous aurez plus de chance d'utiliser les localisateurs spécialisés, surtout si vous établissez d'abord le bon contexte ( par exemple, select_frame("relative=top"); select_frame("id=upload_file_frame");).

1
Ross Patterson