首页 > 编程 > Python > 正文

python破解bilibili滑动验证码登录功能

2019-11-25 11:44:03
字体:
来源:转载
供稿:网友

地址:https://passport.bilibili.com/login

左图事完整验证码图,右图是有缺口的验证码图

                                                                    

步骤:

1.准备bilibili账号

2.工具:pycharm selenium chromedriver PIL

3.破解思路:

找到完整验证码和有缺口的验证码图片,然后计算缺口坐标,再利用selenium移动按钮到指定位置,齐活

步骤代码如下:

先导入需要的包和库

from selenium import webdriverfrom selenium.webdriver.support.wait import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import Byfrom selenium.webdriver import ActionChainsfrom urllib.request import urlretrievefrom bs4 import BeautifulSoupfrom lxml.html import etreeimport re,requestsfrom PIL import Imagefrom time import sleepfrom .config import username,passwordclass Jiyan_test:  def __init__(self):    self.url='https://passport.bilibili.com/login'    self.brower=webdriver.Chrome('chromedriver')    self.wait=WebDriverWait(self.brower,20)#设置等待   def login(self):    self.brower.get(self.url)    self.user=self.wait.until(EC.presence_of_element_located((By.ID,'login-username')))    self.passwd=self.wait.until(EC.presence_of_element_located((By.ID,'login-passwd')))    self.user.send_keys(username)    self.passwd.send_keys(password)  def get_images(self):#获取验证码图片    # print(self.brower.page_source)    full_position=[]#完整散图坐标    bg_position=[]#缺口散图坐标    html=etree.HTML(self.brower.page_source)    gt_cut_fullbg_slices=html.xpath('//div[@class="gt_cut_fullbg_slice"]/@style')    full_slice_url=re.findall('url/(/"(.*)/"/);',gt_cut_fullbg_slices[0])[0].replace('webp','jpg')    gt_cut_bg_slices = html.xpath('//div[@class="gt_cut_bg_slice"]/@style')    bg_slice_url = re.findall('url/(/"(.*)/"/);', gt_cut_bg_slices[0])[0].replace('webp', 'jpg')    print(gt_cut_fullbg_slices)    for i in gt_cut_fullbg_slices:      position=re.findall('background-position: (.*);',i)[0].replace('px','').split(' ')      position=[int(i) for i in position]      full_position.append(position)    for i in gt_cut_fullbg_slices:      position = re.findall('background-position: (.*);', i)[0].replace('px','').split(' ')      position=[int(i) for i in position]      bg_position.append(position)    print(full_position)    print(bg_position)    print(full_slice_url)    print(bg_slice_url)    full_pic_data=requests.get(full_slice_url).content    bg_pic_data=requests.get(bg_slice_url).content    with open('image/full_pic.jpg','wb') as f:      f.write(full_pic_data)    with open('image/bg_pic.jpg', 'wb') as f:      f.write(bg_pic_data)    full_image=Image.open('image/full_pic.jpg')    bg_image=Image.open('image/bg_pic.jpg')    return full_image,bg_image,full_position,bg_position

分割图片 

def pic_cut(self,file,position):#分割图片    first_line_pic=[]    second_line_pic=[]    # full_image, bg_image, full_position, bg_position=self.get_images()    for p in position:      if p[1]==-58:        first_line_pic.append(file.crop((abs(p[0]),58,abs(p[0])+10,166)))      if p[1]==0:        second_line_pic.append(file.crop((abs(p[0]),0,abs(p[0])+10,58)))    print(first_line_pic)    print(second_line_pic)    return first_line_pic,second_line_pic

合并图片

   

 def merge_pics_new(self,first_line_pic,second_line_pic,file_name):    #新建图片    image=Image.new('RGB',(260,116))    offset=0#设置偏移量    #拼接第一行    for i in first_line_pic:      image.paste(i,(offset,0))      offset+=i.size[0]    offset_x=0    #拼接第二行    for j in second_line_pic:      image.paste(j,(offset_x,58))      offset_x+=j.size[0]    image.save('image/'+file_name)#合成完整图片   def merge_pics(self):#合并图片    #先割切乱码图片    full_image, bg_image, full_position, bg_position=self.get_images()    first_line_pic, second_line_pic=self.pic_cut(full_image,full_position)    self.merge_pics_new(first_line_pic, second_line_pic,'full_new_pic.jpg')    first_line_pic, second_line_pic = self.pic_cut(bg_image, bg_position)    self.merge_pics_new(first_line_pic, second_line_pic, 'bg_new_pic.jpg')

再判断图片是否一样

  def check_pics_is_same(self,bg_image,full_image,x,y):#判断图片是否一样    bg_pixel=bg_image.getpixel((x,y))    full_pixel=full_image.getpixel((x,y))    for i in range(0,3):      if abs(bg_pixel[i]-full_pixel[i])>=50:        return False      else:        return True

计算滑块距离

   

def reckon_distance2(self):#计算滑块    try:      full_image = Image.open('image/full_new_pic.jpg')      bg_image = Image.open('image/bg_new_pic.jpg')      for i in range(0,full_image.size[0]):        for j in range(0,full_image.size[1]):          if not self.check_pics_is_same(bg_image,full_image,i,j):            return i    except Exception:      print('图片读取失败')

计算运动轨迹

    

def reckon_trail(self):#计算运动轨迹    print('计算运动轨迹')    track=[]    distance=self.reckon_distance2()    distance=int(distance)-7#矫正值    print('缺口坐标',distance)    fast_distance=distance*(4/5)    start,v0,t=0,0,0.2    while start<distance:      if start<fast_distance:#加速状态        a=1.5#加速      else:        a=-3#减速      #数学公式 s=v0*t+1/2 v*t平方      move=v0*t+1/2*a*t*t      #当前速度      v=v0+a*t      #重置粗速度      v0=v      #重置起始位置      start+=move      track.append(round(move))    return track

 

模拟拖动

def move_block(self):# 模拟拖动滑块    print('开始模拟')    track=self.reckon_trail()    #找寻滑块标签    slider=self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'gt_slider_knob')))    ActionChains(self.brower).click_and_hold(slider).perform()#执行    for x in track:      ActionChains(self.brower).move_by_offset(xoffset=x,yoffset=0).perform()    sleep(0.4)    ActionChains(self.brower).release().perform()#释放滑块 if __name__ == '__main__':  c=Jiyan_test()  c.login()  c.merge_pics()  c.move_block()

测试运行正常,偶尔有对不准的现象,需要调整distance的值

总结

以上所述是小编给大家介绍的python破解bilibili滑动验证码登录功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对武林网网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表