Selenium和Sikulix【JAVA】【找不到元素,切换面板】


文章目录

  • 前言
  • 一、Selenium和Sikulix是什么?
  • 二、Selenium
    • 1.环境准备
    • 2.浏览器相关操作
    • 3.定位元素
    • 4.执行JS脚本
    • 5.鼠标键盘操作
    • 6.操作控件
      • 复选框
      • 下拉列表
      • 单选按钮
      • 悬浮多级菜单
      • 点击下拉菜单
    • 7.处理弹窗
    • 跳转页面处理
    • 8.获取页面源码
    • 9.找不到页面元素
      • 元素加载前就定位
      • 页面切换后找不到元素
      • 页面有嵌入式元素
  • 三、Sikulix
    • 1.环境准备
    • 2.方法
      • 定位方法:
      • 鼠标操作
      • 键盘操作


前言

最近要做一个自动化数据填充的项目,领导说要用Selenium和Sikulix
给的要求是要用jar包,通过Java编写
但是翻遍论坛、官网,都是用Python或者其可视化界面的说明,而且这都少之又少
于是想自己写个总结的,也方便之后项目开发查阅

注:这篇文章只是介绍主要方法(我用到的),具体还有很多其他的,自行查阅吧^ - ^


一、Selenium和Sikulix是什么?

自动化测试工具
selenium主要用于B/S架构,即浏览器
sikulix主要用于C/S架构,即客户端
通俗讲,涉及到网页,就可以用Selenium;若不是网页,就可以使用Sikulix


二、Selenium

1.环境准备

因为要操作浏览器,除了要下载Selenium的jar包外,还要下载浏览器驱动:
下载的驱动版本要一致

Selenium:
1、selenium-java-2.48.0.jar
2、selenium-server-standalone-2.48.0.jar
<<<我是下载地址>>>
浏览器驱动:
<<>>
<<>>
<<>>
<<>>

配置浏览器代码如下:

//设置浏览器驱动路径
System.setProperty("webdriver.ie.driver","C:\\IEDriverServer.exe")
//一般是启动对应驱动的默认浏览器,也可以手动指定浏览器的安装路径
System.setProperty("webdriver.firefox.bin", "E:/firefox.exe");

2.浏览器相关操作

代码 功能
WebDriver driver = new InternetExplorerDriver() 创建IE浏览器驱动
对应的,还有其他浏览器驱动:
* FirefoxDriver 火狐
* ChromeDriver 谷歌
即new的对象替换成对应的浏览器名字即可
driver.get(“www.baidu.com”) 打开指定网址
driver.manage().window().maximize() 最大化窗口
driver.quit() 关闭浏览器

示例代码如下:

//启动IE浏览器
//1.设置浏览器驱动路径
System.setProperty("webdriver.ie.driver","C:\\IEDriverServer.exe")
//2.创建驱动
WebDriver driver = new InternetExplorerDriver();
//3.打开百度
driver.get("http://localhost:8080/heima");
//4.最大化窗口
driver.manage().window().maximize();
//5.关闭浏览器
driver.quit();

3.定位元素

代码 功能
driver.findElement(By.id(“元素id”)) 根据id获取元素
driver.findElement(By.partialLinkText(“文本”)) 根据超链接的文本进行模糊获取
linkText()是全匹配
driver.findElement(By.tagName(“元素标签”)) 根据标签获取元素,例如所有的input标签
driver.findElement(By.xpath(“路径”)) 根据xpath定位元素

一般除了id获取,其他方式获取都会获取到多个元素,此时应该用driver.findElements()方法
获取的元素类型为:List< WebElement>

示例代码如下:

//1、根据id获取元素
WebElement input = driver.findElement(By.id("kw"));
//2、根据超链接文本的部分内容获取元素
WebElement aHref = driver.findElement(By.partialLinkText("百度百科"));
//3、根据tag_name + xPath获取元素
driver.findElements(By.xpath("//*[@id=\"app\"]/select[1]"));

4.执行JS脚本

应用场景:
1、WebElement元素有click方法,用来触发单击事件,但是IE浏览器对该方法不支持,所以需要用到JS
2、WebElement元素有sendKeys方法,用来输入信息,但是实际会输入很慢,可以直接用JS改变value属性

