通过selenium突破极验验证实现登录

笔者是一名初入Python爬虫的小白,通过书籍(静觅大神出的书籍)的方式学了下突破验证的方式实现模拟登录有此类型的应用的知识。该方法不涉及任何商业关系,如果有违规行为麻烦联系下笔者

实现的步骤分为3步:

  • 1.使应用出现验证的完整图片和带有缺口的图片
  • 2.识别缺口的位置
  • 3.模拟拖动滑块至缺口处,完成验证

引入相关的库

1
2
3
4
5
6
7
8
复制代码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;

我们定义一个类来实现相关的操作并且定义一些配置

1
2
3
4
复制代码EMAIL='xxx'  #账号
PASSWORD='xxx' #密码(只是简单的处理)
BORDER=6; #开始滑动的小块与左边缘的距离
INIT_LEFT=60; #开始从X轴方向即x=60开始检测缺口的位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
复制代码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,安装的具体过程找下搜索引擎问问

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%