BiliBili 滑动解锁【代码】

基本方案:

一、获取Bilibili的乱码图片地址,并保存到本地

二、获取图片的坐标

三、根据坐标,将乱码图片进行切割

四、将切割的图片进行重新拼接

五、校验拼接好的原图与缺口图的像数值,得出需要滑动的距离

六、计算滑动轨迹

from time import sleep

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from PIL import Image

from lxml.html import etree
import re, requests



class BiliBiliSlideCode:

    def __init__(self):
        self.driver = webdriver.Chrome()
        self.wait = WebDriverWait(self.driver, 10)

        
    def _findEle(self, *loc):
        try:
            self.wait.until(EC.presence_of_element_located(*loc))
            return self.driver.find_element(by=loc[0][0], value=loc[0][1])
        except:
            print("没有找到元素 %s" % loc)

            
            
    def open(self, user, passw):
        self.driver.get('https://passport.bilibili.com/login')
        # self.driver.maximize_window()
        self._findEle((By.ID, 'login-username')).send_keys(user)
        self._findEle((By.ID, 'login-passwd')).send_keys(passw)

        
    def get_image(self):

        bg_image_path = 'image/bg_messy_code.jpg'
        fullbg_image_path = 'image/fullbg_messy_code.jpg'

        html = etree.HTML(self.driver.page_source)

        # 获取乱码图片的URL 地址
        fullbg_image_styles = html.xpath("//div[contains(@class,'gt_cut_fullbg gt_show')]//@style")
        fullbg_image_url = str(re.findall('url\(\"(.*?)\"\)', fullbg_image_styles[0])[0]).replace('webp', 'jpg')

        bg_image_styles = html.xpath("//div[contains(@class,'gt_cut_bg gt_show')]//@style")
        bg_image_url = str(re.findall('url\(\"(.*?)\"\)', bg_image_styles[0])[0]).replace('webp', 'jpg')

        # 将乱码图片保存到本地
        with open(bg_image_path, 'wb') as f:
            bg_image_data = requests.get(bg_image_url).content
            f.write(bg_image_data)

        with open(fullbg_image_path, 'wb') as f:
            fullbg_image_data = requests.get(fullbg_image_url).content
            f.write(fullbg_image_data)

        bg_messy_code_image = Image.open(bg_image_path)
        fullbg_messy_code_image = Image.open(fullbg_image_path)

        return bg_messy_code_image, self._potions(bg_image_styles), \
               fullbg_messy_code_image, self._potions(fullbg_image_styles)

        
        
    # 获取乱码图片的坐标
    def _potions(self, image_styles: any):
        image_postions = []

        for image_style in image_styles:
            postion = re.findall('position:(.*?);', image_style)[0]
            scope = postion.replace('px', '').strip().split(' ')
            image_postions.append([int(scope[0]), int(scope[1])])
        return image_postions

    # 切割乱码图片
    def split_image(self, image: Image.Image, potions: [[]]):
        first_images = []
        second_image = []

        for p in potions:
            width = abs(p[0])

            if p[1] == -58:
                box = width, 58, width + 10, 116
                first_images.append(image.crop(box))
            else:
                box = width, 0, width + 10, 58
                second_image.append(image.crop(box))
        return first_images, second_image

    # 拼接乱码图片
    def _joint_image(self, first_images, second_images, filename):
        image = Image.new("RGB", (260, 116))

        first_i = 0
        for first_image in first_images:
            print()
            image.paste(first_image, (first_i, 0))
            first_i += first_image.size[0]

        second_i = 0
        for second_image in second_images:
            image.paste(second_image, (second_i, 58))
            second_i += second_image.size[0]
        image.save(filename)

    # 合并乱码图片
    def merge_messy_image(self):
        bg_image, bg_potions, fullbg_image, fullbg_potions = self.get_image()

        bg_first_images, bg_second_images = self.split_image(bg_image, bg_potions)
        fullbg_first_images, fullbg_second_images = self.split_image(fullbg_image, fullbg_potions)

        self._joint_image(bg_first_images, bg_second_images, 'image/bg_merge_image.jpg')
        self._joint_image(fullbg_first_images, fullbg_second_images, 'image/fullbg_merge_image.jpg')


    def image_is_same(self, bg_image: Image.Image, fullbg_image: Image.Image, x, y):

        bg_pixel = bg_image.getpixel((x, y))
        fullbg_pixel = fullbg_image.getpixel((x, y))

        for i in range(0, 3):
            if abs(bg_pixel[i]) - abs(fullbg_pixel[i]) >= 50:
                return False
            else:
                return True

    def count_slide_chunk(self):
        bg_image = Image.open('image/bg_merge_image.jpg')
        fullbg_image = Image.open('image/fullbg_merge_image.jpg')

        for i in range(0,bg_image.size[0]):
            for j in range(0,bg_image.size[1]):
                if not self.image_is_same(bg_image,fullbg_image,i,j):
                    return i

    def reckon_trail(self):  # 计算运动轨迹
        print('计算运动轨迹')
        track = []
        distance = self.count_slide_chunk()
        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
            print("move : %s" % move)
            # 当前速度
            v = v0 + a * t
            print("v : %s" % v)
            # 重置粗速度
            v0 = v
            print("v0 : %s" % v0)
            # 重置起始位置
            start += move
            print("start : %s" % start)
            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.driver).click_and_hold(slider).perform()  # 执行
        for x in track:
            ActionChains(self.driver).move_by_offset(xoffset=x, yoffset=0).perform()
        ActionChains(self.driver).release().perform()  # 释放滑块


if __name__ == '__main__':
    bili_code = BiliBiliSlideCode()
    bili_code.open('13681950786', '652855fuck')
    bili_code.merge_messy_image()
    bili_code.move_block()


参考地址: https://blog.csdn.net/thindi/article/details/83152903

猜你喜欢

转载自blog.csdn.net/weixin_38708177/article/details/88234312