Web自動化三種等待方式,一篇文章教會你

發表於2024-02-19

image.png

三種等待方式

簡介

在實際工作中等待機制可以保證程式碼的穩定性,保證程式碼不會受網速、電腦效能等條件的約束。

等待就是當執行程式碼時,如果頁面的渲染速度跟不上程式碼的執行速度,就需要人為的去限制程式碼執行的速度。

在做 Web 自動化時,一般要等待頁面元素載入完成後,才能執行操作,否則會報找不到元素等各種錯誤,這樣就要求在有些場景下加上等待。

最常見的有三種等待方式:隱式等待、顯式等待、強制等待,下面介紹以下這三種等待方式。

隱式等待

隱式等待的機制是:設定一個等待時間,輪詢查詢(預設 0.5 秒)元素是否出現,如果沒出現就丟擲異常。這也是最常見的等待方法。

隱式等待的作用是全域性的,是作用於整個 session 的生命週期,也就是說只要設定一次隱式等待,後面就不需要設定。如果再次設定隱式等待,那麼後一次的會覆蓋前一次的效果。

當在 DOM 結構中查詢元素,且元素處於不能立即互動的狀態時,將會觸發隱式等待。

Python 實現

self.driver.implicitly_wait(30)

Java 實現

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

顯式等待

顯示等待的機制是:顯式等待是在程式碼中定義等待條件,觸發該條件後再執行後續程式碼,就能夠根據判斷條件進行等待。程式每隔一段時間進行條件判斷,如果條件成立,則執行下一步,否則繼續等待,直到超過設定的最長時間。示例程式碼如下:

Python 實現

匯入顯式等待

from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions
...


# 設定10秒的最大等待時間,等待 (By.TAG_NAME, "title") 這個元素點選
WebDriverWait(driver, 10).until(
    expected_conditions.element_to_be_clickable((By.TAG_NAME, "title"))
)
...

Java 實現

importorg.openqa.selenium.*;
importorg.openqa.selenium.chrome.ChromeDriver;
importorg.openqa.selenium.support.ui.ExpectedConditions;
importorg.openqa.selenium.support.ui.WebDriverWait;
importjava.time.Duration;
publicclass demo3{

publicstaticvoidmain(String[]args){

WebDriverdriver=newChromeDriver();

driver.get("https://ceshiren.com");
//顯示等待,直到元素(id為kw)出現,才停止等待
WebElementelement=(newWebDriverWait(driver,Duration.ofSeconds(5)))
.until(ExpectedConditions.presenceOfElementLocated(By.id("kw")));


driver.close();
//關閉瀏覽器程式
driver.quit();
}
}

這裡透過匯入 expected_conditions 這個庫來滿足顯式等待所需的使用場景,但是 expected_conditions 庫並不能滿足所有場景,這個時候就需要定製化開發來滿足特定場景。

實戰演示
假設:要判斷某個元素超過指定的個數,就可以執行下面的操作。

Python 實現

def ceshiren():
    # 定義一個方法
    def wait_ele_for(driver):
        # 將找到的元素個數賦值給 eles
        eles = driver.find_elements(By.XPATH, '//*[@id="site-logo"]')
        # 放回結果
        return len(eles) > 0
    driver = webdriver.Chrome()
    driver.get('https://ceshiren.com')
    # 顯式等待10秒,直到 wait_ele_for 返回 true
    WebDriverWait(driver, 10).until(wait_ele_for)

Java 實現

importorg.openqa.selenium.By;
importorg.openqa.selenium.WebDriver;
importorg.openqa.selenium.WebElement;
importorg.openqa.selenium.chrome.ChromeDriver;
importorg.openqa.selenium.support.ui.ExpectedConditions;
importorg.openqa.selenium.support.ui.WebDriverWait;

importjava.time.Duration;
importjava.util.List;

publicclass demo4{
publicstaticvoidmain(String[]args){

WebDriverdriver=newChromeDriver();
driver.get("https://ceshiren.com");

// 顯式等待,等待元素出現超過指定個數
WebDriverWaitwait=newWebDriverWait(driver,Duration.ofSeconds(10));
List<WebElement>elements=wait.until(ExpectedConditions.visibilityOfAllElementsLocated(By.xpath("//*[@id=\"site-logo\"]")));
intcount=elements.size();

if(count>0){
// 執行操作
System.out.println("元素超過指定個數");
}else{
System.out.println("元素未超過指定個數");
}

driver.quit();
}
}

強制等待

強制等待是使執行緒休眠一定時間。強制等待一般在隱式等待和顯式等待都不起作用時使用。示例程式碼如下:

Python 實現

# 等待十秒
time.sleep(10)

Java 實現

//等待1s
Thread.sleep(1000)

實戰演示

訪問測試人社群(https://ceshiren.com),點選分類,然後點選開源專案:

在這裡插入圖片描述

當點選分類時,元素還未載入完成,這裡就需要隱式等待。在點選開源專案時,元素已載入完成,但是還處在不可點選的狀態,這時要用到顯式等待。

Python 實現

#匯入依賴
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait

class TestHogwarts():
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.get('https://ceshiren.com/')
        # 加入隱式等待
        self.driver.implicitly_wait(5)

    def teardown(self):
        # 強制等待
        time.sleep(10)
        self.driver.quit()

    def test_hogwarts(self):
        # 點選類別
        self.driver.find_element(By.CSS_SELECTOR, '[title="按類別分組的所有話題"]').click()
        # 元素定位,這裡的category_name是一個元組。
        category_name = (By.XPATH, "//*[@class='category-text-title']//*[text()='開源專案']")
        # 加入顯式等待
        WebDriverWait(self.driver, 10).until(
            expected_conditions.element_to_be_clickable(category_name))
        # 點選開源專案
        self.driver.find_element(*category_name).click()

Java 實現

importorg.openqa.selenium.*;
importorg.openqa.selenium.chrome.ChromeDriver;
importjava.util.logging.Logger;

publicclass demo{
privatestaticfinalLoggerlogger=Logger.getLogger(demo.class.getName());
publicstaticvoidmain(String[]args)throwsInterruptedException{

WebDriverdriver=newChromeDriver();

driver.get("https://ceshiren.com");

Thread.sleep(2000);
driver.manage().window().setSize(newDimension(1936,1056));
driver.findElement(By.cssSelector("#ember18-header .name")).click();
driver.findElement(By.id("ember77")).click();

driver.close();
//關閉瀏覽器程式
driver.quit();
}
}

相關文章