BILIBILI之滑块验证

bilibili的滑动验证码图片比较好玩,和前一篇不大一样。

采用canvas方法,分析发现只找到一个图片,不过,可以通过设置display截图方式获得2张图(完整图片,带缺口的图片),取得图片后接下来的方式和前一篇一样,偏移位置参数存在差异,需要自行调试。完整代码如下

#!/usr/bin/env python
# encoding: utf-8
#@author: jack
#@contact: [email protected]
#@site: https://www.cnblogs.com/jackzz
import re
from time import sleep
from selenium import webdriver
import random
import requests
from PIL import Image
from selenium.webdriver.support.ui import WebDriverWait
from  selenium.webdriver.support import expected_conditions as EC
from  selenium.webdriver.common.by import By
from  io import BytesIO
from selenium.webdriver.common.action_chains import ActionChains

USERNAME =  '123456'
PASSWORD = '123456'


class BiliLogin(object):

    def __init__(self):
        '''
        初始化
        '''
        self.login_url = 'https://passport.bilibili.com/login'
        self.driver = webdriver.Firefox()
        self.wait = WebDriverWait(self.driver,10)
        self.driver.maximize_window()

    def input_info(self):
        '''
        输入账号密码
        :return:
        '''
        self.driver.get(self.login_url)
        username = self.wait.until(EC.presence_of_element_located((By.ID,'login-username')))
        password = self.wait.until(EC.presence_of_element_located((By.ID,'login-passwd')))
        username.send_keys(USERNAME)
        password.send_keys(PASSWORD)
        sleep(1)

    def click_login_button(self):
        '''
        点击登陆按钮
        :return:
        '''
        login_button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'btn-login')))
        login_button.click()
        sleep(1)

    def get_captcha_image(self):
        '''
        获取验证码图片
        :return:
        '''
        geetest_canvas_bg = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'geetest_canvas_bg')))
        geetest_canvas_bg.screenshot('bg.png')
        image_bg = Image.open('bg.png')
        #通过js代码修改标签样式 显示图片2
        js = 'var change = document.getElementsByClassName("geetest_canvas_fullbg");change[0].style = "display:block;"'
        self.driver.execute_script(js)
        sleep(3)
        geetest_canvas_fullbg = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'geetest_canvas_fullbg')))
        geetest_canvas_fullbg.screenshot('fullbg.png')
        image_fullbg = Image.open('fullbg.png')
        return image_bg,image_fullbg

    def get_diff_location(self,image1, image2):
        '''
        通过像素对比 找到缺口位置
        :param image1:
        :param image2:
        :return:
        '''
        for x in range(65, image1.size[0]):
            for y in range(image1.size[1]):
                if self.is_similar(image1, image2, x, y) == False:
                    # 判断成立 表示xy这个点 两张图不一样
                    return x

    def is_similar(self,image1, image2, x, y):
        pixel1 = image1.getpixel((x, y))
        pixel2 = image2.getpixel((x, y))

        for i in range(0, 3):
            if abs(pixel1[i]) - pixel2[i] >= 60:
                return False
        return True

    def get_track(self,x):
        '''
        滑块移动轨迹
        初速度 v =0
        单位时间 t = 0.2
        位移轨迹 tracks = []
        当前位移 ccurrent = 0
        :param x:
        :return:
        '''
        v = 0
        t = 0.2
        tracks = []
        current = 0
        mid = x*4/5#到达mid值开始减速

        while current < x:
            if current < mid:
                a = random.randint(1,3)
            else:
                a = -random.randint(2,4)
            # a = 2
            v0 = v
            # 单位时间内位移公式
            s = v0 * t + 0.5 * a * (t ** 2)
            # 当前位移
            current = current + s
            tracks.append(round(s))
            v = v0 + a * t
        return tracks

    def move_to_xoffset(self,tracks):
        element = self.driver.find_element_by_class_name('geetest_slider_button')
        ActionChains(self.driver).click_and_hold(element).perform()
        for x in tracks:
            ActionChains(self.driver).move_by_offset(xoffset=x, yoffset=0).perform()
        ActionChains(self.driver).release(element).perform()
        sleep(3)

    def main(self):
        self.input_info()
        self.click_login_button()
        image_bg,image_fullbg = self.get_captcha_image()
        xoffset = self.get_diff_location(image_bg,image_fullbg)
        print(xoffset)
        tracks = self.get_track(xoffset-7)
        print(tracks)
        self.move_to_xoffset(tracks)
        sleep(2)
        try:

            self.driver.find_elements_by_class_name('xxxxxxx')
        except:
            self.driver.refresh()
            self.main()

if __name__ == '__main__':
    bili = BiliLogin()
    try:
        count = 5
        while count > 0:
            bili.main()
            count -= 1
    except Exception as e:
        print('识别错误,继续')
    finally:
        print('恭喜通过滑块验证')
        sleep(2)
        bili.driver.quit()
完整代码

猜你喜欢

转载自www.cnblogs.com/jackzz/p/11444409.html