簡體   English   中英

使用 Python + Selenium 選擇 iframe

[英]Select iframe using 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 命令組合都重復失敗。

偶爾的成功是不可復制的,所以也許是某種競爭條件或什么的? 從來沒有找到正確的方法來正確地獲取硒。

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

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

最終對我有用的是:

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

基本上不要用selenium在iframe中找到鏈接並點擊; 使用 jQuery。 Selenium 顯然有能力運行任意一段 javascript(這是 python-selenium,我猜原來的 selenium 命令是 runScript 或其他東西),一旦我可以使用 jQuery,我就可以做這樣的事情: 選擇一個表單在 iframe 中使用 jQuery

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

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

要在<iframe>內轉移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']"))

理想情況下,您必須誘導WebDriverWait以獲得所需的框架可用並切換到它,您可以使用以下任一定位器策略

  • 使用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

參考

您可以在以下位置找到一些相關討論:

您可以使用此簡單代碼使用 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM