selenium(一)基于java、元素定位

Selenium自动化

Selenium是一个用于Web应用程序的自动化测试工具。它直接运行在浏览器中,可以模拟用户在浏览器上面的行为操作。

chrome下载

https://www.google.com/chrome/

下载的结果是 "ChromeSetup.exe",双击该文件,安装程序会自动启动。

默认安装位置:C:\Program Files\Google\Chrome\Application\chrome.exe

结果我的在:C:\Users\91073\AppData\Local\Google\Chrome\Application\chrome.exe

。。。为啥?


下载驱动

最新版:Chrome for Testing availability

查看谷歌浏览器版本

谷歌浏览器输入网址的地方输入:chrome://version
下载与浏览器对应(或相近)版本的浏览器驱动:http://chromedriver.storage.googleapis.com/index.html

备用地址:CNPM Binaries Mirror

解压后得到一个chromedriver.exe驱动文件


禁用自动升级

关闭自动升级方法:

1.右键单击【计算机】------【管理】------【计算机管理本地】------【系统工具】------【任务计划程序】------【任务计划程序库】------这里找到两个和Google自动更新相关的任务计划【GoogleUpdateTaskMachineCore】与【GoogleUpdateTaskMachineUA】,把这两个选项禁用。


2.在【服务和应用程序】------【服务】,这里找到了两个和Google更新相关的服务【Google更新服务(gupdate)】、【Google更新服务(gupdatem)】,右键------选择属性------启动类型禁用即可;


卸载谷歌浏览器

在卸载当前版本之前,建议备份你的书签、扩展、密码等资料。

  1. 通过Windows + R快捷键调出"运行"对话框。
  2. 键入APPWIZ.CPL和命中输入。

这将带您到所有已安装应用程序的列表。从列表中选择Google Chrome,然后点击卸载 命令。


降级版本

版本报错

Caused by: org.openqa.selenium.SessionNotCreatedException: session not created: This version of ChromeDriver only supports Chrome version 114
Current browser version is 116.0.5845.97 with binary path C:\Users\91073\AppData\Local\Google\Chrome\Application\chrome.exe

Google浏览器历史版本下载地址

Download older versions of Google Chrome for Windows, Linux and Mac

按住alt键,双击桌面的谷歌浏览器桌面图标

拷贝目标路径:C:\Users\lenovo\AppData\Local\Google\Chrome\Application\chrome.exe

打开命令提示符,输入如下并回车键;

cd C:\Users\lenovo\AppData\Local\Google\Chrome\Application

输入"chrome.exe--disable-remote-words-auto-upgrade--version=版本号",然后按回车键。在这里,请将"版本号"替换为所需的版本号。


Selenium入门

maven坐标

打开selenium的仓库地址 : https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java

直接拷贝到pom文件吧,,

XML 复制代码
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.5</version>
</dependency>

<!-- 测试工具testng-->
<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>6.14.3</version>
    <scope>test</scope>
</dependency>

入门案例

如果浏览器驱动未加入环境变量,那么创建浏览器驱动的时候,需要指定浏览器驱动的路径

java 复制代码
public class Client {

    public static void main(String[] args) throws InterruptedException {
        //配置浏览器驱动地址
        System.setProperty("webdriver.chrome.driver", "D:\\tools\\chrome\\driver113\\chromedriver.exe");
        //打开Chrome浏览器
        WebDriver webDriver = new ChromeDriver();
        TimeUnit.SECONDS.sleep(5);
        //打开百度网站
        webDriver.get("https://www.baidu.com");
        TimeUnit.SECONDS.sleep(2);
        //输入框输入搜索关键词 selenium 中文官网
        webDriver.findElement(By.id("kw")).sendKeys("selenium 中文官网");
        TimeUnit.SECONDS.sleep(2);
        //点击百度一下按钮
        webDriver.findElement(By.id("su")).submit();
        TimeUnit.SECONDS.sleep(2);
        //查询所有搜索的结果
        List<WebElement> resultElements = webDriver.findElements(By.className("result"));
        if (!resultElements.isEmpty()) {
            //找到第一条结果的第一个链接
            List<WebElement> aTagElements = resultElements.get(0).findElements(By.tagName("a"));
            if (!aTagElements.isEmpty()) {
                //新开一个窗口打开此链接
                String href = aTagElements.get(0).getAttribute("href");
                System.out.println(href);
                ((JavascriptExecutor) webDriver).executeScript(String.format("window.open('%s')", href));
            }
        }
        TimeUnit.SECONDS.sleep(10);
        //关闭浏览器
        webDriver.quit();
    }
}