代码 功能
driver.executeScript(js字符串, 元素) 执行js代码

示例代码如下:

//-------------点击-------------
//创建IE驱动
WebDriver driver = new InternetExplorerDriver();
//定义点击js
String js = "arguments[0].click()";
//获取元素
WebElement input = driver.findElement(By.id("kw"));
//执行
((InternetExplorerDriver) driver).executeScript(js, input);

//-------------输入信息-------------
String js = "document.getElementById('kw').value='Eugenema'";
((InternetExplorerDriver) driver).executeScript(js);

5.鼠标键盘操作

代码 功能
element.sendKeys(Keys.ENTER) 向element元素中输入回车
driver.getMouse().mouseMove(element.getCoordinates()) 鼠标悬停
driver的类型不能是WebDriver
element的类型是RemoteWebElement
常用键盘代码
代码 功能
Keys.ENTER 回车
Keys.CONTROL, ‘a’ Ctrl + A
Keys.UP 上方向键

示例代码如下:

//-------------获取超链接元素,鼠标悬停其上-------------
RemoteWebElement aHref = (RemoteWebElement) driver.findElement(By.partialLinkText("A班"));
((InternetExplorerDriver) driver).getMouse().mouseMove(aHref.getCoordinates());
//-------------获取输入文本框,向文本框输入回车-------------
WebElement input = driver.findElement(By.id("kw"));
input.sendKeys(Keys.ENTER);

6.操作控件

复选框

通过xPath获取所有复选框,全选
示例代码如下:

List<WebElement> input = driver.findElements(By.xpath("//input[@type='checkbox']"));
String js = "arguments[0].click()";
for (WebElement webElement : input) {
    if(webElement.getAttribute("checked") == null){
        //表示未选中
        ((InternetExplorerDriver) driver).executeScript(js, webElement);
    }
}

下拉列表

通过标签获取所有下拉列表,选中特定选项
示例代码如下:

List<WebElement> selects = driver.findElements(By.tagName("select"));

//将第一个下拉列表创建成对象
Select select = new Select(selects.get(0));
//获取所有选项
List<WebElement> options = select.getOptions();
//找到“湖南省”选项并选中
for (WebElement option : options) {
    if(option.getText().equals("湖南省")){
        option.click();
    }
}

//将第二个下拉列表创建成对象
select = new Select(selects.get(1));
//获取所有选项
options = select.getOptions();
//找到“湘潭市”选项并选中
for (WebElement option : options) {
    if(option.getText().equals("湘潭市")){
        option.click();
    }
}

单选按钮

通过xpath获取所有单选按钮,将第一个未选中的选中
示例代码如下:

List<WebElement> audios = driver.findElements(By.xpath("//input[@type='radio']"));
js = "arguments[0].click()";
for (WebElement audio : audios) {
    if(!audio.isSelected()){
        ((InternetExplorerDriver) driver).executeScript(js, audio);
    }
}

悬浮多级菜单

将鼠标移到某父级菜单上,显示下一级菜单
示例代码如下:

RemoteWebElement aHref = (RemoteWebElement) driver.findElement(By.partialLinkText("A班"));
((InternetExplorerDriver) driver).getMouse().mouseMove(aHref.getCoordinates());

点击下拉菜单

鼠标点击父级菜单指定位置,调出下一级菜单
示例代码如下:

WebElement element = driver.findElement(By.xpath("//*[@id=\"menu\"]/ul/li[2]/span"));
clickJs(element);
clickJs(driver.findElement(By.partialLinkText("菜单 2-1")));


public static void clickJs(WebElement element){
    String js = "arguments[0].click()";
    ((InternetExplorerDriver) driver).executeScript(js, element);
}

7.处理弹窗

一般有alert弹窗、confirm弹窗以及能够输入信息的prompt弹窗
示例代码如下:

//1、处理alert弹窗
driver.switchTo().alert().accept();
//2、处理confirm弹窗
driver.switchTo().alert().dismiss();   //点击取消
driver.switchTo().alert().accept();   //点击确认
//3、处理prompt弹窗
System.out.println(driver.switchTo().alert().getText());//获取弹窗提示文本
driver.switchTo().alert().sendKeys("Eugenema输入信息");  //向窗口输入文本
driver.switchTo().alert().accept();  //点击确认

