Java + Selenium 完成簡單滑塊驗證學習之路(破解無缺口滑塊驗證碼)(三)

                                              破解無缺口滑塊驗證碼

在學習完selenium 簡單操作之後,繼續我的破解之路。先看一下原網頁頁面。(靈魂打碼重點看滑塊)

破解這種無缺口滑塊首先要找到滑塊位置,根據selenium選擇器去選擇要拖動的Slider,選中之後查看要拖動的px,執行

dragAndDropBy方法即可。

(1)F12 查看滑塊的位置,使用selenium選擇器選擇滑塊

(2)查看要拖動的距離以及滑塊的大小

  

注意要拖動的距離則爲 (305-40)px

下面附上第一版代碼:

package com.example.blacklist.selenium;



import javafx.scene.control.Slider;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @author www
 */
public class SeleniumTest {
    public static void main(String[] args) throws Exception {
       
        System.setProperty("webdriver.chrome.driver","D:\\driver\\chrome\\chromedriver.exe");
        WebDriver driver = new ChromeDriver();
        //PhantomJs
        //WebDriver driver = PhantomJsUtil.getPhantomJs();
        //fire
        //System.setProperty("webdriver.firefox.marionette","D:\\driver\\fire\\geckodriver.exe");
        //WebDriver driver = new FirefoxDriver();
        try {
            driver.get("xxxxxxURL");
            List<WebElement> elements = driver.findElements(By.xpath("//input[@data-meta=\"Field\"]"));
            Thread.sleep(2000L);
            elements.get(0).sendKeys("username");
            Thread.sleep(2000L);
            elements.get(1).sendKeys("password");
            Thread.sleep(5000L);
            String pageSource1= driver.getPageSource();
            if(pageSource1.contains("next-btn next-btn-primary next-btn-large")){
                WebElement element = driver.findElement(By.cssSelector(".next-btn.next-btn-primary.next-btn-large"));
                System.out.println("LOGIN----------"+element.getText()+"-----------------LOGIN");
                element.click();
                Thread.sleep(5000L);
            }

            //存到本地
            File file = new File("C:\\Users\\www\\Desktop\\files\\pageSource1.txt");
            PrintStream ps = new PrintStream(new FileOutputStream(file));
            ps.print(pageSource1);
            WebElement Slider = driver.findElement(By.cssSelector(".nc_iconfont.btn_slide"));
            Thread.sleep(2000L);
            //WebElement Slider = driver.findElement(By.id("nc_2_n1z"));
            System.out.println("Slider=========="+ Slider.getTagName()+"==============Slider");
            Actions action = new Actions(driver);
            Thread.sleep(5000L);
            action.dragAndDropBy(Slider,265,0).perform();
            Thread.sleep(5000L);
            String pageSource = driver.getPageSource();
            File file2 = new File("C:\\Users\\www\\Desktop\\files\\pageSource2.txt");
            PrintStream ps2 = new PrintStream(new FileOutputStream(file2));
            ps2.print(pageSource);
            ps.close();
            ps2.close();
            Thread.sleep(60000L);
            driver.close();
            driver.quit();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            driver.close();
            driver.quit();
        }

    }

    @Test
    public void get(){
        for (int j = 1; j <= 2; j++) {
            System.out.println(j);
        }
    }
}

執行後可以發現被檢測到受自動軟件的控制此時需要我們關閉,代碼如下

 //chrom
        ChromeOptions option = new ChromeOptions();
        //關閉受自動軟件的控制
        option.addArguments("disable-infobars");
        List<Object> list=new ArrayList<>();

再次執行會發現受自動軟件的控制已經被關閉。

下面就是重點了,在做完這些操作之後,鼠標可以成功拖動滑塊,但卻無法驗證通過。查閱了很多資料發現有些網站會有發爬蟲機制,能夠根據selenium 的一些標識。這是就需要進一步改寫selenium的標識從而突破網站的攔截。

我們來看一個例子。

執行下面這一段代碼啓動Chrome窗口:

  @Test
    public void get(){
        System.setProperty("webdriver.chrome.driver","D:\\driver\\chrome\\chromedriver.exe");
        WebDriver driver = new ChromeDriver();

    }

現在,在這個窗口中打開開發者工具,並定位到Console選項卡,如下圖所示。

執行

window.navigator.webdriver

可以看到這個值爲true,而我們直接在瀏覽器中打開,執行相同的命令,可以發現這行代碼的返回值爲undefined,如下圖所示。