结果,很神奇的哦


命令行打开浏览器

java 复制代码
new ChromeDriver(options);

如果希望Chrome 浏览器启动时附带启动参数,可通过addArguments 方式加载。

希望测试某个浏览器插件,可通过addExtensions方式提前加载以.crx 为扩展名的插件

感觉上和addArguments有点类似,不过setExperimentalOption是设置实验选项ChromeDriver选项尚未通过ChromeOptions API公开 ),这个方法我比较经常用来设置浏览器默认下载路径

对于一台机器上安装了多个版本的Chrome浏览器,可以使用setBinary 指定待测试Chrome。

让 selenium 连接我们手动打开的浏览器

打开浏览器有两种方式:图标点击和命令行运行。

图标点击不用多说,我们经常使用这种方式打开浏览器。命令行方式允许我啰嗦一句,找到浏览器的安装目录,在安装目录中输入 chrome.exe 就可以了。 比如我的 chrome 浏览器安装在

C:\Users\91073\AppData\Local\Google\Chrome\Application

这个路径,则在这个目录下打开 cmd 命令行,输入 chrome.exe,就可以打开一个浏览器

在浏览器打开的时候设置额外的参数,为它提供不同的功能。 通过 selenium 连接浏览器,需要用到两个参数 --remote-debugging-port 和 --user-data-dir

  • --remote-debugging-port 这个参数允许我们通过远程的方式连接,selenium 当然也可以。

  • --user-data-dir 这个参数指定一个独立的目录存放产生的用户数据,在连接时也要设置,否则会失效。

    chrome.exe --remote-debugging-port=9222 --user-data-dir="F:\selenium\ChromeProfile"

有了远程调试地址,selenium 连接浏览器就变的很简单,只需要加 2 行代码。 创建一个选项,绑定debuggerAddress 远程调试地址。 此时就可以用 selenium 控制之前手工打开的浏览器了。

java 复制代码
            //配置浏览器驱动地址
            System.setProperty("webdriver.chrome.driver", "F:\\webrpaTest\\RPA\\RoboticProcessAutomation\\browser\\driver\\chrome\\121\\chromedriver.exe");
            ChromeOptions options = new ChromeOptions();
            options.setBinary("C:\\Users\\91073\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe");
            //设置 Chrome 的远程调试端口地址
            options.setExperimentalOption("debuggerAddress", "127.0.0.1:9222");
//            WebDriver driver = new ChromeDriver(ChromeDriverService.createDefaultService(), options);
            WebDriver driver = new ChromeDriver(options);
            System.out.println(driver.getTitle());

WebDriver 实例化参数

Chome浏览器部分

executable_path:浏览器驱动程序路径,如果没有制定,则默认使用环境变量PATH中设置的路径

options:启动选项 (Options对象通常位于各浏览器的 WebDriver 模块下,列如:from selenium.webdriver.浏览器名称.options import Options),建议优先使用options 参数来设置浏览器(options 基于 capabilities,在实例化某个浏览器的Options对象时会自动写入该浏览器预设的 capabilities)

  • service_log_path:驱动程序存放日志文件的位置

  • keep_alive:表示在与 ChromeDriver 进行链接时,是否带上 HTTP 请求头Connection: keep-alive,既是否使用长链接,布尔类型参数,默认值为True

  • service_args:浏览器驱动程序的参数,根据所使用的浏览器驱动不同,参数也有可能不同。

Edge浏览器部分

  • executable_path:浏览器驱动程序路径,如果没有制定,则默认使用环境变量PATH中设置的路径
  • capabilities:非浏览器特定的字典对象,传入浏览器启动参数时需要使用到
    port:驱动程序启用的端口号,如果不填写,则自动使用任意闲置的端口号,默认参数为0
    verbose:是否在服务中设置详细日志记录
    service_log_path:驱动程序存放日志文件的位置
    log_path:不推荐使用的 service_log_path 参数
    keep_alive:表示在与 EdgeDriver 进行链接时,是否带上 HTTP 请求头Connection: keep-alive,既是否使用长链接,布尔类型参数,默认值为True

元素定位

web自动化的难点和重点之一,就是如何 选择 我们想要操作的web页面元素。

