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

yipeiwu_com5年前Python基础

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

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

                                                                    

步骤:

1.准备bilibili账号

2.工具:pycharm selenium chromedriver PIL

3.破解思路:

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

步骤代码如下:

先导入需要的包和库

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
from urllib.request import urlretrieve
from bs4 import BeautifulSoup
from lxml.html import etree
import re,requests
from PIL import Image
from time import sleep
from .config import username,password
class 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滑动验证码登录功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对【听图阁-专注于Python设计】网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

相关文章

仅用500行Python代码实现一个英文解析器的教程

仅用500行Python代码实现一个英文解析器的教程

语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们对世界的了解可以迅速地发现这些歧义。举一个我很喜欢的例子: 正确的解析是连接“wi...

python内置函数:lambda、map、filter简单介绍

lambda lambda可以理解为一种小函数,但是它是一个表达式,而不是一个语句,所以在def不允许出现的地方仍然可以使用lambda函数,例如list里。但是lambda内只可以执行...

Python面向对象程序设计多继承和多态用法示例

Python面向对象程序设计多继承和多态用法示例

本文实例讲述了Python面向对象程序设计多继承和多态用法。分享给大家供大家参考,具体如下: 多继承 就是一个子类继承多个父类: 多继承的例子,如下: # -*- coding:u...

python33 urllib2使用方法细节讲解

Proxy 的设置 urllib2 默认会使用环境变量 http_proxy 来设置 HTTP Proxy。如果想在程序中明确控制 Proxy 而不受环境变量的影响,可以使用下面的方式...

Python Matplotlib 基于networkx画关系网络图

Python Matplotlib 基于networkx画关系网络图

前言 昨天才开始接触,鼓捣了一个下午,接下来会持续更新,如果哪里有错误的地方,望各位大佬指出,谢谢! 数据描述 两个文件,一个文件包含了网络图的节点,节点存在类别(0,1,2,3)四类,...