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就可以拖动滑块成功验证了,希望会对你有所帮助

猜你喜欢

转载自blog.csdn.net/weixin_39041673/article/details/103472391
今日推荐