使用 Python + Selenium 选择 iframe
- 2024-12-17 08:30:00
- admin 原创
- 166
问题描述:
所以,我对如何在 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 命令组合都会重复失败。
偶尔的成功无法重现,所以也许是某种竞争条件之类的?从来没有找到在 selenium 中正确获取它的正确方法。
解决方案 1:
当我使用 Python (v. 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()
解决方案 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
找到常见的 WebElement :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()
解决方案 3:
最终对我有用的是:
sel.run_script("$('#upload_file_frame').contents().find('img[alt=\"Humana\"]').click();")
基本上,不要使用 selenium 来查找 iframe 中的链接并单击它;使用 jQuery。Selenium 显然能够运行任意一段 javascript(这是 python-selenium,我猜原始 selenium 命令是 runScript 之类的),一旦我可以使用 jQuery,我就可以执行以下操作:使用 jQuery 选择 iframe 中的表单
解决方案 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的焦点,<iframe>
您可以使用以下任一定位器策略:
使用
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
参考
您可以在以下位置找到几个相关的讨论:
iframe 下 #document 的处理方法
通过 Selenium 和 python 切换到 iframe
解决方案 6:
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");
。
解决方案 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