美文网首页
bilibili滑块

bilibili滑块

作者: 是东东 | 来源:发表于2021-07-27 15:02 被阅读0次
# -*- coding: utf-8 -*-


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
import time
import random
from PIL import Image

# 初始化

# 登录界面的url
url = 'https://passport.bilibili.com/login'
# 实例化一个chrome浏览器
browser = webdriver.Chrome()
# 用户名
username = '18519146290'
# 密码
password = 'xc080218'
# 设置等待超时
wait = WebDriverWait(browser, 20)


# 登录
def login():
    # 打开登录页面
    browser.get(url)
    browser.maximize_window()
    # 获取用户名输入框

    browser.find_element_by_xpath("//div[@class='type-tab']/span[text()='密码登录']").click()

    user = wait.until(EC.presence_of_element_located((By.ID, 'login-username')))
    # 获取密码输入框
    passwd = wait.until(EC.presence_of_element_located((By.ID, 'login-passwd')))
    # 输入用户名
    user.send_keys(username)
    # 输入密码
    passwd.send_keys(password)

    # 获取登录按钮
    login_btn = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'a.btn.btn-login')))
    # 随机延时点击
    time.sleep(random.random() * 3)
    login_btn.click()


# 设置元素可见
def show_element(element):
    browser.execute_script("arguments[0].style=arguments[1]", element, "display: block;")


# 设置元素不可见
def hide_element(element):
    browser.execute_script("arguments[0].style=arguments[1]", element, "display: none;")


# 对某元素截图
def save_pic(obj, name):
    try:
        pic_url = browser.save_screenshot('.\\bilibili.png')
        print("%s:截图成功!" % pic_url)

        # 获取元素位置信息
        left = obj.location['x']
        top = obj.location['y']
        right = left + obj.size['width']
        bottom = top + obj.size['height']

        print('图:' + name)
        print('Left %s' % left)
        print('Top %s' % top)
        print('Right %s' % right)
        print('Bottom %s' % bottom)
        print('')

        im = Image.open('.\\bilibili.png')
        im = im.crop((left, top, right, bottom))  # 元素裁剪
        file_name = 'bili_' + name + '.png'
        im.save(file_name)  # 元素截图
    except BaseException as msg:
        print("%s:截图失败!" % msg)


def cut():
    c_background = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'canvas.geetest_canvas_bg.geetest_absolute')))
    c_slice = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'canvas.geetest_canvas_slice.geetest_absolute')))
    c_full_bg = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'canvas.geetest_canvas_fullbg.geetest_fade.geetest_absolute')))
    hide_element(c_slice)
    save_pic(c_background, 'back')
    show_element(c_slice)
    save_pic(c_slice, 'slice')
    show_element(c_full_bg)
    save_pic(c_full_bg, 'full')


# 判断像素是否相同
def is_pixel_equal(bg_image, fullbg_image, x, y):
    """
    :param bg_image: (Image)缺口图片
    :param fullbg_image: (Image)完整图片
    :param x: (Int)位置x
    :param y: (Int)位置y
    :return: (Boolean)像素是否相同
    """

    # 获取缺口图片的像素点(按照RGB格式)
    bg_pixel = bg_image.load()[x, y]
    # 获取完整图片的像素点(按照RGB格式)
    fullbg_pixel = fullbg_image.load()[x, y]
    # 设置一个判定值,像素值之差超过判定值则认为该像素不相同
    threshold = 20
    # 判断像素的各个颜色之差,abs()用于取绝对值
    if (abs(bg_pixel[0] - fullbg_pixel[0] < threshold) and abs(bg_pixel[1] - fullbg_pixel[1] < threshold) and abs(bg_pixel[2] - fullbg_pixel[2] < threshold)):
        # 如果差值在判断值之内,返回是相同像素
        return True

    else:
        # 如果差值在判断值之外,返回不是相同像素
        return False


# 计算滑块移动距离
def get_distance(bg_image, fullbg_image):
    '''
    :param bg_image: (Image)缺口图片
    :param fullbg_image: (Image)完整图片
    :return: (Int)缺口离滑块的距离
    '''

    # 滑块的初始位置
    distance = 60
    # 遍历像素点横坐标
    for i in range(distance, fullbg_image.size[0]):
        # 遍历像素点纵坐标
        for j in range(fullbg_image.size[1]):
            # 如果不是相同像素
            if not is_pixel_equal(fullbg_image, bg_image, i, j):
                # 返回此时横轴坐标就是滑块需要移动的距离
                return i


# 构造滑动轨迹
def get_trace(distance):
    '''
    :param distance: (Int)缺口离滑块的距离
    :return: (List)移动轨迹
    '''

    # 创建存放轨迹信息的列表
    trace = []
    # 设置加速的距离
    faster_distance = distance * (4 / 5)
    # 设置初始位置、初始速度、时间间隔
    start, v0, t = 0, 0, 0.2
    # 当尚未移动到终点时
    while start < distance:
        # 如果处于加速阶段
        if start < faster_distance:
            # 设置加速度为2
            a = 1.5
        # 如果处于减速阶段
        else:
            # 设置加速度为-3
            a = -3
        # 移动的距离公式
        move = v0 * t + 1 / 2 * a * t * t
        # 此刻速度
        v = v0 + a * t
        # 重置初速度
        v0 = v
        # 重置起点
        start += move
        # 将移动的距离加入轨迹列表
        trace.append(round(move))
    # 返回轨迹信息
    return trace


# 模拟拖动
def move_to_gap(trace):

    # 得到滑块标签
    # slider = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'gt_slider_knob')))
    slider = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div.geetest_slider_button')))
    # 使用click_and_hold()方法悬停在滑块上,perform()方法用于执行
    ActionChains(browser).click_and_hold(slider).perform()
    for x in trace:
        # 使用move_by_offset()方法拖动滑块,perform()方法用于执行
        ActionChains(browser).move_by_offset(xoffset=x, yoffset=0).perform()
    # 模拟人类对准时间
    time.sleep(0.5)
    # 释放滑块

    ActionChains(browser).release().perform()

    try:
        time.sleep(3)
        return browser.find_element_by_xpath('//div[@class="bili-avatar"]')
    except Exception as e:
        print(e)
        return None


def slide():
    # distance = get_distance(Image.open('.\\bili_back.png'), Image.open('.\\bili_full.png')) * 1.29 + 34
    distance = get_distance(Image.open('.\\bili_back.png'), Image.open('.\\bili_full.png')) + random.choice(range(-10, -3))
    print('计算偏移量为:%s Px' % distance)
    # 计算移动轨迹
    trace = get_trace(distance)
    # 移动滑块
    result = move_to_gap(trace)
    time.sleep(3)
    if not result:
        return None


while True:
    login()
    cut()
    result = slide()
    if result:
        break


相关文章

网友评论

      本文标题:bilibili滑块

      本文链接:https://www.haomeiwen.com/subject/anromltx.html