使用selenium模擬瀏覽器操作頁面及問題處理(採用Java語言)
有一個需求是:頁面上有一批測試資料要刪除,一共10萬條資料,每頁顯示20條,一共5000頁,手動刪除的操作一般是先點選全選本頁20條,點選"刪除"按鈕,再點選彈出"確認"按鈕完成一次操作。人工點選太費時費力,本來寫了一個js指令碼,每隔10秒定時去操作,把指令碼放在當前頁面的瀏覽器控制檯執行,不一會瀏覽器就卡死了。這時selenium就派上用場了
所需依賴:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId >
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-api</artifactId>
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</ groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-support</artifactId>
<version>2.53.1</version >
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-server</artifactId>
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-remote-driver</artifactId>
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-htmlunit-driver</artifactId>
<version>2.52.0</version>
</dependency>
程式碼實現邏輯:
// 載入驅動 System.setProperty("webdriver.chrome.driver", "D:/chromedriver/chromedriver.exe"); driver = new ChromeDriver(); // 訪問登陸頁面 driver.get("這裡寫登陸頁url"); // 跳轉到原始登入頁 WebElement oldLogBtn=((ChromeDriver) driver).findElementByLinkText("舊版頁面登入"); oldLogBtn.click(); // 使用者名稱 WebElement username=((ChromeDriver) driver).findElementById("username"); username.sendKeys("這裡寫使用者名稱"); // 密碼 WebElement password=((ChromeDriver) driver).findElementById("password"); password.sendKeys("這裡寫密碼"); // 記住登入狀態 WebElement remember=((ChromeDriver) driver).findElementById("rememberMe"); remember.click(); // 提交登陸 WebElement submit =((ChromeDriver) driver).findElementById("login"); submit.click(); driver.get("這裡寫抓取頁url"); // 當前頁面全選框 WebElement checkbox = ((ChromeDriver) driver).findElementById("checkbox"); // 通訊錄刪除按鈕 WebElement delBtn = ((ChromeDriver) driver).findElement(By.xpath("//*[@id=\"content-header\"]/div/button[2]")); // 刪除確認按鈕 // WebElement confirmBtn = ((ChromeDriver) driver).findElement(By.cssSelector(".btn.btn-primary.submit ")); WebElement confirmBtn = ((ChromeDriver) driver).findElement(By.xpath("//*[@id=\"del-contacts\"]/div/div[3]/div[1]/button[1]")); System.out.println("confirmBtn=" + confirmBtn); Timer timer = new Timer(); timer.schedule(new TimerTask() { public void run() { // 全選 checkbox.click(); try { // 刪除 delBtn.click(); Thread.sleep(1000); // 確認 confirmBtn.click(); } catch (InterruptedException e) { e.printStackTrace(); } } }, 2000, 5000);
注意要點:
第一:根據你所使用的瀏覽器,我這裡使用的chrome驅動,當然你也可以使用Firefox或者ie等等驅動,下載地址為chromedriver.exe驅動下載,注意驅動版本與電腦上瀏覽器的版本相容關係
第二:在找元素的時候,有的時候元素只有一個class屬性,而且是多個值,中間還有空格,一般我們在javascript中,通過jQuery這麼選取:$(".btn.btn-light"),但是如果在selenium中你通過下面這種方式獲取就會報錯
(1)org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"class name","selector":".btn.btn-light"}:
WebElement button = ((ChromeDriver) driver).findElementByClassName(".btn.btn-light");
(2)接下來我把class屬性值中的“.”去掉,改用空格替代,保持頁面上class屬性值的原樣,又報新錯誤
了org.openqa.selenium.InvalidSelectorException: invalid selector: Compound class names not permitted:
WebElement delBtn1 = ((ChromeDriver) driver).findElementByClassName("btn btn-light");
這是因為selenium的這個api不支援複合屬性
(3)幸好selenium支援css選擇器,然後我改成下面的
WebElement confirmBtn2 = ((ChromeDriver) driver).findElement(By.cssSelector(".btn.btn-light"));
這次獲取button元素沒有出錯,但是在呼叫這個元素的click方法時
報錯org.openqa.selenium.ElementNotVisibleException: element not visible :
網上說這個錯誤可能是因為元素選錯了,也有可能是這個class屬性很多元素都有,所以不唯一;也有可能是頁面還沒渲染出來,要等待一會;還有可能是這是隱藏元素或遮罩層的元素,反正那個部落格分析的挺詳細的,你可以慢慢排查,我會在文章下面的參考地址貼出那篇部落格;文章建議優先根據元素id來獲取元素,沒有id就使用xpath路徑;儘量不要使用class來獲取;
第三:有的人可能不會xpath語法,沒關係,開啟瀏覽器控制檯,在element標籤下,選中你要的元素,滑鼠右鍵,在彈出的選單中選擇“copy”---》“copy xpath”,貼上到程式中完事,如下圖:
第四:selenium再智慧,也要通過瀏覽器操作,之所以要下載chromedriver.exe,執行程式時會彈出chrome瀏覽器,一切就緒後,千萬不要用滑鼠去操作頁面,一旦動了頁面,程式功能就失效了
第五:遇到渲染慢的頁面,sleep一下
後來發現採用httpclient模擬瀏覽器處理比上面好用;在你不知道按鈕傳送的請求連線情況下用上面selenium,知道的話還是httpclient效率高一些
參考地址:https://blog.csdn.net/BerlinLove/article/details/70053808
https://blog.csdn.net/duzilonglove/article/details/78603956