筆者是一名初入Python爬蟲的小白,經過書籍(靜覓大神出的書籍)的方式學了下突破驗證的方式實現模擬登陸有此類型的應用的知識。該方法不涉及任何商業關係,若是有違規行爲麻煩聯繫下筆者web
實現的步驟分爲3步:算法
引入相關的庫canvas
from selenium import webdriver;
from selenium.webdriver.support.wait import WebDriverWait;
from selenium.webdriver.support import expected_conditions as EC;
from selenium.webdriver.common.by import By;
from selenium.webdriver import ActionChains;
import time;
from PIL import Image;
from io import BytesIO;
複製代碼
咱們定義一個類來實現相關的操做而且定義一些配置瀏覽器
EMAIL='xxx' #帳號
PASSWORD='xxx' #密碼(只是簡單的處理)
BORDER=6; #開始滑動的小塊與左邊緣的距離
INIT_LEFT=60; #開始從X軸方向即x=60開始檢測缺口的位置
複製代碼
class GrackGeetest(object):
def __init__(self):
#這邊咱們開始定義一些相關的參數信息(咱們用登陸極驗官網來作例子,其它的方式相似)
self.url='https://auth.geetest.com/login/';
self.browser=webdriver.Chrome();
self.wait=WebDriverWait(self.browser,20);
self.email=EMAIL;
self.password=PASSWORD;
#實現步驟1相關方法:
def getGeetestButton(self):
#獲取點擊可使現驗證圖出現的按鈕節點元素並返回
button=self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'geetest_radar_tip')));
return button;
#獲取驗證圖在網頁中的位置並以元組的方式返回
def getImagePosition(self):
geetestImage=self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'geetest_canvas_img')));
time.sleep(2);
location=geetestImage.location;
size=geetestImage.size;
top,bottom,left,right=location['y'],location['y']+size['height'],location['x'],location['x']+size['width'];
return (top,bottom,left,right);
#截取當前頁面
def getChromePage(self):
pageShot=self.browser.get_screenshot_as_png();
pageShot=Image.open(BytesIO(pageShot));
return pageShot;
#從網頁中截取該驗證圖片並返回
def getGeetestImage(self,name='geetest.png'):
top,bottom,left,right=self.getImagePosition();
#截取當前頁面的圖片
pageShot=self.getChromePage();
#截取其中出現的驗證圖的位置
captchaImage=pageShot.crop((left,top,right,bottom));
captchaImage.save(name);#保存到當前的文件夾中
return captchaImage;
#實現步驟2相關方法:識別缺口位置
def getSlider(self):
#獲取可拖動的滑塊對象
slider=self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'geetest_slider_button')));
return slider;
#經過對比2張圖的像素點的差距得出缺口位置
def getGap(self,image1,image2):
left=60;
#size[0]->width,size[1]->height
for i in range(left,image1.size[0]):
for j in range(image1.size[1]):
if not self.isPixelEqual(image1,image2,i,j):
#由於小滑塊和缺口是同一條水平線上的因此就只取x軸方向上的值
left=i;
return left;
return left;
def isPixelEqual(self,image1,image2,x,y):
#判斷2個像素是否相同
pixel1=image1.load()[x,y]; #pixel1,pixel2爲rgb值,是一個元組
pixel2=image2.load()[x,y];
#閥值當超出這個閥值的時候則證實這2個像素點不匹配,爲缺口的左上角的像素點
threshold=60;
if abs(pixel1[0]-pixel2[0])<threshold and abs(pixel1[1]-pixel2[1])<threshold and abs(pixel1[2]-pixel2[2])<threshold :
return True;
else:
return False;
#步驟三相關方法:最關鍵的一步也是突破極驗驗證機器學習算法的一步
#採用物理中物體的分階段改變加速度的方式,這裏採用先加速後減速的方式
#公式 x=v0*t+1/2*a*t*t v=v0+a*t
def getTrack(self,distance):
#distance偏移量
#移動軌跡
tranck=[];
#當前位移
current=0;
#開始減速的閥值
mid=distance*4/5;
#計算間隔
t=0.2;
#初速度
v=0;
while current<distance:
if current<mid:
a=2;
else:
#開始減速
a=-3;
#初速度
v0=v;
#當前速度
v=v0+a*t;
#位移
move=v0*t+1/2*a*t*t;
#當前位移
current+=move;
#加入軌跡
track.append(round(move));
return track;
#按照運動軌跡移動滑塊
def moveToGap(self,slider,tracks):
#拖動滑塊到缺口處
ActionChains(self.browser).click_and_hold(slider).perform();
for x in tracks:
ActionChains(self.browser).move_by_offset(xoffset=x,yoffset=0).perform();
time.sleep(0.5);
ActionChains(self.browser).release().perform();
#最後模擬點擊登陸應用就好了
def login(self):
button=self.wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#base > div.content-outter > div > div > div:nth-child(3) > div > form > div:nth-child(5) > div > button')));
button.click();
time.sleep(10);
#接下來直接實現經過一個方法將這整個過程鏈接起來
def sendUserAndPassword(self):
self.browser.get(self.url);
#經過類選擇器,我是直接在瀏覽器那邊複製過來的,因此比較長,能夠經過其它方式獲得該元素(右鍵那個網頁元素就有一些選擇能夠看看哈)
email=self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#base > div.content-outter > div > div > div:nth-child(3) > div > form > div:nth-child(1) > div > div.ivu-input-wrapper.ivu-input-type.ivu-input-group.ivu-input-group-with-prepend > input')));
password=self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#base > div.content-outter > div > div > div:nth-child(3) > div > form > div:nth-child(2) > div > div.ivu-input-wrapper.ivu-input-type.ivu-input-group.ivu-input-group-with-prepend > input')));
email.send_keys(self.email);
password.send_keys(self.password);
def doVerifyLogin(self):
#步驟1:
#輸入帳號密碼
self.sendUserAndPassword();
#點擊驗證按鈕
verifyButton=self.getGeetestButton();
verifyButton.click();
#開始獲取2張驗證圖
image1=self.getGeetestImage('geetest1.png');
#點擊小滑塊獲得有缺口的驗證圖
slider=self.getSlider();
slider.click();
#獲取帶缺口的驗證圖
image2=self.getGeetestImage('geetest2.png');
#步驟2:
#獲取缺口位置
gap=self.getGap(image1,image2);
#缺口的位置須要減去那個小滑塊與左邊那一小段距離
gap-=BORDER;
#步驟3:
#移動軌跡
track=self.getTrack();
#拖動滑塊
self.moveToGap(slider,track);
#最後判斷是否成功了,不成功就從新操做這一過程
try:
success = self.wait.until(
EC.text_to_be_present_in_element((By.CLASS_NAME, 'geetest_success_radar_tip_content'), '驗證成功'))
print(success)
# 失敗後重試
if not success:
self.doVerifyLogin()
else:
self.login()
except:
self.doVerifyLogin();
if __name__ == '__main__':
crack = GrackGeetest();
crack.doVerifyLogin();
複製代碼
以上就是完整的代碼了,同時須要安裝ChromeDriver,安裝的具體過程找下搜索引擎問問bash