id定位

id 定位 driver.findElement(By.id("id的值"));

如果元素有id属性 ,这个id 必须是当前html中唯一的。所以如果元素有id, 根据id选择元素是最简单高效的方式。

  1. 使用WebDriver对象的findElement函数定义一个Web页面元素
  2. 使用findElements函数可以定位页面的多个元素

使用 find_elements 选择的是符合条件的 所有 元素, 如果没有符合条件的元素, 返回空列表

List<WebElement> listOfElements = driver.findElements(By.xpath("//div"));
webElement.findElements(By.tagName("tr"));
  • 如果没有匹配条件的元素,Find Elements命令将返回一个空列表

使用 find_element 选择的是符合条件的 第一个 元素, 如果没有符合条件的元素, 抛出 NoSuchElementException 异常

定位的页面元素需要使用WebElement对象来存储,以便后续使用


class定位

class 定位 driver.findElement(By.className("class属性"));

java 复制代码
 //企查查
 webDriver.get("https://www.qcc.com/");
 TimeUnit.SECONDS.sleep(2);
 //查企业 查老板 查风险 查招标 找关系
 List<WebElement> elements = webDriver.findElements(By.className("search-type"));

class 属性通常用于指向样式表的类

在html中,class规定元素的类名,语法格式为"<元素名称 class="value">"。class属性大多数时候用于指向样式表中的类(class)。

html标签是允许定义多个class类名的。比如:

html 复制代码
<div class = "exp1 exp2"></div>

上边这个div就用到了exp1、exp2这两个class类,对于个数是没有限制,只需每个类名之间用空格隔开就好。


tag 名 定位

TagName 标签名称定位    driver.findElement(By.tagName("标签名称"));

选择所有的tag名为 div的元素,如下所示


name定位

name定位    driver.findElement(By.name("name的值"));

css定位

CSS定位为的优势在于定位速度比Xpath定位快,且比Xpath定位更加稳定

css 方式定位    driver.findElement(By.cssSelector("css表达式"));

Xpath定位

xpath定位方式

xpath 是XML Path的简称, 用于在XML文档中选择文档中的节点。基于XML树状文档结构,Xpath语言可以在整棵树中寻找指定的节点。

java 复制代码
xpath 方式定位
driver.findElement(By.xpath("xpath表达式"));

xpath 有两种表示方法,绝对路径和相对路径,

绝对路径是指从根开始,以/开始,如/html/body/div,

相对路径是指在一个路径下,另外的路径以这个路径作为参照,以//开始。从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。

  • XPath表达式中的//表示在HTML文档的全部层级位置进行查找

举例如下:

java 复制代码
//百度一下
webDriver.get("https://www.baidu.com");
WebElement element = webDriver.findElement(By.xpath("//*[@id='su']"));

这里 为啥是**//*[@]** 呢?

  • //表示从任意位置去查找
  • *是标签名
  • @是属性定位

强烈建议使用相对路径和属性值结合的定位方式来编写xpath定位表达式。如

java 复制代码
By.xpath("//*[@id='su']")

xpath获取

xpath获取技巧:网页的html是一种特殊的XML文档。使用浏览器调试工具,可以直接获取xpath语句

右键-检查(或者F12),然后点击这个箭头,就可以在浏览器上选择元素了

使用Chrome 来直接获取元素的XPath.

通过层级关系和索引定位(索引从1开始):

XML 复制代码
//*[@id="content"]/div/div[2]/div[4]/div[2]/h2/div[2]/form/div

标签+属性定位

XPath通过idnameclass属性定位。语法如下:

//标签名[@属性名='属性值']
java 复制代码
//用XPath通过id属性定位  
element1 = driver.find_element_by_xpath("//input[@id='kw']")

//用XPath通过name属性定位  
element2 = driver.find_element_by_xpath("//input[@name='wd']")

//用XPath通过class属性定位  
element3 = driver.find_element_by_xpath("//*[@class='s_ipt']")

总结

  1. 如果不想制定标签名称,可以用*号表示任意标签。
  2. 有时候同一个属性,同名的比较多,这时候可以通过标签筛选下,定位更准一点。
  3. 如果想制定具体某个标签,就可以直接写标签名称

List pageUl = ar.driver.findElements(By.xpath("//ul[@class='bfe-pager']"));//获取页数


层级定位