跳转页面处理

当页面通过超链接等途径跳转到新页面时,想要获取新页面上的元素,就需要切换
Selenium通过页面标志来定位页面,所以要切换页面就需要知道新页面的标志

代码 功能
driver.getWindowHandle() 获取当前页面的标志
driver.getWindowHandles() 获取所有页面的标志
driver.switchTo().window(“页面标志”) 切换到指定页面

示例代码:

//获取当前窗口
String current_handle = driver.getWindowHandle();
//获取所有窗口
Set<String> windowHandles = driver.getWindowHandles();
//遍历窗口,找到新窗口就跳转
Iterator<String> it = windowHandles.iterator();
while(it.hasNext()){
    //若是当前窗口,就跳过
    String next = it.next();
    if(next == current_handle){
        continue;
    }
    //跳入新窗口
    WebDriver new_driver = driver.switchTo().window(next);
}
//切换回旧窗口
driver.switchTo().window(current_handle);

如果切换页面后找不到元素了,但是新页面有该元素,可以通过下面获取页面源码driver.getPageSource(),查看当前driver是在哪个页面上,再决定是否切换页面

8.获取页面源码

代码 功能
driver.getPageSource() 获取页面的源码
element.getAttribute(“innerHTML”) 获取该元素的源码

9.找不到页面元素

首先,找不到元素有多种情况,除了上面页面跳转,还有以下情况:

  1. id写错 / path写错(这基本不太可能)
  2. 页面元素未加载就开始定位元素
  3. 循环遍历列表元素进行操作
  4. 页面有嵌入式元素

现在就来聊一下如何去解决~

元素加载前就定位

这个问题一般出现在网页打开速度较慢的情况,此时可能元素还未加载出来,自然就无法定位了
那么解决办法就是:等!
全局隐式等待
这也是官方给出的解决办法,推荐使用

m_oDriver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);

参数为:时间,时间单位
上述语句的作用是等待5秒,隐式全局等待
隐式等待:全局化设置,在规定时间内寻找元素。寻找到则继续执行;寻找不到则继续寻找。直到规定时间未找到,抛出异常
显式等待:对每一次寻找做等待限制。显式等待可自定义找到和未找到动作,非全局(这里不做讲解)

下面模拟找不到元素的情况:

	/**指定IE驱动路径*/
	private static String g_oDriverPath = System.getProperty("user.dir") + File.separator
			+ "webDriver" + File.separator + "IEDriverServer.exe";
	public static void main(String[] args) throws Exception {
		//设置IE驱动
		System.setProperty("webdriver.ie.driver", g_oDriverPath);
		//打开IE窗口
		WebDriver m_oDriver = new InternetExplorerDriver();
		
		//全局设置等待时间
		m_oDriver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
		
		//查找元素
		m_oDriver.findElement(By.id("nihai"));
	}
