声明:滑块验证码更迭速度超快的,很多更替都体现在细节上,只有破解的过程中才能体会到真正的破解痛点,而本人是在18年中旬做的滑块验证码破解,所以最新版滑块验证码肯定是更新过好多次了的,因此本文主要提供一种破解思路,如果源码能给你带来直接借鉴作用那是最好。
废话不多说,直接上源码!
#--PANDA Edit--
from PIL import Image
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time,requests,random
class Verification_Code:
#匹配原图
def match_source(self,image):
imagea=Image.open('d://source1.png')
imageb=Image.open('d://source2.png')
imagec=Image.open('d://source3.png')
imaged=Image.open('d://source4.png')
list=[imagea,imageb,imagec,imaged]
#通过像素差遍历匹配本地原图
for i in list:
pixel1 = image.getpixel((868, 340))
pixel2 = i.getpixel((868, 428))
if abs(pixel1[0]-pixel2[0])<5:
return i
return image
#对比RGB值得到缺口位置
def is_similar(self,image1,image2,x,y):
pixel1 = image1.getpixel((x, y + 88))
pixel2 = image2.getpixel((x, y))
if abs(pixel1[0] - pixel2[0]) >= 50 and abs(pixel1[1] - pixel2[1]) >= 50 and abs(pixel1[2] - pixel2[2]) >= 50:
return False
return True
#计算滑块位移距离
def get_diff_location(self,image1,image2):
for i in range(825, 1082):
for j in range(335, 463):
if self.is_similar(image1,image2,i,j)==False:
return i
return -1
#滑块移动轨迹
def get_track(self,distance):
track=[]
current=0
mid=distance*7/8
t=random.randint(2,3)/10
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 check_success(self,image1,image2,driver,run):
pixel1=image1.getpixel((1032,480))
pixel2=image2.getpixel((1032,568))
if abs(pixel1[0] - pixel2[0]) <10 and abs(pixel1[1] - pixel2[1])<10 and abs(pixel1[2] - pixel2[2])<10:
return True
else:
if run<3:
refresh=driver.find_element_by_class_name('geetest_refresh_1')
refresh.click()
return False
#主程序
def run(self,URL,token,phoneNumber):
driver = webdriver.Chrome()
# 打开页面
driver.get('https://account.ch.com/NonRegistrations-Regist')
driver.maximize_window()
input1 = driver.find_element_by_name('phoneNumberInput')
# 输入注册号码
input1.send_keys(phoneNumber)
time.sleep(0.2)
getcheck=driver.find_element_by_id('getDynamicPwd')
getcheck.click()
flag0=1
flag1=1
run=1
#循环验证
while flag1==1:
time.sleep(1)
# 获取拖拽元素
try:
slideblock = driver.find_element_by_class_name('geetest_slider_button')
except:
print('网络延迟')
self.cancelRecv(URL, token, phoneNumber)
flag0=0
break
ActionChains(driver).click_and_hold(slideblock).perform()
ActionChains(driver).move_by_offset(xoffset=250, yoffset=0).perform()
time.sleep(0.4)
# 获取包含滑块及缺口截屏图片
driver.save_screenshot('D:\quekou.png')
# 放开拖拽元素
ActionChains(driver).release(slideblock).perform()
quekouimg=Image.open('d://quekou.png')
# 匹配本地对应原图
sourceimg=self.match_source(quekouimg)
# 获取缺口位置
visualstack=self.get_diff_location(sourceimg,quekouimg)
# 获取移动距离loc
loc=visualstack-827
# 生成拖拽移动轨迹
track_list=self.get_track(loc+3)
time.sleep(2)
ActionChains(driver).click_and_hold(slideblock).perform()
time.sleep(0.2)
# 根据轨迹拖拽滑块
for track in track_list:
ActionChains(driver).move_by_offset(xoffset=track,yoffset=0).perform()
# 模拟人工滑动超过缺口位置返回至缺口的情形,增加移动轨迹真实性
imitate=ActionChains(driver).move_by_offset(xoffset=-1, yoffset=0)
time.sleep(0.015)
imitate.perform()
time.sleep(random.randint(6,10)/10)
imitate.perform()
time.sleep(0.04)
imitate.perform()
time.sleep(0.012)
imitate.perform()
time.sleep(0.019)
imitate.perform()
time.sleep(0.033)
ActionChains(driver).move_by_offset(xoffset=1, yoffset=0).perform()
# 放开拖拽元素
ActionChains(driver).pause(random.randint(7,14)/10).release(slideblock).perform()
time.sleep(1)
driver.save_screenshot('d:\checkpicture.png')
checkimg=Image.open('d:\checkpicture.png')
#判断是否验证成功
if self.check_success(checkimg,sourceimg,driver,run):
time.sleep(3.5)
flag1 = 0
# 检查手机号码获取验证码次数是否已达上限
try:
driver.find_element_by_tag_name('button').click()
flag0 = 0
self.addBlacklist(URL, token, phoneNumber)
print('本号码注册获取验证码次数已达上限')
except:
print()
run+=1
if run>3 and flag1==1: #判断多次循环后滑块验证码是否通过
self.cancelRecv(URL, token, phoneNumber)
flag0=0
break
#填入验证码进行注册
if flag0==1:
count = 1
while True:
messageContent = requests.get(URL,"action=getMessage&sid=987&phone=" + phoneNumber + "&token=" + token).text
# 截取头信息
header = messageContent[0:messageContent.index("|")]
#判断是否接收到验证码
if header == '0':
time.sleep(3.5)
if count > 5:
self.addBlacklist(URL, token, phoneNumber)
break
if header == '1':
messageInfo = messageContent[messageContent.index("|") + 1:len(messageContent)]
verificationCode = messageInfo[messageInfo.index("验证码:") + len("验证码:"):messageInfo.index(",",messageInfo.index("验证码:"))]
#填入验证码
driver.find_element_by_name('ValidateCode').send_keys(verificationCode)
#填入密码
driver.find_element_by_name('phonePassword').send_keys('wsk190120')
#确认密码
driver.find_element_by_name('phonePasswordConfirm').send_keys('wsk190120')
#点击注册
driver.find_element_by_id('dynamicRegist').click()
time.sleep(2)
#利用是否跳转页面判断是否成功注册
try:
driver.find_element_by_class_name('u-dialog-btn').click()
self.addBlacklist(URL, token, phoneNumber)
except:
print('注册成功')
f=open('d://output.txt','a+')
f.write('INSERT INTO map_chuser VALUES(null,'+'\''+phoneNumber+'\''+',\''+'wsk190120'+'\''+',0,0,1);'+'\n')
f.close()
break
count+=1
time.sleep(0.5)
driver.close()
#获取手机号码
def getPhone(self,URL,loginInfo,token):
phoneInfo = requests.get(URL, "action=getPhone&sid=987&token=" + token).text
return phoneInfo[loginInfo.index("|") + 1:len(loginInfo)]
#手机号码加黑
def addBlacklist(self,URL,token,phoneNumber):
requests.get(URL, "action=addBlacklist&sid=987&phone=" + phoneNumber + "&token=" + token)
#手机号码释放
def cancelRecv(self,URL,token,phoneNumber):
requests.get(URL,'action=cancelRecv&sid=987&phone='+phoneNumber+'&token='+token)
#生成随机密码
'''def random_str(self,randomlength):
str = ''
chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
length = len(chars) - 1
for i in range(randomlength):
str += chars[random.randint(0, length)]
return str'''
if __name__=='__main__':
auto_logon = Verification_Code()
URL = "http://www.ximahuang.com/alz/api"
for i in range(5):
try:
print(i)
#开发者登录吸码皇
loginInfo = requests.get(URL,b'action=loginIn&name=xtpa001&password=190120&developer=developer=df64aff97eb04560af80ba7834f4e6c9').text
#截取登录令牌
token = loginInfo[loginInfo.index("|") + 1:len(loginInfo)]
#获取用户信息
userInfo = requests.get(URL, "action=getSummary&token=" + token)
#获取手机号码
phoneNumber = auto_logon.getPhone(URL,loginInfo, token)
#获取验证码进行验证注册
auto_logon.run(URL,token,phoneNumber)
except:
print('注册提前结束!')
print('程序结束!')