通过层级关系定位,注意:最终定位的是子标签....语法如下:

 //父标签名[@父标签属性名='属性值']/子标签

在页面中,定位下面代码片段中的<input>标签

html 复制代码
<p id="p1">
    <label for="userA">账号A</label>
    <input required="" value="">
</p>

答案如下:

java 复制代码
driver.find_element_by_xpath("//p[@id='p1']/input")

索引定位

索引定位元素,语法如下:

bash 复制代码
//父标签名[@父标签属性名='属性值']/子标签[索引值]   索引从1开始

比如我要定位如下图片的"京东家电连接"


答案是:

bash 复制代码
//*[@id=\"navitems-group1\"]/li[2]/a

用id="navitems-group1"定位到如下图片这里,这些是一些li标签

//*[@id="navitems-group1"]/li[1]/a

//*[@id="navitems-group1"]/li/a

注意:如果是第一个元素,索引值可以不加。因为不加索引值会选取ul下的全部li标签

而我们用的是单数定位形式,默认选择第一个。


文本定位

bash 复制代码
//标签名[text()='文本']

xpath定位时,定位某一元素不好定时,可以定位其子级元素,然后通过 /... 定位到它的父级元素

bash 复制代码
HTML实例:<button type="button" class="ant-btn ant-btn-primary"><span>新 建</span></button>
xpath定位://span[text()='搜 索']/..

逻辑定位

XPath逻辑定位说明:

  1. xpath还有一个比较强的功能,可以支持与(and)、或(or)、非(not)。
  2. 一般用的比较多的是and运算,同时满足两个属性。

比如一个日期输入框无法输入

1

//获取当前页所有的数据
List datasaaa = ar.driver.findElements(By.xpath("/html/body/div[11]/table/tbody/tr/td[not(contains(@class, \"outMonthDay\"))]"));	 
System.out.println("datasaaa.size():"+datasaaa.size());
for(int i=0;i<datasaaa.size();i++){
    String text=datasaaa.get(i).getText().trim();
	System.out.println("text:" + text);
	if(Integer.parseInt(text)==day1){
		datasaaa.get(i).click();
		break;
	}
}

判断元素是否存在

场景:比如银行某些账号的对账提醒,但是不是所有的账号都有。所以要先判断元素是否存在

捕获异常方式

捕获异常是使用f**indElement()**方法无法获取元素则会抛出异常,如果找到元素则会返回True

java 复制代码
//通过异常判断
public static boolean isElementExist(WebDriver driver, String xpath) {
    try {
        WebElement element = driver.findElement(By.xpath(xpath));
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

弊端:只要页面上有元素,不几个,都返回True

比如:在打开百度贴吧的时候,会有登录提醒。做一个判断,如果存在则关闭该弹窗

java 复制代码
driver.get("https://tieba.baidu.com/");
//只需要设置一次,所有的元素都可有最多 10s 的等待加载的时间(默认0)
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
//判断xpath是否存在,存在则点击关闭弹窗
boolean exist = isElementExist(driver, "//*[@id=\"tiebaCustomPassLogin\"]/div[2]/span");

父子、兄弟、相邻节点定位方式

相邻节点定位

比如,我要获取表格的总记录数。此时因为一个变化的值,

如果查询条数少,只有一页。则获取页数可以用xpath :/ul/li[5]/b

如果查询条数过多,则xpath发生变化:/ul/li[6]/b

此时,是否可以用兄弟节点定位。通过">"来定位。">"是可以用属性定位的//a[@class=\"next\"]


获取文本

//h5[text()='可用余额'

//span[text() = '全部']/parent::label/span[1]

子节点定位父节点

result = html.xpath('//a[@id="parentSpan"]/text()')

获取 href 属性

# 8、获取 href 属性
result = html.xpath('//a[@id="parentSpan"]/@href')
相关推荐
智慧老师8 分钟前
Spring基础分析13-Spring Security框架
java·后端·spring
lxyzcm10 分钟前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
V+zmm1013443 分钟前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
oneouto1 小时前
selenium学习笔记(二)
笔记·学习·selenium
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-13141 小时前
常用的缓存技术都有哪些
java
炭烤玛卡巴卡1 小时前
学习postman工具使用
学习·测试工具·postman
AiFlutter2 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
J不A秃V头A2 小时前
IntelliJ IDEA中设置激活的profile
java·intellij-idea
DARLING Zero two♡2 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode