python爬⾍滑动验证码_爬⾍:滑动验证解决⽅法及python实
现
爬⾍时遇到滑动验证,基本思路是通过lenium操作浏览器,将滑动验证的原始图⽚和缺⼝图⽚进⾏对⽐,找出缺⼝位置,然后在利⽤lenium模拟拖动滑块,达到验证的⽬的。下⾯就以猪⼋戒⽹为例,进⾏操作。
⼀、分析
登陆页⾯主要为上图。
点击按钮(div标签,类名为 geetest_radar_tip)后,出现滑动验证码:
这个滑动验证图⽚并没有原始图⽚,直接出现的就是缺⼝图⽚。⽽我们要找的就是深⾊缺⼝的位置。
观察图⽚标签,找到 这个标签,如果把该标签设置的display属性设置为none,则验证图则会变为下图:
拼接的⼩⽅块隐藏掉了,这张图⽚更容易让我们与原图⽐对。
逸出功公式
然后再找到这个标签,将display设置为block:
原图显⽰出来,我们可以将上⾯两张图⽚的滑动验证图⽚进⾏截取,⽐对,即可找到缺⼝位置。
实现过程中要注意⼏点:
1.lenium在加载后,不要⽴即寻找标签,因为如果标签没有加载完成,会找不到,这样就会抛出错误。
告白情书
2.截图的⼤⼩可以跟浏览器的内显⽰的⼤⼩不⼀样,需要计算浏览器显⽰⼤⼩与截图⼤⼩的⽐例。
3.进⾏滑动时,要先加速后减速,如果⼀直匀速,会被⽹站识别。
⼆、实现
身上发冷1、导⼊相关要⽤的包:
from lenium importwebdriverfrom by importByfrom lenium.webdriver.support importexpected_conditions as ECfrom lenium.webdriver.support.wait importWebDriverWaitfrom PIL importImagefrom six importBytesIOimporttimefrom lenium.webdriver import ActionChains
2.主函数:
if __name__ == '__main__':
browr=get_url('/login','11111111111','********') #此函数的定义在第3点
time.sleep(1)
slice_img_label= browr.find_element_by_css_lector('st_slicebg') #找到滑动图⽚标签
full_img_label = browr.find_element_by_css_lector('st_canvas_fullbg') #原始图⽚的标签
position = get_position(slice_img_label) #获取滑动验证图⽚的位置,此函数的定义在第4点
screenshot = get_screenshot(browr) #截取整个浏览器图⽚,此函数的定义在第5点
position_scale = get_position_scale(browr,screenshot) #获取截取图⽚宽⾼和浏览器宽⾼的⽐例,
此函数的定义在第6点
slice_img = get_slideimg_screenshot(screenshot,position,position_scale) #截取有缺⼝的滑动验证图⽚,此函数的定义在第7点
screenshot = get_screenshot(browr) #获取整个浏览器图⽚
full_img = get_slideimg_screenshot(screenshot,position,position_scale) #截取滑动验证原图
显⽰
left = compare(full_img,slice_img) #将原图与有缺⼝图⽚进⾏⽐对,获得缺⼝的最左端的位置,此函数定义在第8点
left = left / position_scale[0] #将该位置还原为浏览器中的位置
slide_btn= browr.find_element_by_css_lector('.geetest_slider_button') #获取滑动按钮
track = get_track(left) #获取滑动的轨迹,此函数定义在第9点
move_to_gap(browr,slide_btn,track) #进⾏滑动,此函数定义在第10点
success = browr.find_element_by_css_lector('.geetest_success_radar_tip') #获取显⽰结果的标签
time.sleep(2) == "验证成功":
login_btn= browr.find_element_by_css_lector('button.j-login-btn') #如果验证成功,则点击登录按钮
login_btn.click()el:)print('失败')
下⾯是主函数中⽤到的各个功能性函数:
青少年礼仪3..定义访问页⾯的函数:
defget_url(url,ur,password):
browr=webdriver.Chrome()
<(url)
browr.maximize_window()
wait= WebDriverWait(browr,10)
wait.until(EC.prence_of_element_located((By.CLASS_NAME,'geetest_radar_btn')))
ur_input= browr.find_element_by_id('urname')
pwd_input= browr.find_element_by_id('password')
btn= browr.find_element_by_css_lector('.geetest_radar_btn')
ur_input.nd_keys(ur)
爱要怎么说出口歌词pwd_input.nd_keys(password)
《秋》巴金btn.click()
time.sleep(0.5)return browr
此函数主要是⽤于启动Chrome,打开⽹页,将⽤户名和密码填⼊相应位置,并点击验证按钮。
4.获取滑动验证图⽚在浏览器的位置。
使⽤location是获取标签左上⾓的位置,然后再通过该标签的⼤⼩,即可算出其四个⾓的位置。
defget_position(img_label):
location=img_label.location
size=img_label.size
top, bottom, left, right= location['y'], location['y'] + size['height'], location['x'], location['x'] +size['width']return (left, top, right, bottom)
5.获取整个浏览器的截图。并从内存进⾏读取。
defget_screenshot(browr):
_screenshot_as_png()
f=BytesIO()
f.write(screenshot)return Image.open(f)
6.通过对⽐截图和浏览器宽⾼的⼤⼩,算出换算⽐例。
由于截图是有浏览器的边缘的拖拽条,所以浏览器的宽度+10px
defget_position_scale(browr,screen_shot):
height= ute_script('return document.documentElement.clientHeight')
width= ute_script('return document.documentElement.clientWidth')
x_scale= screen_shot.size[0] / (width+10)
y_scale= screen_shot.size[1] /(height)return (x_scale,y_scale)
7.截取有缺⼝的滑动图⽚:
defget_slideimg_screenshot(screenshot,position,scale):
x_scale,y_scale=scale
position= [position[0] * x_scale, position[1] * y_scale, position[2] * x_scale, position[3] *y_scale]return
8.将原始图⽚和有缺⼝的图⽚进⾏⽐较:
defcompare_pixel(img1,img2,x,y):
pixel1=img1.load()[x,y]
pixel2=img2.load()[x,y]
threshold= 50
貔貅公母怎么区分
if abs(pixel1[0]-pixel2[0])<=threshold:if abs(pixel1[1]-pixel2[1])<=threshold:if abs(pixel1[2]-pixel2[2])
酸奶解酒<=threshold:returnTruereturnFaldefcompare(full_img,slice_img):
left= 0
for i inrange(full_img.size[0]):for j in range(full_img.size[1]):if notcompare_pixel(full_img,slice_img,i,j):returnireturn left
9.计算出滑动的轨迹,其实就是简单的s = 1/2*a*t*t的简单公式。这部分代码,直接⽤的崔庆才博主的代码:
defget_track(distance):"""根据偏移量获取移动轨迹
:param distance: 偏移量
:return: 移动轨迹"""
#移动轨迹
track =[]#当前位移
current =0#减速阈值
mid = distance * 4 / 5
#计算间隔
t = 0.2
#初速度
v =0while current
a = 4
el:#加速度为负 3
a = -3
#初速度 v0
v0 =v#当前速度 v = v0 + at
v = v0 + a *t#移动距离 x = v0t + 1/2 * a * t^2
move = v0 * t + 1 / 2 * a * t *t#当前位移
current +=move#加⼊轨迹
track.append(round(move))return track
10.进⾏移动:
defmove_to_gap(browr,slider, tracks):"""拖动滑块到缺⼝处
:param slider: 滑块
:param tracks: 轨迹
:return:"""ActionChains(browr).click_and_hold(slider).perform()for x intracks:
ActionChains(browr).move_by_offt(xofft=x, yofft=0).perform()
time.sleep(0.5)
ActionChains(browr).relea().perform()
以上3-10是定义的功能性函数,放在前⾯,2是主函数,放在后⾯。运⾏即可。也可以将其写为⼀个类,使⽤时更为⽅便。此处,只是为实现功能,所以就没有进⼀步进⾏规范。