使用Python + Selenium选择iframe

时间:2011-09-23 20:43:55

标签: 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>

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命令组合都会重复失败。偶尔的成功是不可复制的,所以也许是某种竞争条件或其他什么?从来没有找到正确的方法来获得适当的硒。

7 个答案:

答案 0 :(得分:41)

这适用于Python(v.2.7),webdriver&amp;使用iframe进行测试并尝试在iframe中插入数据时的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()

答案 1 :(得分:8)

最终对我有用的是:

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

基本上,不要使用selenium来查找iframe中的链接并单击它;使用jQuery。 Selenium有能力运行任意一段javascript(这是python-selenium,我猜最初的selenium命令是runScript或者其他东西),一旦我可以使用jQuery,我可以这样做:Selecting a form which is in an iframe using jQuery

答案 2 :(得分:8)

如果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()等找到它作为常见的WebElement。:

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()

答案 3 :(得分:4)

您不需要使用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

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

答案 4 :(得分:1)

Selenium的selectFrame命令接受所有标准定位器,如css=,但它还有一组额外的定位器,专门用于FRAME和IFRAME元素。

正如the doc所说:

  

selectFrame(locator)选择当前窗口中的帧。   (您可以多次调用此命令来选择嵌套帧。)   要选择父框架,请使用“relative = parent”作为定位器;至   选择顶部框架,使用“relative = top”。您也可以选择一个框架   基于0的索引号;选择“index = 0”的第一帧,或   第三帧“index = 2”。

     

您也可以使用DOM表达式来标识所需的帧   直接,像这样:dom=frames["main"].frames["subframe"]

     

参数:locator - 标识框架或iframe的元素定位器

一般来说,使用专门的定位器会更好,特别是如果你先建立正确的上下文(例如select_frame("relative=top"); select_frame("id=upload_file_frame");)。

答案 5 :(得分:0)

您可以使用此简单代码通过xpath查找iframe

样本使用 set_iframe(“ / html / body / div [2] / table /”)

def set_iframe(xpath):
    print('set_iframe')
    driver.switch_to.default_content()
    seq = driver.find_elements_by_tag_name('iframe')
    for x in range(0, len(seq)):
        driver.switch_to.default_content()
        print ("iframe-"+str(x))
        try:
            driver.switch_to.frame(int(x))
            driver.find_element_by_xpath(xpath)
            return str(x)
        except:
            continue

答案 6 :(得分:0)

要在 <iframe> 内移动 Selenium 的焦点,您可以使用以下任一 Locator Strategies

  • 使用 ID

    driver.switch_to.frame("upload_file_frame") 
    
  • 使用 CSS_SELECTOR

    driver.switch_to.frame(driver.find_element(By.CSS_SELECTOR, "iframe#upload_file_frame"))
    
  • 使用 XPATH

    driver.switch_to.frame(driver.find_element(By.XPATH, "//iframe[@id='upload_file_frame']"))
    

理想情况下,您必须诱导 WebDriverWait 使所需的框架可用并切换到它,您可以使用以下任一 Locator Strategies

  • 使用 ID

    WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"upload_file_frame")))  
    
  • 使用 CSS_SELECTOR

    WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe#upload_file_frame")))
    
  • 使用 XPATH

    WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@id='upload_file_frame']")))
    
  • 注意:您必须添加以下导入:

     from selenium.webdriver.support.ui import WebDriverWait
     from selenium.webdriver.common.by import By
     from selenium.webdriver.support import expected_conditions as EC
    

参考

您可以在以下位置找到一些相关讨论: