如何在 Selenium Webdriver 中处理 iFrames:switchTo()

Selenium Webdriver 中的 iFrame

Selenium Webdriver 中的 iFrame 是一个嵌入在另一个网页中的网页或内联框架,或嵌入在另一个 HTML 文档中的 HTML 文档。iFrame 通常用于将其他来源(如广告)的内容添加到网页中。iFrame 使用 <iframe> 标签定义。

如何识别 iFrame

我们无法通过仅仅查看页面或使用 Firebug 检查来检测框架。

观察下图,显示的广告是一个 Iframe,我们无法通过 Firebug 检查来定位或识别它。那么问题是,您如何识别 iFrame?

Identify The Iframe
如何使用 Selenium WebDriver 识别 iFrame

我们可以使用以下方法在 Selenium 中识别框架

  • 右键单击元素,如果找到“此框架”之类的选项,那么它就是一个 iFrame。(请参阅上图)
  • 右键单击页面并单击“查看页面源代码”,然后搜索“iframe”,如果能找到任何带有“iframe”的标签名,则表示该页面包含一个 iFrame。

在上图中,您可以看到右键单击后,“此框架”选项可用,因此我们现在确定它是一个 iFrame。

我们甚至可以使用以下代码片段识别 iFrame 的总数。

Int size = driver.findElements(By.tagName("iframe")).size();

如何使用 WebDriver 命令在 Selenium 中处理框架

基本上,我们可以通过 3 种方式切换元素并在 Selenium 中处理框架。

  • 按索引
  • 按名称或 ID
  • 按网页元素

方法 1:按索引切换到框架

索引是 Selenium 中处理框架的属性之一,通过它我们可以切换到框架。

iframe 的索引从“0”开始。

假设页面中有 100 个框架,我们可以通过使用索引切换到 Selenium 中的框架。

  • driver.switchTo().frame(0);
  • driver.switchTo().frame(1);

方法 2:按名称或 ID 切换到框架

Name 和 ID 是在 Selenium 中处理框架的属性,通过它们我们可以切换到 iFrame。

  • driver.switchTo().frame("iframe1");
  • driver.switchTo().frame("元素的 ID");

通过 ID 切换到 iFrame 的示例

通过网页元素切换到框架

我们可以通过以下 URL 访问此 iFrame:https://demo.guru99.com/test/guru99home/

Handle Frames In Selenium Using WebDriver Commands

由于它是一个 iFrame,因此无法直接通过 XPath 点击 iFrame。我们必须先切换到框架,然后才能使用 XPath 进行点击。

步骤 1)

WebDriver driver = new FirefoxDriver();

driver.get("https://demo.guru99.com/test/guru99home/");

driver.manage().window().maximize();

  • 我们初始化 Firefox 驱动程序。
  • 导航到包含 iFrame 的“guru99”网站。
  • 最大化窗口。

步骤 2)

driver.switchTo().frame("a077aa5e");
  • 在此步骤中,我们需要通过 Firebug 检查找出 iFrame 的 ID。
  • 然后通过 ID 切换到 iFrame。

步骤 3)

driver.findElement(By.xpath("html/body/a/img")).click();
  • 在这里我们需要找出要点击的元素的 XPath。
  • 使用上面显示的 Web 驱动程序命令单击元素。

这是完整的代码

public class SwitchToFrame_ID {
public static void main(String[] args) {

		WebDriver driver = new FirefoxDriver(); //navigates to the Browser
	    driver.get("https://demo.guru99.com/test/guru99home/"); 
	       // navigates to the page consisting an iframe

	       driver.manage().window().maximize();
	       driver.switchTo().frame("a077aa5e"); //switching the frame by ID

			System.out.println("********We are switch to the iframe*******");
     		driver.findElement(By.xpath("html/body/a/img")).click();
  		    //Clicks the iframe
       
  			System.out.println("*********We are done***************");
      }
}		

输出

浏览器导航到包含上述 iFrame 的页面并点击 iFrame。

方法 3:按网页元素切换到框架

我们甚至可以使用网页元素切换到 iFrame。

  • driver.switchTo().frame(WebElement);

如何切换回主框架

我们必须退出 iFrame。

要返回父框架,您可以使用 switchTo().parentFrame(),或者如果您想返回主框架(或最上层父框架),您可以使用 switchTo().defaultContent();

	    driver.switchTo().parentFrame();
	    driver.switchTo().defaultContent();

如果我们无法使用 ID 或网页元素切换框架,该怎么办

假设页面中有 100 个框架,并且没有可用的 ID,在这种情况下,我们不知道所需元素是从哪个 iFrame 加载的(这也是我们不知道框架索引的情况)。

针对上述问题的解决方案是,我们必须通过以下代码片段找到加载元素的 iFrame 的索引,然后我们需要通过索引切换到 iFrame。

以下是使用以下代码片段查找加载元素的框架索引的步骤

步骤 1)

WebDriver driver = new FirefoxDriver();
driver.get("https://demo.guru99.com/test/guru99home/");
driver.manage().window().maximize();
  • 初始化 Firefox 驱动程序。
  • 导航到包含 iFrame 的“guru99”网站。
  • 最大化窗口。

步骤 2)

int size = driver.findElements(By.tagName("iframe")).size();
  • 上述代码使用标签名“iframe”查找页面中存在的 iFrame 总数。

步骤 3)

此步骤的目标是找出 iFrame 的索引。

for(int i=0; i<=size; i++){
	driver.switchTo().frame(i);
	int total=driver.findElements(By.xpath("html/body/a/img")).size();
	System.out.println(total);
	    driver.switchTo().defaultContent();}

