Selenium自动化操作

一、引入依赖

java 复制代码
<dependencies>
        <!-- https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager -->
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>5.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>4.0.0</version>
        </dependency>
    </dependencies>

二、初始化浏览器对象

这里我们使用的是edg的浏览器,外加创建截图方法,方便后面有错误进行截图查看。

java 复制代码
package common;

import io.github.bonigarcia.wdm.WebDriverManager;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;

public class Utils {
    //创建一个公共的driver
    public static WebDriver driver;

    //判断driver是否为空
    public static WebDriver creat(){
        if(driver == null){
            //创建
            WebDriverManager.edgedriver().setup();
            EdgeOptions options = new EdgeOptions();
            //允许访问所有链接
            options.addArguments("--remote-allow-origins=*");
            driver = new EdgeDriver(options);
        }
        //添加隐式等待
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));
        return driver;
    }

    /**
     * 屏幕截图
     * 屏幕截图文件目录
     * ./src/test/java/images/
     *                       /2025-04-29/
     *                                  /test01-20123010.png
     *                                  /test02-20133510.png
     *                       /2025-04-30/
     *                                  /test01-20123010.png
     *      *                           /test02-20133510.png
     *
     *str:方法名/类名
     */
    //截图
    public void getPicture(String str) throws IOException {
        //规定两个时间
        SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");

        //接收
        String dirTime = sim1.format(System.currentTimeMillis());
        String fileTime = sim2.format(System.currentTimeMillis());

        String name = "./src/test/image/" + dirTime + "/" + str + "-" + fileTime + ".png";
        File screenshotAs = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(screenshotAs, new File(name));
    }

    //使用
    public Utils(String url){
        //得到driver
        driver = creat();
        driver.get(url);
    }

}

三、测试

这里我们使用b站的网页进行测试

1.1 测试是否可以加载页面

java 复制代码
package tests;

import common.Utils;
import org.openqa.selenium.By;

public class Demo1 extends Utils {

    //输入测试的网址,这里我们以b站为例
    public static String url = "https://www.bilibili.com/";

    public Demo1() {
        super(url);
    }

    //测试页面是否可以打开
    public void test(){
        //使用css选择器定位元素
        driver.findElement(By.cssSelector("#i_cecream > div.bili-feed4 > div.bili-header.large-header > div.bili-header__banner > div.header-banner__inner > a > img"));
        driver.quit(); //关闭浏览器页面
    }
}

1.2 测试是否可以跳转页面

我们以这个高考季测试,点击看是否会产生新的页面

java 复制代码
//测试是否可以产生新的页面
    public void jump() throws IOException {
        //使用css选择器定位元素
        driver.findElement(By.cssSelector("#i_cecream > div.bili-feed4 > div.bili-header.large-header > div.bili-header__bar > ul.left-entry > li:nth-child(8) > div > a")).click();
        //截图看是否跳转成功
        //要使用类名.class.getName
        getPicture(Demo1.class.getName());
        driver.quit();
    }

这里我们如果运行自动化代码就会报错,因为用自动化打开的页面不包含高考季的链接。

我们点击页面的动态看看会不会成功

java 复制代码
 public void jump() throws IOException, InterruptedException {
        //使用css选择器定位元素-高考季
//        driver.findElement(By.cssSelector("#i_cecream > div.bili-feed4 > div.bili-header.large-header > div.bili-header__bar > ul.left-entry > li:nth-child(8) > div > a")).click();
        //css定位到动态看是否可以成功
        driver.findElement(By.cssSelector("#i_cecream > div.bili-feed4 > div.bili-header.large-header > div.bili-header__channel > div.channel-icons > a:nth-child(1) > div")).click();
        //截图看是否跳转成功
        //要使用类名.class.getName
        Thread.sleep(2000);
        getPicture(Demo1.class.getName());
        driver.quit();
    }

我们可以看到这次是成功的,但是有了新的问题,我们目的是截图动态页面,但是结果却是起始页面,我们尝试来解决一下

⭐解决方法:

我们可以通过切换窗口的方法来解决这个问题

1.2.1 我们先获取初始页面的句柄

1.2.2 我们通过css选择器定位元素切换窗口后,我们可以打印出来所有的句柄

1.2.3 我们可以看到切换页面后句柄是不一样的,所以我们就可以通过切换句柄来转移到新的标签页,这样就可以操作新的标签页了

1.2.4 可以截图到切换到新页面的样子

1.2.5 完整代码如下:

java 复制代码
    //测试是否可以产生新的页面
    public void jump() throws IOException, InterruptedException {
        //使用css选择器定位元素-高考季
//        driver.findElement(By.cssSelector("#i_cecream > div.bili-feed4 > div.bili-header.large-header > div.bili-header__bar > ul.left-entry > li:nth-child(8) > div > a")).click();
        //css定位到动态看是否可以成功
        //我们可以使用数组来达到切换页面的过程
        //在切换页面前,我们先保存起始页面的句柄
        String windowHandle = driver.getWindowHandle();
        System.out.println(driver.getWindowHandle()); //获取当前的句柄
        //跳转页面
        driver.findElement(By.cssSelector("#i_cecream > div.bili-feed4 > div.bili-header.large-header > div.bili-header__bar > ul.left-entry > li:nth-child(5) > a > span")).click();
        //跳转后获取全部的句柄
        System.out.println("================");
        Set<String> windowHandles = driver.getWindowHandles();
        System.out.println(driver.getWindowHandles());
        //切换窗口
        for (String w : windowHandles) {
            if(w != windowHandle){
                //切换窗口
                driver.switchTo().window(w);
            }
        }
        Thread.sleep(2000);
//        截图看是否跳转成功
        //要使用类名.class.getName
        getPicture(Demo1.class.getName());
        //这里我们可以先关闭切换的页面,再关闭全部的
        driver.close();
        driver.quit();
    }