使用 Python + Selenium 选择 iframe

Posted

技术标签:

【中文标题】使用 Python + Selenium 选择 iframe【英文标题】:Select iframe using Python + Selenium 【发布时间】:2011-11-23 23:29:40 【问题描述】:

所以,我对如何在 Selenium 中执行此操作感到非常困惑,并且无法在任何地方找到答案,所以我分享我的经验。

我试图选择一个 iframe 并且没有运气(或者无论如何都不能重复)。 html 是:

<iframe id="upload_file_frame"   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  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 命令组合都重复失败。

偶尔的成功是不可复制的,所以也许是某种竞争条件或什么?从来没有找到正确的方法将它放入硒中。

【问题讨论】:

【参考方案1】:

在使用 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()

【讨论】:

在使用 xpath 搜索时,WebDriver 以某种方式在 iframe 中找到元素。我尝试通过 CSS、ID 查找元素,但它总是给我一个不存在元素的错误(实际上超时失败是因为我使用了 waitForElement 命令)。我不认为通过 xpath 搜索元素会有所作为,但幸运的是,当我没有想法时尝试了它。非常感谢! 在处理似乎具有动态生成的名称和 URL 的 iframe 时特别​​方便。真的很有用,谢谢【参考方案2】:

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

【讨论】:

这可能是切换到框架的最佳解决方案,但 frame_to_be_available_and_switch_to_it 需要一个元组 (By.ID,"frameID") 或 WebElement,而不是纯字符串。【参考方案3】:

最终对我有用的是:

        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

【讨论】:

你最好使用 Selenium 的 getEval 命令(在 Python 绑定中可能是“get_eval”)而不是它的 runScript 命令。 getEval 在 JavaScript 代码完成之前不会返回,而 runScript simple 会插入一个 sel.run_script 到底是什么?我在文档或谷歌中找不到这个功能的提及。虽然这可能对您有用,但它的答案很糟糕,因为您没有解释 self.selenium 是什么或如何获得 run_script 就是说,driver.execute_script 对我有用 好吧,说实话,那是五年前的事了,我现在还不知道。不过,很高兴 driver.execute_script 对您有用,您将其发布在此处以供未来的读者使用也很好。【参考方案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 更可靠。

【讨论】:

【参考方案5】:

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

正如the doc 所说:

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

您也可以使用 DOM 表达式来识别您想要的框架 直接,像这样:dom=frames["main"].frames["subframe"]

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

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

【讨论】:

是的,selectFrame 对我不起作用。并不意味着它对任何人都不起作用,但我发现它实际上在 5 分钟内选择了一次框架。【参考方案6】:

要将Selenium 的焦点转移到&lt;iframe&gt; 中,您可以使用以下任一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

参考

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

Ways to deal with #document under iframe Switch to an iframe through Selenium and python

【讨论】:

【参考方案7】:

您可以使用这个简单的代码通过 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

【讨论】:

以上是关于使用 Python + Selenium 选择 iframe的主要内容,如果未能解决你的问题,请参考以下文章

对于使用 Python 的 Selenium,我怎样才能让它按 CTRL、SHIFT、i?

使用Selenium和Python的日历选择器

如何使用 Selenium 和 Python 选择下拉菜单项(值或文本)? [复制]

python+selenium自动化测试——CSS选择元素

python+selenium自动化测试——CSS选择元素

如何使用 Selenium Webdriver 和 Python 从这个非选择下拉菜单中选择这个元素