Java+Selenium--頁面反爬蟲機制,安全滑塊踩過的坑


最近工作中,要在淘寶四級頁下訂單並支付。淘寶的頁面對自動化腳本識別控制還是挺多,短時間重復登錄、下單並支付操作,會被后台檢測,會在登錄,四級頁,訂單提交頁面出現安全滑塊攔截。以下為最近遇到的問題踩到的坑和解決辦法。

1.關於頁面識別window.navigator.webdirver屬性值的問題

當我們沒有使用自動化腳本時,本地打開谷歌瀏覽器,在控制台輸入window.navigator.webdirver時,返回的是undefined。

 

 

 

當我們使用webDriver調用本地瀏覽器時,在控制台輸入window.navigator.webdirver時,可能返回True被服務端判定為爬蟲,會登錄產生滑塊或者登錄失敗。

此時需要在代碼中加入CdpCommand,同時還有ChromeOptions操作,代碼一並附上

public RemoteWebDriver init() {
        //設置property
//driverpath為本地的chromedriver.exe的路徑
System.setProperty("webdriver.chrome.driver", driverpath); System.out.println("准備實例化ChromeOpen類"); //設置瀏覽器options ChromeOptions options = new ChromeOptions(); // 關閉界面上的---Chrome正在受到自動軟件的控制 options.addArguments("disable-infobars"); // 允許重定向 //options.addArguments("--disable-web-security"); // 最大化 //options.addArguments("--start-maximized"); //options.addArguments("--no-sandbox"); //設置ExperimentalOption List<String> excludeSwitches = Lists.newArrayList("enable-automation"); options.setExperimentalOption("excludeSwitches", excludeSwitches); options.setExperimentalOption("useAutomationExtension", false); ChromeDriver driver = new ChromeDriver(options); //修改window.navigator.webdirver=undefined,防機器人識別機制 Map<String, Object> command = new HashMap<>(); command.put("source", "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"); driver.executeCdpCommand("Page.addScriptToEvaluateOnNewDocument", command); return driver; }

 

2.判斷頁面元素是否存在,主要用於檢測是不是有安全滑塊(這個是真的煩,狗頭ORZ)

    //判斷是否存在某元素
    public boolean isJudgingElement(RemoteWebDriver remoteWebDriver, By by) {
        try {
            remoteWebDriver.findElement(by);
            return true;
        } catch (Exception e) {
            System.out.println("不存在此元素");
            return false;
        }
    }

 

3.淘寶登錄滑塊,此處需要使用action操作,且 action.dragAndDropBy(moveButton, 258, 0).perform()為重點操作。

 

 

 

            //點擊登錄按鈕
            Thread.sleep(2000);
            WebElement login = remoteWebDriver.findElement(By.xpath("//form[@id=\"login-form\"]//div[@class=\"fm-btn\"]/button"));
            login.click();

            //判斷是否有滑塊
            Thread.sleep(2000);
            if (isJudgingElement(remoteWebDriver, By.id("baxia-dialog-content"))) {
                remoteWebDriver.switchTo().frame("baxia-dialog-content");
                if (isJudgingElement(remoteWebDriver, By.id("nc_2_n1z"))) {
                    Actions action = new Actions(remoteWebDriver);
                    WebElement moveButton = remoteWebDriver.findElement(By.id("nc_2_n1z"));
                    // 移到滑塊元素並懸停,不能超出框的長度,否則異常
                    action.clickAndHold(moveButton);
                    action.dragAndDropBy(moveButton, 258, 0).perform();
                    action.release();
                }
                remoteWebDriver.switchTo().defaultContent();
                login.click();
            }

            //校驗登錄成功
            Thread.sleep(2000);
            WebElement userid = remoteWebDriver.findElement(By.xpath("//div[@class=\"site-nav-user\"]/a"));
            System.out.println(userid.getText());
            if (userid.getText().equals(username)) {
                System.out.println("淘寶網登錄成功");
            }

 

4.代碼執行失敗截圖瀏覽器,並打印日志,退出瀏覽器,防止瀏覽器進程過多未關閉

 

catch (Exception e) {
            e.printStackTrace();
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//設置日期格式
            String currentTime = df.format(new Date());
            System.out.println(currentTime);// new Date()為獲取當前系統時間
            String path = "C:\\Users\\Desktop\\pic\\Exception_" + currentTime + ".png";
            File src = ((TakesScreenshot) remoteWebDriver).getScreenshotAs(OutputType.FILE);  // 調用截圖方法
            FileUtils.copyFile(src, new File(path));
            System.out.println("登錄失敗!");
            Thread.sleep(2000);
            remoteWebDriver.quit();
        }

//瀏覽器退出
    public void webDriverQuit(RemoteWebDriver remoteWebDriver) {
        remoteWebDriver.quit();
        System.out.println("瀏覽器退出成功");
    }

 

 

 

5.四級頁安全滑塊問題,目前四級頁的安全滑塊和確認訂單頁的安全滑塊,沒有比較好的方法,使用了登錄的滑塊方法,但是並沒有效果。不過好在四級頁還可以通過關閉滑塊彈框,等待頁面加載控件,點擊立即購買,到確認訂單頁面。

 

 

            //打開四級頁
            remoteWebDriver.get(Level4PageUrl);
            Thread.sleep(2000);
            //判斷是否有安全滑塊,點擊關閉
            if (tblogin.isJudgingElement(remoteWebDriver, By.id("sufei-dialog-content"))) {
                /*remoteWebDriver.switchTo().frame("sufei-dialog-content");*/
                remoteWebDriver.findElement(By.id("sufei-dialog-close")).click();
                /*remoteWebDriver.switchTo().defaultContent();*/
                //頁面緩存
                Thread.sleep(10000);
            }

            //點擊立即購買按鈕
            remoteWebDriver.findElement(By.id("J_LinkBuy")).click();
            Thread.sleep(2000);

 

6.確認訂單頁面的安全滑塊(參照賬號登錄方法,不過滑塊驗證失敗,待解決,有解決方案的大佬多多指教,感謝)

            //訂單頁面滑塊判斷
            if (tblogin.isJudgingElement(remoteWebDriver, By.id("nc_1_n1z"))) {
                Actions action = new Actions(remoteWebDriver);
                WebElement moveButton = remoteWebDriver.findElement(By.id("nc_1_n1z"));
                // 移到滑塊元素並懸停,不能超出框的長度,否則異常
                action.clickAndHold(moveButton);
                action.dragAndDropBy(moveButton, 258, 0).perform();
                action.release();
                Thread.sleep(2000);
                if(!tblogin.isJudgingElement(remoteWebDriver, By.linkText("提交訂單"))){
                    //試圖二次刷新頁面,操作安全滑塊
                    String currentUrl = remoteWebDriver.getCurrentUrl();
                    remoteWebDriver.get(currentUrl);
                    Thread.sleep(2000);
                    action = new Actions(remoteWebDriver);
                    moveButton = remoteWebDriver.findElement(By.id("nc_1_n1z"));
                    // 移到滑塊元素並懸停,不能超出框的長度,否則異常
                    action.clickAndHold(moveButton);
                    action.dragAndDropBy(moveButton, 258, 0).perform();
                    action.release();
                    Thread.sleep(2000);
                }
            }

 

7.重頭戲!好家伙,這玩意卡了我兩天,支付頁面,輸入密碼提交支付。開始的思路,頁面的密碼輸入框不可點擊,想通過js語句去修改html的css屬性,達到元素可以定位的效果。無奈,不論怎么修改,都無法在頁面生效,這里不得不給支付寶的開發大大點贊。

 

 

 

 

 

這個思路不行,就想別的解決方案。發現從訂單提交頁面提交成功后,跳轉到支付頁面,光標是自動定位到密碼的第一個輸入框的,而且元素的屬性是visibility: visible,並且輸入第一個數字后,光標自動移到第二個輸入框。然后就想,是不是有方法能夠獲取當前光標,直

接去模擬鍵盤操作。在網上找了很多帖子,奈何基本都是python的帖子,用的是keyboard類的方法。就在絕望准備推倒java,拿起python工具之前,google了一下,發現可以使用action的思路。

            //輸入支付密碼
            for (int i = 0; i < payPassword.length(); i++) {
                char c = payPassword.charAt(i);
                String password = String.valueOf(c);
                Actions action = new Actions(remoteWebDriver);
                action.sendKeys(password).build().perform();
                action.clickAndHold();
                action.release();
                /*String path = picpath + i + ".png";
                File src = ((TakesScreenshot) remoteWebDriver).getScreenshotAs(OutputType.FILE);  // 調用截圖方法
                FileUtils.copyFile(src, new File(path));*/
            }
            Thread.sleep(1000);
            remoteWebDriver.findElement(By.id("J_authSubmit")).click();
            Thread.sleep(5000);

            //付款成功校驗
            String resp = remoteWebDriver.findElement(By.xpath("//div[@id=\"J_AmountList\"]/h2")).getText();

            if ("您已成功付款".equals(resp)) {
                System.out.println("訂單支付成功");
                String currentUrl = remoteWebDriver.getCurrentUrl();
                System.out.println(currentUrl);
                String[] orderIdArray1 = currentUrl.split("bizOrderId=");
                String orderIdString = orderIdArray1[1];
                String[] orderIdArray2 = orderIdString.split("&");
                orderId = orderIdArray2[0];
                System.out.println("訂單編號orderId:" + orderId);
                SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//設置日期格式
                currentTime = df.format(new Date());
                String path = picpath + currentTime + "_orderCreate_" + orderId + ".png";
                File src = ((TakesScreenshot) remoteWebDriver).getScreenshotAs(OutputType.FILE);  // 調用截圖方法
                FileUtils.copyFile(src, new File(path));
                tblogin.webDriverQuit(remoteWebDriver);
            }

 

8.將訂單號,下單時間等信息保存到excel中

public static void createExcelxlsx(String path) throws Exception {
        //創建excel對象
        XSSFWorkbook wb = new XSSFWorkbook();
        //用文件對象創建sheet對象
        XSSFSheet sheet = wb.createSheet("sheet1");
        //創建單元格樣式
        CellStyle cellStyle = wb.createCellStyle();
        //設置表頭
        XSSFRow rowInit = sheet.createRow(0);
        Cell cell1 = rowInit.createCell(0);
        Cell cell2 = rowInit.createCell(1);
        Cell cell3 = rowInit.createCell(2);
        cell1.setCellValue("行號");
        cell2.setCellValue("訂單編號");
        cell3.setCellValue("創建時間");
        FileOutputStream outputInit = new FileOutputStream(path);
        wb.write(outputInit);
        outputInit.flush();
        outputInit.close();
    }

    public static void saveExcelxlsx(String path, int i, String value, String time) throws Exception {
        XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream(path));
        XSSFSheet sheet = wb.getSheet("sheet1");
        //寫訂單數據
        //用sheet對象創建行對象
        XSSFRow row = sheet.createRow(i + 1);
        //構造數據
        List<Object> list = new ArrayList<>();
        list.add(i + 1);
        list.add(value);
        list.add(time);
        int length = list.size();

        for (int n = 0; n < length; n++) {
            FileOutputStream output = new FileOutputStream(path);
            //用行對象創建單元格對象Cell
            Cell cell = row.createCell(n);
            //用cell對象讀寫。設置excel工作表值
            cell.setCellValue(list.get(n).toString());
            wb.write(output);
            output.flush();
            output.close();
        }
    }

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 10; i++) {
            HashMap<String, String> hashMap = tbOrderCreate();
            Iterator it = hashMap.keySet().iterator();
            String v = "";
            String t = "";
            while (it.hasNext()) {
                v = it.next().toString();
                t = hashMap.get(v);
            }
            if (!("".equals(v))) {
                File file = new File(excelpath);
                if (!file.exists()) {
                    createExcelxlsx(excelpath);
                    saveExcelxlsx(excelpath, i, v, t);
                } else {
                    saveExcelxlsx(excelpath, i, v, t);
                }
            }
        }
    }

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM