zoukankan      html  css  js  c++  java
  • selenium 使用入门三(dom元素定位、异常处理)

    一、selenium 定位网页中的元素

    查看WebDriver类,可以看到:

        java.util.List<org.openqa.selenium.WebElement> findElements(org.openqa.selenium.By by);
        org.openqa.selenium.WebElement findElement(org.openqa.selenium.By by);
    

    也就是说,定位元素主要通过findElement的传参By by,再进入By类可以看到:
    主要有以下几种方法:

    public static org.openqa.selenium.By id(java.lang.String id) { /* compiled code */ }
    
        public static org.openqa.selenium.By linkText(java.lang.String linkText) { /* compiled code */ }
    
        public static org.openqa.selenium.By partialLinkText(java.lang.String partialLinkText) { /* compiled code */ }
    
        public static org.openqa.selenium.By name(java.lang.String name) { /* compiled code */ }
    
        public static org.openqa.selenium.By tagName(java.lang.String tagName) { /* compiled code */ }
    
        public static org.openqa.selenium.By xpath(java.lang.String xpathExpression) { /* compiled code */ }
    
        public static org.openqa.selenium.By className(java.lang.String className) { /* compiled code */ }
    
        public static org.openqa.selenium.By cssSelector(java.lang.String cssSelector) { /* compiled code */ }
    
        public org.openqa.selenium.WebElement findElement(org.openqa.selenium.SearchContext context) { /* compiled code */ }
    
        public abstract java.util.List<org.openqa.selenium.WebElement> findElements(org.openqa.selenium.SearchContext searchContext);
    

    使用id ameclassName定位,查找元素id属性为kw

    WebElement element = driver.findElement(By.id("kw"));
    

    同理,name(),className(),也是依次查找nameclass值来定位元素

    linkTextpartialLinkText定位,查找超链接的文本

    html示例

    <a class="title-content c-link c-font-medium c-line-clamp1" href="https://www.baidu.com/" target="_blank"><span class="title-content-index c-index-single c-index-single-hot1">1</span><span class="title-content-title">31省区市新增确诊25例 本土15例</span><span class="title-content-mark c-text c-gap-left-small c-text-new">新</span></a>
    
    driver.findElement(By.linkText("https://www.baidu.com/"));       // 精确匹配
    driver.findElement(By.partialLinkText("baidu"));                          // 模糊匹配
    

    cssSelector定位

    查找某元素使用了指定的css样式

    driver.findElement(By.cssSelector(".c-index-single-hot1"));
    

    xpath定位(推荐使用)

    xpath是个人比较推荐的用法,可以用来实现几乎所有元素查找的功能

    By.xpath("//div[@id='kw']")    // id定位
    By.xpath("//span[@class='title-content-title']")   //class精确定位
    By.xpath("//span[contains(@class,'c-index-single-hot1')]")  // class 模糊定位
    By.xpath("//a[contains(@class,'c-line-clamp1') and @target='_blank']")  // 使用and实现更精确的匹配(如图)
    By.xpath("//li[@class='hotsearch-item odd']/a[1]")   // 通过定位父级来查找子级
    By.xpaht("//li[@class='bui-pagination-num'][last()]")  // 获取最后一个复合条件的li元素
    By.xpath("//a[contains(@class,'c-line-clamp1')/..")  // 通过定位a链接,查找到父级li
    By.xpath("//a[contains(@class,'c-line-clamp1') and @target='_blank']/../span[2]") // 通过定位a链接,查找到父级li,再查找同级的span
    

    二、异常处理

    1.网页更新导致或代码定位没写对时,会导致元素查找失败,因此查找元素需要抛异常(不推荐)

    try {
        driver.findElement(By.partialLinkText("baidu"));
    }catch (Exception exception) {
        exception.printStackTrace();
    }
    

    2.通过findElements来代替findElement

    List<WebElement> elements = driver.findElements(By by);
    if(elements.size() > 0) {
    	// 操作
    }else {
    	System.out.println("查找不到当前元素!");
    }
    

    三、查找元素等待时间

    一般情况下,查找的元素都是比较重要的元素,在查找之前,要先判断网页的dom树是否渲染加载完成,这是findElement存在多个等待时间:

    driver.get("https://www.baidu.com");    # 加载流程
    Thread.sleep(3000);         # 硬性等待3秒,有些页面通过js渲染dom树
    driver.findElement(By.partialLinkText("baidu"));  # 查找元素
    

    上面流程,实际操作会遇到几种情况:

    1.driver.get()操作设置非阻塞模式

    网页加载过于缓慢(图片、js等过多), 或者网络卡顿,此时driver.get()的时间就会过长。可以通过设置PageLoadStrategy属性来优化, 这样get()操作不会阻塞进程,get瞬间,同时开始执行后续操作。

    ChromeOptions chromeOptions = new ChromeOptions();
    chromeOptions.setPageLoadStrategy(PageLoadStrategy.NONE);
    ChromeDriver driver = new ChromeDriver(chromeOptions);
    

    2.findElement和findElments等隐性等待时间

    但是,这样也存在一个问题,就是网页加载完成与否,无法判断,因此需要一个时间等待来响应,常见的有Thread.sleep,之后执行findElement。findElement等待操作的过程,也是一个n秒有效时间内查找等待网页刷新,再查找的过程。这里的n秒有效时间,也就是隐性等待时间,可以设置(一般不推荐太长,避免程序在查找不到元素的时候等待时间过长):

    driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    

    3.通过WebDriverWait来实现等待时间控制:

    seconds,就是指定的等待时间

    public static boolean isVisibility(WebDriver driver,int seconds,String... xpathExpressions) {
            for (String xpathExpression: xpathExpressions) {
                try {
                    WebDriverWait wait = new WebDriverWait(driver, seconds);
                    // 判断元素是否出现
                    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpathExpression)));
                    // 判断是否至少有 1 个元素存在于 dom 树中。举个例子,如果页面上有 n 个元素的 class 都是’column-md-3’,那么只要有 1 个元素存在,这个方法就返回 True。
                    //wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpathExpression)));
                }catch (Exception exception) {
                    return false;
                }
            }
            return true;
        }
    // 调用判断
    if(DriverUtil.isVisibility(driver,3000, "//div[@id='kw']")) {
    	WebElement element = dirver.findElement(By.xpath("//div[@id='kw']"));
    }else {
    	System.out.println("查找不到当前元素!");
    }
    

    四、一些异常处理:
    最近开发遇到这么一段代码执行的时候报错:

    WebElement item = driver.findElement(By.xpath("//div[@id='ctrlselectFundTypeSelectitem0']"));
    item.click();
    

    报错信息:

    element not interactable
      (Session info: headless chrome=87.0.4280.66)
    Build info: version: 'unknown', revision: 'unknown', time: 'unknown'
    System info: host: 'localhost.localdomain', ip: '127.0.0.1', os.name: 'Linux', os.arch: 'amd64', os.version: '3.10.0-1062.el7.x86_64', java.version: '14.0.1'
    Driver info: org.openqa.selenium.chrome.ChromeDriver
    Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 87.0.4280.66, chrome: {chromedriverVersion: 87.0.4280.87 (b7fed45dbe27a..., userDataDir: /tmp/.com.google.Chrome.KKkill}, goog:chromeOptions: {debuggerAddress: localhost:38680}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: eager, platform: LINUX, platformName: LINUX,proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify, webauthn:virtualAuthenticators: true}
    Session ID: 096d1e9b1a7c4d994e193616c19ab35c
    

    这个怎么回事呢,其实就是元素虽然查找到了,但是在页面中的位置非可见的(或者说z-index浮层被别的元素覆盖),这种情况需要检查确定元素是否可见:

    item.isDisplayed();
    
  • 相关阅读:
    配置码云git自动更新的webhook
    PHP如何像javabean一样get+字段名方式取值
    magento信用金额支付插件开发
    JAVASCRIPT localeCompare函数运用
    利用innodb_force_recovery 解决WAMP MySQL服务器无法正常启动的问题
    android回收AnimationDrawable动画的每一帧的图片资源,而释放内存
    MySQL 性能优化 30个数据库设计的最佳实践
    mydumper 快速高效备份mysql,按照表生成备份文件,快速恢复
    MySQL 5.6查询优化器新特性的“BUG” eq_range_index_dive_limit
    Mysql Innodb 引擎优化-内存、日志、IO、其他相关参数
  • 原文地址:https://www.cnblogs.com/chq3272991/p/14474631.html
Copyright © 2011-2022 走看看