在 selenium web driver 中如何选择正确的 iframe
- 2025-03-26 09:10:00
- admin 原创
- 12
问题描述:
我正在尝试单击此页面上的某个元素:
url = 'https://finance.yahoo.com/quote/GOOG?ltr=1'
driver = webdriver.Firefox()
driver.get(url)
driver.find_element_by_link_text('Financials')
此时我想点击“现金流”、“资产负债表”或“季度”。我知道这些按钮已经加载,因为我可以使用 BeautifulSoup 从页面源中提取它们。但是当我尝试使用 Selenium 执行此操作时:
driver.find_element_by_link_text('Cash Flow')
driver.find_element_by_link_text('Balance Sheet')
driver.find_element_by_link_text('Quarterly')
除了“季度”返回一个元素之外,所有元素都返回“无法找到元素”,但它是位于图表上方的元素,而不是表格上方的元素,而这正是我感兴趣的。
我认为这是由于错误的 iframe 造成的,并且我已找到所有 iframe:
driver.find_elements_by_tag_name('iframe')
返回 9 个元素。但我搞不清楚要点击的元素属于哪个 iframe。我也按顺序浏览了 iframe,但仍然找不到我感兴趣的元素。
解决方案 1:
我刚刚检查了网站,它们(您正在寻找的元素)不在任何iframe标签中。
以下代码对我有用(更改为 xpath,无需切换):
driver.find_element_by_xpath("//span[contains(text(),'Cash Flow')]").click()
driver.find_element_by_xpath("//span[contains(text(),'Balance Sheet')]").click()
driver.find_element_by_xpath("//span[contains(text(),'Quarterly')]").click()
注意:可能是因为对于“财务”,父标签a
代表链接,但对于其他元素(现金流量、资产负债表),父标签div
不是链接标签。所以find_element_by_link_text
可能无法发挥作用。
在 iframe 之间切换:
在我们尝试识别该元素之前,您必须切换到该元素所在的框架。
假设您的元素位于以下 3 个 iframe 内:
<iframe name="frame1">
<iframe name="frame2">
<iframe name="frame3">
<span>CashFlow</span> <! Span element is inside of 3 iframes>
</iframe>
<span>balance sheet> <! Span element is inside of 2 iframes>
</iframe>
</iframe>
现在,如果您想识别三个 iFrames 内的 CashFlow:
driver.switch_to_frame(driver.find_element_by_name("frame1")) // here, you can provide WebElement representing the iFrame or the index.
driver.switch_to_frame(driver.find_element_by_name("frame2"))
driver.switch_to_frame(driver.find_element_by_name("frame3"))
driver.find_element_by_link_text("CachFlow")
# switch to default frame before you again try find some other element which is not in the same frame (frame3)
driver.switch_to_default_content()
# then navigate to the frame that you want to indentify the element:
driver.switch_to_frame(driver.find_element_by_name("frame1"))
driver.switch_to_frame(driver.find_element_by_name("frame2"))
driver.find_element_by_link_text("balance sheet")
# switch to default content again
driver.switch_to_default_content()
注意:我使用了框架引用而不是索引,因为您提到有 9 个 iFrames。因此,使用索引会造成混淆。如果您无法识别 frameElement,则只能使用索引。
参考:
解决方案 2:
您需要切换到正确的 iframe - 它们都有不同的 ID(或其他一些标签),在 java 中它看起来像这样(对于一些随机的 iframe id)
driver.switchTo().frame(driver.findElementById("defaultdestFB2-1"))
解决方案 3:
是的,这有助于解决问题。非常感谢。此网页上有 2 个框架 (0) 和 (1)。我添加了行“driver.switch_to.frame(1)”。下面是我使用的代码的副本,它解决了我遇到的问题...
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
#create capabilities
capabilities = DesiredCapabilities.INTERNETEXPLORER
#delete platform and version keys
capabilities.pop("platform", None)
capabilities.pop("version", None)
#start an instance of IE
driver = webdriver.Ie(executable_path="C:\\LocalDev\\IEDriverServer.exe", capabilities=capabilities)
#open Accela login page
driver.get("https://pwms-avdev.co.arapahoe.co.us/security/hostSignon.do?signOff=true")
driver.switch_to.frame(1)
#enter Agency
agency = driver.find_element_by_id("servProvCode")
agency.send_keys('arapahoe')