使用Python和Selenium选择iframe

62 投票
7 回答
142517 浏览
提问于 2025-04-17 02:57

我在用Selenium的时候,完全搞不懂该怎么做,找了半天也没找到答案,所以我决定分享一下我的经历。

我想选择一个iframe,但总是失败(或者说不稳定)。这个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>

我用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")

我尝试了各种Selenium命令的组合,但每次都失败。

偶尔成功一次,但又无法重复,所以我在想是不是有什么竞争条件之类的问题?总之,我没找到在Selenium中正确的方法。

7 个回答

30

如果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"))

如果iframe没有@id@name,我们可以通过一些常用的方法找到它,比如使用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']")))

要从iframe切换回来:

driver.switch_to.default_content()
100

我在用Python(版本2.7)、webdriver和Selenium进行测试时,遇到了iframe的问题,想在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()
12

最后对我有效的方法是:

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

简单来说,不要用selenium去找iframe里的链接并点击它;用jQuery来做。selenium其实可以运行一些任意的javascript代码(这是python-selenium,我猜原来的selenium命令是runScript之类的),一旦我能用jQuery,就可以像这样操作:用jQuery选择在iframe中的表单

撰写回答