使用Python + Selenium选择iframe

ros*_*idh 30 python selenium

所以,我对如何在Selenium中做到这一点感到困惑,并且无法在任何地方找到答案,所以我分享了我的经验.

我试图选择一个iframe并且没有运气(或者无论如何都没有重复).HTML看起来像这样:

<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>
Run Code Online (Sandbox Code Playgroud)

Python代码(使用selenium库)试图使用以下方法找到这个iframe:

    @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")
Run Code Online (Sandbox Code Playgroud)

我找到的Selenium命令的每个组合都重复失败.偶尔的成功是不可复制的,所以也许是某种竞争条件或其他什么?从来没有找到正确的方法来获得适当的硒.

小智 48

在使用iframe进行测试并尝试在iframe中插入数据时,这适用于Python(v.2.7),webdriver和Selenium:

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()
Run Code Online (Sandbox Code Playgroud)

  • 当使用 xpath 搜索时,WebDriver 会以某种方式在 iframe 中找到元素。我尝试过通过 CSS、ID 查找元素,但它总是给我一个不存在元素的错误(实际上超时失败,因为我使用了 waitForElement 命令)。我不认为通过 xpath 搜索元素会有什么不同,但幸运的是,当我没有想法时,我尝试了一下。多谢! (3认同)

And*_*son 10

如果iframe是动态节点,也可以iframe显式等待外观,然后使用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"))
Run Code Online (Sandbox Code Playgroud)

如果iframe没有@id或者@name也可以共同使用WebElement中找到driver.find_element_by_xpath(),driver.find_element_by_tag_name()等..:

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

要切换回iframe:

driver.switch_to.default_content()
Run Code Online (Sandbox Code Playgroud)

  • 这可能是切换到框架的最佳解决方案,但 [frame_to_be_available_and_switch_to_it](https://www.selenium.dev/selenium/docs/api/py/_modules/selenium/webdriver/support/expected_conditions.html#frame_to_be_available_and_switch_to_it) 期望元组 `(By.ID,"frameID")` 或 WebElement,而不是纯字符串。 (4认同)

ros*_*idh 9

最终对我有用的是:

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

基本上,不要使用selenium来查找iframe中的链接并单击它; 使用jQuery.Selenium显然能够运行任意一段javascript(这是python-selenium,我猜最初的selenium命令是runScript或者其他东西),一旦我可以使用jQuery,我可以这样做:选择一个表单是在使用jQuery的iframe中

  • 你最好使用Selenium的getEval命令(可能是Python绑定中的"get_eval")而不是runScript命令.getEval在JavaScript代码完成之前不会返回,而runScript simple会插入<SCRIPT>元素并返回,导致浏览器在**调用返回后运行JavaScript代码**. (3认同)

dja*_*fan 6

您不需要使用JavascriptExecutor。您所需要做的就是切换到框架中,然后再切换回来,如下所示:

// 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
Run Code Online (Sandbox Code Playgroud)

只要你小心翼翼地对待这一点,你就永远不会有问题。我唯一一次总是使用 JavascriptExecutor 是为了获得窗口焦点,因为我认为在这种情况下使用 Javascript 更可靠。