一、元素等待
1、硬性等待(不推荐)
// 会一直等到设置的睡眠时间结束,造成时间浪费,一般调试用
Thread.sleep(long millis);
2、隐式等待
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5)); // 等待元素5秒
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(5)); // 等待页面加载5秒
driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(5)); // 等待脚本加载5秒
3、显示等待
import org.openqa.selenium.support.ui.WebDriverWait; // 导入界面等待包
import org.openqa.selenium.support.ui.ExpectedConditions; // 导入界面意外状况包
import java.time.Duration; // 持续时间对象包。。
// 等待元素可被点击
WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(10));
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[text()='官方']"))).click();
显示等待常用等待方法:
方法 | 等待条件 |
---|---|
presenceOfElementLocated | 页面元素在页面中存在 |
visibilityOfElementLocated | 页面元素在页面存在并且可见 |
elementToBeClickable | 页面元素是否在页面上可用和可被单击 |
frameToBeAvailableAndSwitchToIt | 切换到iframe中,返回值为boolean类型 |
二、窗口切换
driver.swithTo()
1.切换frame
// frame有id或name时可直接传入id或name。其它时候先定位元素,再传入元素
driver.switchTo().frame(iFrameIdOrName);
// 还可以直接获取到frame元素 进行切换
driver.switchTo().frame(frameElement);
// 如果外层没有写明的iframe 则可直接跳到ParentFrame
driver.switchTo().parentFrame(frameElement);
2.切换窗口
driver.switchTo().window(); // 传入窗口句柄
driver.switchTo().defaultContent(); // 切换回主窗口
多窗口切换示例:
//获取所有窗口句柄
Set<String> windowHandles = driver.getWindowHandles();
// 遍历个句柄 找到标题与目标窗口标题一致的窗口句柄
for (String windowHandle:windowHandles
) {
if(!driver.getTitle().equals("titileName")){
// 切换到目标窗口
driver.switchTo().window(windowHandle);
}
}
3.切换弹出框
driver.switchTo().alert();
附:工具类(简化复杂操作)
这个是网络上收集的,供大家参考吧!
- 最优初Selenium 始化
- 代理
- 显示等待
- 强制等待
- 隐式默认等待
- 截图
- 支持多线程并发
package com.reptile;
import com.file.ReadWriteFileUtils;
import lombok.SneakyThrows;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 简要描述
*
* @Author: huanmin
* @Date: 2022/7/18 17:27
* @Version: 1.0
* @Description: 文件作用详细描述....
*/
public class ChromeDriverUtil {
//文件版本,防止多线程缓存文件和用户文件共享,导致创建错误
private static AtomicInteger fileSerial=new AtomicInteger(0);
private ChromeDriver driver;
public ChromeDriverUtil(String path, boolean pd, boolean img) {
init(path, pd, img);
}
@SneakyThrows
private void init(String path, boolean pd, boolean img) {
System.setProperty("webdriver.chrome.driver", path);
ChromeOptions options = new ChromeOptions();
if (!pd) {
options.addArguments("--headless"); //无浏览器模式
}
options.addArguments("--disable-gpu"); // 谷歌文档提到需要加上这个属性来规避bug
options.addArguments("--disable-software-rasterizer"); //禁用3D软件光栅化器
options.addArguments("--no-sandbox");// 为了让linux root用户也能执行
// 优化参数
options.addArguments("--disable-dev-shm-usage"); //解决在某些VM环境中,/dev/shm分区太小,导致Chrome失败或崩溃
if (img) {
options.addArguments("blink-settings=imagesEnabled=false"); //禁止加图片,如果爬取图片的话,这个不能禁用
options.addArguments("--disable-images");
}
String tmpdir = System.getProperty("java.io.tmpdir");
String dir = tmpdir + File.separator + "chrome_file_data_cache"+File.separator+fileSerial.incrementAndGet();
File file1 = new File(dir+File.separator + "data");
if(file1.exists()){
file1.mkdirs();
}
File file2 = new File(dir+File.separator + "cache");
if(file2.exists()){
file1.mkdirs();
}
options.addArguments("--user-data-dir=" + file1.getAbsolutePath()); //解决打开页面出现data;空白页面情况,因为没有缓存目录
options.addArguments("--disk-cache-dir=" + file2.getAbsolutePath()); //指定Cache路径
options.addArguments("--incognito") ; //无痕模式
options.addArguments("--disable-plugins"); //禁用插件,加快速度
options.addArguments("--disable-extensions"); //禁用扩展
options.addArguments("--disable-popup-blocking"); //关闭弹窗拦截
options.addArguments("--ignore-certificate-errors"); // 禁现窗口最大化
options.addArguments("--allow-running-insecure-content"); //关闭https提示 32位
options.addArguments("--disable-infobars"); //禁用浏览器正在被自动化程序控制的提示 ,但是高版本不生效
if (!pd) {
//无浏览器模式-最大化窗口 ,防止有些元素被隐藏
int screenWidth = ((int) java.awt.Toolkit.getDefaultToolkit().getScreenSize().width);
int screenHeight = ((int) java.awt.Toolkit.getDefaultToolkit().getScreenSize().height);
options.addArguments("window-size=" + screenWidth + "," + screenHeight);
}
//随机设置请求头
options.addArguments("--user-agent=" + UserAgent.getUserAgentWindows());
proxy(options, false); //设置代理 ,true 开启代理
driver = new ChromeDriver(options);//实例化
if (pd) {
driver.manage().window().maximize(); //界面的方式, 最大化窗口, 防止有些元素被隐藏,无界面就不要使用了
}
//当我们去定位页面元素时,如果元素没有找到,不会立即抛出异常,而是周期性地(通常为 0.5s)去重新寻找,直到该元素找到或者超过最大等待时间才结束 ,超时后就报错NoTouchElementException
//当我们使用implicitly_wait()时,如果想要定位的元素已经找到,但是它的内容(如文本内容,属性等)没有加载出来,此时隐式等待无效,仍会直接抛出NoSuchElementException异常,这也是为什么我们很多时候仍需要使用time.sleep()的原因。
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
}
//无头模式,不加载图片
public static ChromeDriverUtil buildHide(String path) {
return new ChromeDriverUtil(path, false, true);
}
//无头模式,加载图片
public static ChromeDriverUtil buildHideImg(String path) {
return new ChromeDriverUtil(path, false, false);
}
//显示游览器 ,全功能
public static ChromeDriverUtil build(String path) {
return new ChromeDriverUtil(path, true, false);
}
public ChromeDriver getDriver() {
return driver;
}
//强制等待 代码在执行到某个位置时强制等待一段时间
@SneakyThrows
public void sleep(long ms) {
Thread.sleep(ms);
}
// 显示等待,是为了解决隐式等待遗留的问题,比如元素显示了,但是内部的文本没有显示出来,可能文本是通过ajax异步的会比较慢
public WebElement wait(int seconds, ExpectedCondition<WebElement> expectedCondition) {
WebDriverWait webDriverWait = new WebDriverWait(driver, seconds);
//返回null或者false,等待500毫秒继续尝试,直到过期
WebElement until = webDriverWait.until(expectedCondition);
return until;
}
//自行扩展, 从接口中读取,或者从文件中读取都行
private void proxy(ChromeOptions options, boolean pd) {
if (pd) {
String prox = "101.200.127.149:" + 3129;
Proxy p = new Proxy();
p.setHttpProxy(prox);//http
// p.setFtpProxy(prox); //ftp
// p.setSslProxy(prox);//ssl
// p.setSocksProxy(prox); //SOCKS
// p.setSocksUsername("");
// p.setSocksPassword("");
options.setProxy(p);
}
}
//截图
public void screenshotPNG(TakesScreenshot takesScreenshot, File file) {
byte[] screenshotAs1 = takesScreenshot.getScreenshotAs(OutputType.BYTES);
ReadWriteFileUtils.writeByte(screenshotAs1, file);
try (
FileOutputStream fos1 = new FileOutputStream(file);
BufferedOutputStream fos = new BufferedOutputStream(fos1);
) {
fos.write(screenshotAs1, 0, screenshotAs1.length); // 写入数据
} catch (Exception e) {
e.printStackTrace();
}
}
}
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END