使用 Python 选择 iframe硒

发布于 2024-12-06 08:59:15 字数 1431 浏览 0 评论 0原文

所以,我对如何在 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 命令组合,重复失败。

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

So, I was absolutely baffled as to how to do this in Selenium, and couldn't find the answer anywhere, so I'm sharing my experience.

I was trying to select an iframe and having no luck (or not repeatably anyway). The HTML is:

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

The Python code (using the selenium library) was trying to find this iframe using this:

    @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")

Repeated fails with every combination of Selenium commands I could find.

The occasional success would not be reproducible, so perhaps it was some sort of race condition or something? Never did find the right way to get it in selenium proper.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

夜清冷一曲。 2024-12-13 08:59:15

这对我来说适用于 Python (v. 2.7)、webdriver 和 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()

This worked for me with Python (v. 2.7), webdriver & Selenium when testing with iframes and trying to insert data within an 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()
眼眸里的那抹悲凉 2024-12-13 08:59:15

如果 iframe 是动态节点,也可以显式等待 iframe 出现,然后使用 < code>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 找到它/code> 等:

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

If iframe is dynamic node, it's also possible to wait for iframe appearence explicitly and then switch to it using 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"))

If iframe doesn't have @id or @name it can be found as common WebElement using 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']")))

To switch back from iframe:

driver.switch_to.default_content()
晒暮凉 2024-12-13 08:59:15

最终对我有用的是:

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

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

What finally worked for me was:

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

Basically, don't use selenium to find the link in the iframe and click on it; use jQuery. Selenium has the capability to run an arbitrary piece of javascript apparently (this is python-selenium, I am guessing the original selenium command is runScript or something), and once I can use jQuery I can do something like this: Selecting a form which is in an iframe using jQuery

冷夜 2024-12-13 08:59:15

您不需要使用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 更可靠。

You don't need to use JavascriptExecutor. All you needed to do was switch into the frame and then switch back out, like so:

// 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

As long as you are careful with this, you will never have a problem. The only time I always use a JavascriptExecutor is to get window focus since I think using Javascript is more reliable in that case.

牛↙奶布丁 2024-12-13 08:59:15

中转移 Selenium 的焦点> 您可以使用以下任一定位器策略

  • 使用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']"))
    

理想情况下,您必须诱导 WebDriver等待所需的框架可用并切换到它,您可以使用以下任一方法定位器策略

  • 使用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
     从 selenium.webdriver.common.by 导入
     从 selenium.webdriver.support 导入预期条件作为 EC
    

参考

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

To shift Selenium's focus within the <iframe> you can use either of the following Locator Strategies:

  • Using ID:

    driver.switch_to.frame("upload_file_frame") 
    
  • Using CSS_SELECTOR:

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

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

Ideally, you have to induce WebDriverWait for the desired frame to be available and switch to it and you can use either of the following Locator Strategies:

  • Using ID:

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

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

    WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@id='upload_file_frame']")))
    
  • Note : You have to add the following imports :

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

Reference

You can find a couple of relevant discussions in:

來不及說愛妳 2024-12-13 08:59:15

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

正如 文档 所说:

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");)。

Selenium's selectFrame command accepts all the standard locators like css=, but it also has a an extra set of locators that work specifically with FRAME and IFRAME elements.

As the doc says:

selectFrame ( locator ) Selects a frame within the current window.
(You may invoke this command multiple times to select nested frames.)
To select the parent frame, use "relative=parent" as a locator; to
select the top frame, use "relative=top". You can also select a frame
by its 0-based index number; select the first frame with "index=0", or
the third frame with "index=2".

You may also use a DOM expression to identify the frame you want
directly, like this: dom=frames["main"].frames["subframe"]

Arguments: locator - an element locator identifying a frame or iframe

In general, you'll have better luck using the specialized locators, especially if you establish the right context first (e.g., select_frame("relative=top"); select_frame("id=upload_file_frame");).

苹果你个爱泡泡 2024-12-13 08:59:15

来查找 iframe

您可以使用这个简单的代码来使用 xpath示例使用
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

you can use this simple code to look for the iframe using xpath

sample use
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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文