frame切换/窗口切换
前言
参考教程:Python + Selenium Web自动化 2024版 - 自动化测试 爬虫_哔哩哔哩_bilibili
上期文章:Selenium-Java版(css表达式)-CSDN博客
切换到frame
运行代码
java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.edge.EdgeDriver;
import java.time.Duration;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 创建WebDriver对象
WebDriver wd = new EdgeDriver();
wd.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
// 访问目标网页
wd.get("https://www.byhy.net/cdn2/files/selenium/sample2.html");
// 根据class name选择元素,返回的是一个列表
List<WebElement> elements = wd.findElements(By.className("plant"));
// 遍历列表并打印每个元素的文本内容
for (WebElement element : elements) {
System.out.println(element.getText());
}
// 创建Scanner对象等待用户输入
Scanner scanner = new Scanner(System.in);
System.out.println("等待回车键结束程序");
scanner.next();
// 关闭浏览器
wd.quit();
}
发现并没有打印元素的文本内容
原因
这些元素是在一个叫iframe的元素中的

frame元素或者iframe元素的内部会包含一个被嵌入的另一份html文档。使用selenium打开一个网页的操作范围并不包含被嵌入的html文档里面的内容。
解决
操作被嵌入的html文档中的元素,需要**切换操作范围
**到被嵌入的文档中。
使用 WebDriver 对象的switchTo属性,三选一:
括号内填id
java
wd.switchTo().frame("frame1");
括号内填class属性值
java
wd.switchTo().frame("innerFrame");
括号内填frame对应的WebElement对象
java
wd.switchTo().frame(wd.findElement(By.tagName("iframe")));
上面例子的正确代码
java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.edge.EdgeDriver;
import java.time.Duration;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 创建WebDriver对象
WebDriver wd = new EdgeDriver();
wd.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
// 访问目标网页
wd.get("https://www.byhy.net/cdn2/files/selenium/sample2.html");
// 切换到名为 'frame1' 的 frame
wd.switchTo().frame("frame1");
// 根据class name选择元素,返回的是一个列表
List<WebElement> elements = wd.findElements(By.className("plant"));
// 遍历列表并打印每个元素的文本内容
for (WebElement element : elements) {
System.out.println(element.getText());
}
// 创建Scanner对象等待用户输入
Scanner scanner = new Scanner(System.in);
System.out.println("等待回车键结束程序");
scanner.next();
// 关闭浏览器
wd.quit();
}
}
运行框打印出了内容

切换回原来的主html
java
wd.switchTo().defaultContent();
假如操作完frame里面的元素后,需要点击主html里面的按钮
运行代码
java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.edge.EdgeDriver;
import java.time.Duration;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 创建WebDriver对象
WebDriver wd = new EdgeDriver();
wd.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
// 访问目标网页
wd.get("https://www.byhy.net/cdn2/files/selenium/sample2.html");
// 根据name属性值 'innerFrame',切换到iframe中
wd.switchTo().frame("innerFrame");
// 根据 class name 选择元素,返回的是 一个列表
List<WebElement> elements = wd.findElements(By.className("plant"));
// 遍历列表并打印每个元素的文本内容
for (WebElement element : elements) {
System.out.println(element.getText());
}
// 切换回 最外部的 HTML 中
wd.switchTo().defaultContent();
// 然后再 选择操作 外部的 HTML 中 的元素
wd.findElement(By.id("outerbutton")).click();
// 创建Scanner对象等待用户输入
Scanner scanner = new Scanner(System.in);
System.out.println("等待回车键结束程序");
scanner.next();
// 关闭浏览器
wd.quit();
}
}
查看自动打开的网站

切换到新的窗口

问题
运行代码
java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.edge.EdgeDriver;
import java.time.Duration;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 创建WebDriver对象
WebDriver wd = new EdgeDriver();
wd.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
// 访问目标网页
wd.get("https://www.byhy.net/cdn2/files/selenium/sample3.html");
// 点击打开新窗口的链接
WebElement link = wd.findElement(By.tagName("a"));
link.click();
// wd.getTitle()方法是当前窗口的标题栏文本
System.out.println(wd.getTitle());
// 创建Scanner对象等待用户输入
Scanner scanner = new Scanner(System.in);
System.out.println("等待回车键结束程序");
scanner.next();
// 关闭浏览器
wd.quit();
}
}
运行框

虽然打开了新窗口,但输出的不是新窗口标题,而是老窗口的标题
解决
点击链接和输出标题的中间加入如下代码
java
// 获取所有窗口句柄
Set<String> windowHandles = wd.getWindowHandles();
// 遍历所有窗口句柄
for (String handle : windowHandles) {
// 先切换到该窗口
wd.switchTo().window(handle);
// 得到该窗口的标题栏字符串,判断是不是我们要操作的那个窗口
if (wd.getTitle().contains("Microsoft")) {
// 如果是,那么这时候WebDriver对象就是对应的该窗口,正好,跳出循环
break;
}
}
运行框

回到原窗口
法一
和切换新窗口用同样的方法,只需换一行代码
java
wd.getTitle().contains("白月黑羽")
法二
遍历窗口句柄之前,提前保存当前窗口句柄
java
// mainWindow变量保存当前窗口的句柄
String mainWindow = wd.getWindowHandle();
新窗口操作完后,将driver对应的对象返回到原来的窗口
java
// 通过前面保存的老窗口的句柄,自己切换到老窗口
wd.switchTo().window(mainWindow);
示例
运行代码
java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.edge.EdgeDriver;
import java.time.Duration;
import java.util.Scanner;
import java.util.Set;
public class Main {
public static void main(String[] args) {
// 创建WebDriver对象
WebDriver wd = new EdgeDriver();
wd.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
// 访问目标网页
wd.get("https://www.byhy.net/cdn2/files/selenium/sample3.html");
// mainWindow变量保存当前窗口的句柄
String mainWindow = wd.getWindowHandle();
// 点击打开新窗口的链接
WebElement link = wd.findElement(By.tagName("a"));
link.click();
// 获取所有窗口句柄
Set<String> windowHandles = wd.getWindowHandles();
// 遍历所有窗口句柄
for (String handle : windowHandles) {
// 先切换到该窗口
wd.switchTo().window(handle);
// 得到该窗口的标题栏字符串,判断是不是我们要操作的那个窗口
if (wd.getTitle().contains("Microsoft")) {
// 如果是,那么这时候WebDriver对象就是对应的该窗口,正好,跳出循环
break;
}
}
// 打印当前窗口的标题栏文本
System.out.println(wd.getTitle());
// 通过前面保存的老窗口的句柄,自己切换到老窗口
wd.switchTo().window(mainWindow);
// 打印切换回老窗口后的标题栏文本
System.out.println(wd.getTitle());
// 创建Scanner对象等待用户输入
Scanner scanner = new Scanner(System.in);
System.out.println("等待回车键结束程序");
scanner.next();
// 关闭浏览器
wd.quit();
}
}
运行框

不仅仅适用于最初的老窗口,操作期间打开的其他窗口都可以保留其窗口句柄