上述“for 循环”遍历页面中的所有 iFrame,如果找到所需的 iFrame 则打印“1”,否则返回“0”。

这是第 3 步之前的完整代码

public class IndexOfIframe {
public static void main(String[] args) {
	    WebDriver driver = new FirefoxDriver();
	    driver.get("https://demo.guru99.com/test/guru99home/");  
	    driver.manage().window().maximize();
	    //driver.manage().timeouts().implicitlyWait(100, TimeUnit.SECONDS);
	    int size = driver.findElements(By.tagName("iframe")).size();

	    for(int i=0; i<=size; i++){
		driver.switchTo().frame(i);
		int total=driver.findElements(By.xpath("html/body/a/img")).size();
		System.out.println(total);
	    driver.switchTo().defaultContent();}}}

执行此程序,输出将如下所示

输出

1
0
0
0	
0
0

验证输出,您会发现一系列的 0 和 1。

  • 在输出中找到“1”的地方就是加载元素的框架索引。
  • 由于 iFrame 的索引从“0”开始,如果您在第一个位置找到 1,则索引为 0。
  • 如果您在第三个位置找到 1,则索引为 2。

一旦找到索引,我们可以注释掉 for 循环。

步骤 4)

driver.switchTo().frame(0);
  • 一旦找到元素的索引,您就可以使用上述命令切换框架。
  • driver.switchTo().frame(从步骤 3 中找到的索引);

步骤 5)

driver.findElement(By.xpath("html/body/a/img")).click();
  • 上述代码将点击 iFrame 或 iFrame 中的元素。

因此,完整的代码将如下所示

public class SwitchToframe   {
public static void main(String[] args) throws NoSuchElementException{
	    WebDriver driver = new FirefoxDriver();
	    driver.get("https://demo.guru99.com/test/guru99home/");  
	    driver.manage().window().maximize();
	    //int size = driver.findElements(By.tagName("iframe")).size();
	
	/*for(int i=0; i<=size; i++){
	    driver.switchTo().frame(i);
	    int total=driver.findElements(By.xpath("html/body/a/img")).size();
		System.out.println(total);
	    driver.switchTo().defaultContent(); //switching back from the iframe
	 }*/
	            
		//Commented the code for finding the index of the element
	    driver.switchTo().frame(0); //Switching to the frame
		System.out.println("********We are switched to the iframe*******");
		driver.findElement(By.xpath("html/body/a/img")).click();
		
		//Clicking the element in line with Advertisement
	    System.out.println("*********We are done***************");
	        }
	    }

输出

浏览器导航到包含上述 iFrame 的页面并点击 iFrame。

Selenium 中嵌套框架的概念

假设有两个框架相互嵌套,如下图所示,我们的要求是打印外部框架和内部框架中的文本。

在嵌套框架的情况下,

  • 首先,我们必须通过 iFrame 的索引或 ID 切换到外部框架
  • 一旦我们切换到外部框架,我们就可以找到外部框架中 iFrame 的总数,并且
  • 我们可以通过任何已知方法切换到内部框架。

退出框架时,我们必须按照进入的相同顺序退出,即先内部框架,然后是外部框架。

上述嵌套框架的 HTML 代码如下所示。

Concept of Nested Frames in Selenium

上述 HTML 代码清楚地解释了另一个 iFrame 标签内的 iFrame 标签(以绿色突出显示),表明存在嵌套 iFrame。

以下是切换到外部框架并打印外部框架文本的步骤

步骤 1)

	WebDriver driver=new FirefoxDriver();
	    driver.get("Url");
	    driver.manage().window().maximize();
	    driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
	    int size = driver.findElements(By.tagName("iframe")).size();
	    System.out.println("Total Frames --" + size);
	    
		// prints the total number of frames 
		driver.switchTo().frame(0); // Switching the Outer Frame    		
	    System.out.println (driver.findElement(By.xpath("xpath of the outer element ")).getText());
  • 切换到外部框架。
  • 打印外部框架上的文本。

一旦我们切换到外部框架,我们应该知道外部框架内是否存在任何内部框架

步骤 2)

size = driver.findElements(By.tagName("iframe")).size();
    // prints the total number of frames inside outer frame           
    System.out.println("Total Frames --" + size);
  • 查找外部框架内 iFrame 的总数。
  • 如果大小为“0”,则框架内没有内部框架。

步骤 3)

driver.switchTo().frame(0); // Switching to innerframe
System.out.println(driver.findElement(By.xpath("xpath of the inner element ")).getText());
  • 切换到内部框架
  • 打印内部框架上的文本。

这是完整的代码

public class FramesInsideFrames {
public static void main(String[] args) {
WebDriver driver=new FirefoxDriver();
	    driver.get("Url");
	    driver.manage().window().maximize();
	    driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

	    int size = driver.findElements(By.tagName("iframe")).size();
	    System.out.println("Total Frames --" + size);
               
		// prints the total number of frames 
		driver.switchTo().frame(0); // Switching the Outer Frame    		
	    System.out.println (driver.findElement(By.xpath("xpath of the outer element ")).getText());

		//Printing the text in outer frame
		size = driver.findElements(By.tagName("iframe")).size();
	    // prints the total number of frames inside outer frame           
                                                                                                          
	    System.out.println("Total Frames --" + size);
	    driver.switchTo().frame(0); // Switching to innerframe
	    System.out.println(driver.findElement(By.xpath("xpath of the inner element ")).getText());
		
		//Printing the text in inner frame
		driver.switchTo().defaultContent();
	}
}

输出:

上述代码的输出将打印内部框架和外部框架中的文本。