所以,如果網站通過js代碼獲取這個參數,返回值爲undefined說明是正常的瀏覽器,返回true說明用的是Selenium模擬瀏覽器。一抓一個準。這裏給出一個檢測Selenium的js代碼例子:

 String js1="Object.defineProperties(navigator, {webdriver:{get:()=>undefined}});";
((ChromeDriver) driver).executeScript(js1);

網站只要在頁面加載的時候運行這個js代碼,就可以識別訪問者是不是用的Selenium模擬瀏覽器。如果是,就禁止訪問或者觸發其他反爬蟲的機制。

 

確實修改成功了。這種寫法就萬無一失了嗎?並不是這樣的,如果此時你在模擬瀏覽器中通過點擊鏈接、輸入網址進入另一個頁面,或者開啓新的窗口,你會發現,window.navigator.webdriver又變成了true

接下來,又有朋友提出,可以通過編寫Chrome插件來解決這個問題,讓插件裏面的js代碼在網站自帶的所有js代碼之前執行。

這樣做當然可以,不過有更簡單的辦法,只需要設置Chromedriver的啓動參數即可解決問題。

在啓動Chromedriver之前,爲Chrome開啓實驗性功能參數excludeSwitches,它的值爲['enable-automation'],

List<Object> list=new ArrayList<>();
 list.add("enable-automation");
 option.setExperimentalOption("excludeSwitches",list);

下面附上完整代碼:

package com.example.blacklist.selenium;



import javafx.scene.control.Slider;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @author www
 */
public class SeleniumTest {
    public static void main(String[] args) throws Exception {
       //chrom
        ChromeOptions option = new ChromeOptions();
        //關閉受自動軟件的控制
        option.addArguments("disable-infobars");
        List<Object> list=new ArrayList<>();
        list.add("enable-automation");
        option.setExperimentalOption("excludeSwitches",list);
        //後臺運行
        //option.addArguments("headless");

        System.setProperty("webdriver.chrome.driver","D:\\driver\\chrome\\chromedriver.exe");
        WebDriver driver = new ChromeDriver(option);

        //PhantomJs
        //WebDriver driver = PhantomJsUtil.getPhantomJs();
        //fire
        //System.setProperty("webdriver.firefox.marionette","D:\\driver\\fire\\geckodriver.exe");
        //WebDriver driver = new FirefoxDriver();
        try {
            //改寫 wedriver
            String js1="Object.defineProperties(navigator, {webdriver:{get:()=>undefined}});";
            ((ChromeDriver) driver).executeScript(js1);
            driver.get("xxxxxxxxxURL");
            List<WebElement> elements = driver.findElements(By.xpath("//input[@data-meta=\"Field\"]"));
            Thread.sleep(2000L);
            elements.get(0).sendKeys("userName");
            Thread.sleep(2000L);
            elements.get(1).sendKeys("password");
            Thread.sleep(5000L);
            String pageSource1= driver.getPageSource();
            if(pageSource1.contains("next-btn next-btn-primary next-btn-large")){
                WebElement element = driver.findElement(By.cssSelector(".next-btn.next-btn-primary.next-btn-large"));
                System.out.println("LOGIN----------"+element.getText()+"-----------------LOGIN");
                element.click();
                Thread.sleep(5000L);
            }

            //存到本地
            File file = new File("C:\\Users\\www\\Desktop\\files\\pageSource1.txt");
            PrintStream ps = new PrintStream(new FileOutputStream(file));
            ps.print(pageSource1);
            WebElement Slider = driver.findElement(By.cssSelector(".nc_iconfont.btn_slide"));
            Thread.sleep(2000L);
            //WebElement Slider = driver.findElement(By.id("nc_2_n1z"));
            System.out.println("Slider=========="+ Slider.getTagName()+"==============Slider");
            Actions action = new Actions(driver);
            Thread.sleep(5000L);
            action.dragAndDropBy(Slider,265,0).perform();
            Thread.sleep(5000L);
            String pageSource = driver.getPageSource();
            File file2 = new File("C:\\Users\\www\\Desktop\\files\\pageSource2.txt");
            PrintStream ps2 = new PrintStream(new FileOutputStream(file2));
            ps2.print(pageSource);
            ps.close();
            ps2.close();
            Thread.sleep(60000L);
            driver.close();
            driver.quit();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            driver.close();
            driver.quit();
        }

    }

 
}

到這裏selenium就可以拖動滑塊成功驗證了,希望會對你有所幫助

發佈了15 篇原創文章 · 獲贊 8 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章