//未开启全局等待
javaException in thread "main" org.openqa.selenium.NoSuchElementException: Unable to find element with id == nihai (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 288 milliseconds

//开启全局等待
Exception in thread "main" org.openqa.selenium.NoSuchElementException: Unable to find element with id == nihai (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 5.12 seconds

可以看到,出错时间有了明显延迟,一个288毫秒,一个5.12秒
不过,在实际项目中可能出现失灵的情况,即全局设置失效!!!
于是就需要手动线程睡眠去解决
不过有个缺点:官方提供的方法,在找到元素后就会停止等待,而如果手动线程睡眠,则必须等待线程唤醒才能去找到元素,不管元素是否已经加载完
所以,建议根据项目实际情况、要求去选择合适的方法

页面切换后找不到元素

一般出现在循环读取数据时,数据编辑页面和显示页面不同导致

	//打开IE窗口
	WebDriver m_oDriver = new InternetExplorerDriver();
	//进入网页
	m_oDriver.get("www.eugenema.com");
	// 获取所有行数据,list中每一个webElement就是一行数据
	List<WebElement> elements = m_oDriver .findElements(By.xpath("//*[@id=\"form:cdmData:tbody_element\"]/tr"));
	//遍历所有行数据,编辑
	for( int i=0; i<elements.size(); i++){
		//点击编辑按钮
		//进入新的页面开始编辑
		//编辑完,点击完成,自动返回之前学生列表页面
	}

Selenium和Sikulix【JAVA】【找不到元素,切换面板】_第1张图片
在编辑完第一条数据后,从新页面返回去编辑第二条数据时,会报错
这是因为获取所有元素的语句在for循环外面,而selenium认定切换了页面就需要重新获取所有元素,不然之前list里存的都是过期的元素
即将获取所有行元素的语句复制一份在for循环(因为for循环需要知道循环次数,必须在for循环外先获取一次)

页面有嵌入式元素

这种情况出现在一些比较老的项目中(很不幸,我就是在老项目中接触的这项技术 TAT)
也就是 < iframe > 标签,用于在一个页面中嵌套另一个页面
此时如果想获取iframe嵌套页面内的元素,直接定位是不行的,虽然F12能看到元素的id,但是你就是获取不到
需要先切换面板到嵌套页面,再获取

//id是iframe的id
driver.switchTo().frame(driver.findElement(By.id("stframem")));

三、Sikulix

1.环境准备

<<<点击下载Sikulix>>>

2.方法

主要操作对象为Screen
通过识别图片,检测屏幕上与图片相似度最高的区域,获取到坐标

定位方法:

代码 功能
screen.wait(“图片路径” , 时间) 等待某个图片出现,超过指定时间报异常
时间可不写
screen.waitVanish(“图片路径” , 时间) 只有指定图片消失后,才向下执行
时间可不写
screen.find(“图片路径”) 查找相似度最高的图片
返回match对象
可以通过该对象进行点击、获取坐标
screen.findAll(“图片路径”) 查找所有相似度的图片,返回match列表

示例代码:

//图片存放路径:根目录下的image
private static String g_sImagePath = System.getProperty("user.dir") +
            File.separator + "image" + File.separator;
//创建Screen对象
Screen screen = new Screen();
//等待图标出现
screen.wait(g_sImagePath + "图片.png", 100);
//获取某个图片在屏幕上的位置
Match match = screen.find(g_sImagePath + "图片.png");
System.out.println(match.getX() + " " +  match.getY() + "    " + match.getH() + " " + match.getW());

鼠标操作

代码 功能
screen.doubleClick(“图片路径”) 双击指定图片
click即单击
screen.hover(“图片路径”) 将鼠标移动到该处
screen.mouseMove(x , y) 鼠标在原有基础上移动
例如(-50,0),就是左移50
screen.mouseDown(Button.LEFT) 点击鼠标左键
screen.mouseUp() 鼠标松开
screen.dragDrop(match1 , match2) 从match1点击不放鼠标,滑到match2

示例代码:

//单击
screen.click(g_sImagePath + "图片.png");
//双击
screen.doubleClick(g_sImagePath + "图片.png");
//移动到该处
screen.hover(g_sImagePath + "13.png");
//左移50
screen.mouseMove(-50,0);
//点击
screen.mouseDown(Button.LEFT);
screen.mouseUp();
//1、创建match对象
Match match1 = new Match();
match1.setX(933);
match1.setY(10);
Match match2 = new Match();
match2.setX(20);
match2.setY(900);
//2、两种方式:进行拖拽
match1.dragDrop(match2);
//screen.dragDrop(match1,match2);

键盘操作

代码 功能
screen.type(Keys.CAPS_LOCK) 按下大写锁定键参数还可以是字符串,代表输入该字符串
screen.type(“m”,Key.WIN) 最小化所有窗口

示例代码:

//图片存放路径:根目录下的image
private static String g_sImagePath = System.getProperty("user.dir") +
            File.separator + "image" + File.separator;
//创建Screen对象
Screen screen = new Screen();
//1、最小化所有窗口
screen.type("m", Key.WIN);
//2、等待输入框
screen.wait(g_sImagePath + "输入框.png", 100);
//3、点击输入框
screen.click(g_sImagePath + "输入框.png");
//4、输入文字
screen.type("D:\\Configpath");
//5、敲回车
screen.type(Keys.ENTER);

你可能感兴趣的:(技术学习,selenium,java,定位)