破解無缺口滑塊驗證碼
在學習完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就可以拖動滑塊成功驗證了,希望會對你有所幫助