爬虫模拟登录破解无原图滑动验证码: https://www.cnblogs.com/98WDJ/p/11050559.html
需求:部分网站在频繁的使用之后,会弹出滑块验证码(极验)。有别于过去,现在的原图并不会出现,因此较过去的思路转变为以下:
1、截取带缺口的图片;
2、寻找原图,并截图;
3、比较两张图片,寻找到缺口位置距离;
4、计算运动过程,并驱动浏览器移动滑块。
参考链接基本提供了1-3步的实现,第4步存在被识别为机器操作,需要进行更新(修正以后,目前成功率应该有50%以上),记录如下。
一、启动浏览器,配置option,以防被识别为自动化。
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait from selenium.common.exceptions import TimeoutException from selenium.webdriver import ActionChains from PIL import Image import numpy as np import pandas as pd import time # 配置浏览器 options = webdriver.ChromeOptions() # 此步骤很重要,设置为开发者模式,防止被各大网站识别出来使用了Selenium options.add_experimental_option('excludeSwitches', ['enable-automation'])
二、获取两张图片进行比较,通过网页分析发现。该标签,当display=block,opacity=1时,显示的为原图。
# 获取第一个图 img_name1 = r'../data/png/captcha2.png' img_name2 = r'../data/png/captcha2_src.png' img = wait.until(EC.presence_of_element_located((By.XPATH,'//canvas[@class="geetest_canvas_slice geetest_absolute"]'))) img.screenshot(img_name1) # 获取原图 browser.execute_script("var x=document.getElementsByClassName('geetest_canvas_fullbg geetest_fade geetest_absolute')[0];" "x.style.display='block';" "x.style.opacity=1" ) img = wait.until(EC.presence_of_element_located((By.XPATH,'//canvas[@class="geetest_canvas_slice geetest_absolute"]'))) img.screenshot(img_name2) # 变回来 browser.execute_script("var x=document.getElementsByClassName('geetest_canvas_fullbg geetest_fade geetest_absolute')[0];" "x.style.display='none';" "x.style.opacity=0" )
三、计算两张图片差异,通过rgb一定的缺值进行判断缺口。
# 如何能找到滑块的位置 def get_distance(img1,img2): start_x=60#初始X threhold=60#阈值 for x in range(start_x,img1.size[0]): for y in range(img1.size[1]): rgb1=img1.load()[x,y] rgb2=img2.load()[x,y] res1=abs(rgb1[0]-rgb2[0]) res2=abs(rgb1[1]-rgb2[1]) res3=abs(rgb1[2]-rgb2[2]) if not (res1<threhold and res2<threhold and res3<threhold): return x-7#测试后-7可以提高成功率
四、计算模拟移动,根据自身的挪动特点,我一般的移动操作分为三个阶段(可根据自身特点进行设计)。
1:点击滑块以后,缓慢移动一下。约移动3次。
2:快速移动到缺口附件。大概0.3s。
3:到了缺口附近以后,缓慢靠近,然后在缺口处停留大概0.5秒以后释放。
# 将整个过程分为3段,总时长大概是1.2-1.6秒 # 第一段是启动阶段,第一次点击的时候,总会比较拘谨,慢速启动,大概消费t2(0.3)秒,s2为分段数 # 第二段则是很快到达缺口附近,大概剩余d3(5)距离处 # 第三段是缓慢对接,最后停在上面0.5秒 def get_tracks(distance,s1 = 2,t2 = 0.3,s2 = 3,d3 = 5): # 计算d1移动过程 dtemp = 0 track1 = [] for i in range(s1): t = np.random.randint(low = 1, high=3) track1.append(t) dtemp = dtemp + t # 计算d2距离 distance =distance - dtemp - d3 track2 = [] a = 2 * distance /(t2 ** 2) dtemp = 0 for i in range(s2): # 计算每段行走 ttemp1 = t2/s2 * (i + 1) ttemp2 = t2/s2 * i t = int(0.5 * a * (ttemp1 ** 2) - 0.5 * a * (ttemp2 ** 2) ) track2.append(t) dtemp = dtemp + t #由于取整了,可以存在一点误差,调整d3 d3 = distance - dtemp + d3 print(d3) track3 = [] s = 0 while s < d3: t = np.random.randint(low = 1, high=3) if s + t >= d3: track3.append(d3 - s) break else: s = s + t track3.append(t) return {"track1": track1, 'track2': track2, 'track3': track3}
%%time # 计算路径,不行,这个会被识别为计算机 #获得滑块元素 geetest_slider_button=browser.find_element_by_class_name('geetest_slider_button') #获得距离 img1 = Image.open(img_name1) img2 = Image.open(img_name2) distance=get_distance(img1,img2) #获得步数 tracks_dic=get_tracks(distance,s1 = 2,t2 = 0.2,s2 = 3,d3 = 5) #点击并按住 ActionChains(driver).click_and_hold(geetest_slider_button).perform() track1=tracks_dic['track1'] track2=tracks_dic['track2'] track3=tracks_dic['track3']
最后,遍历执行动作链。
%%time # 执行 ActionChains(browser).click_and_hold(geetest_slider_button).perform() # 执行第一步 for t in track1: ActionChains(browser).move_by_offset(xoffset=t,yoffset=0).perform() #停顿一会,更像人 time.sleep(0.2) for t in track2: ActionChains(browser).move_by_offset(xoffset=t,yoffset=0).perform() for t in track3: ActionChains(browser).move_by_offset(xoffset=t,yoffset=0).perform() time.sleep(0.5) # 松开 ActionChains(browser).release(geetest_slider_button).perform()
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python + selenium 爬虫模拟登录破解无原图滑动验证码 - Python技术站