吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3365|回复: 8
收起左侧

[Python 原创] python模拟哔哩哔哩滑块登入验证

  [复制链接]
Airey 发表于 2020-4-18 13:26
本帖最后由 Airey 于 2020-4-29 16:22 编辑

准备工具
  • pip3 install PIL
  • pip3 install opencv-python
  • pip3 install numpy
  • 谷歌驱动


建议指定清华源下载速度会更快点
使用方法 : pip3 install opencv-python -i  https://pypi.tuna.tsinghua.edu.cn/simple/opencv-python/

根据自己的谷歌浏览器的版本来下载谷歌驱动哦

谷歌驱动下载链接 :http://npm.taobao.org/mirrors/chromedriver/




前言
本篇文章采用的是cv2的Canny边缘检测算法进行图像识别匹配。

CV2参考文档:https://www.w3cschool.cn/opencv/


具体使用的是Canny的matchTemplate方法进行模糊匹配,匹配方法用CV_TM_CCOEFF_NORMED归一化相关系数匹配。得出的max_loc就是匹配出来的位置信息。从而达到位置的距离。

难点
由于图像采用放大的效果匹配出的距离偏大,难以把真实距离,并存在误差。
由于哔哩哔哩滑块验证进一步采取做了措施,如果滑动时间过短,会导致验证登入失败。所以我这里采用变速的方法,在相同时间内滑动不同的距离。
误差的存在是必不可少的,有时会导致验证失败,这都是正常现象。

流程
1.实例化谷歌浏览器 ,并打开哔哩哔哩登入页面。
2.点击登陆,弹出滑动验证框。
3.全屏截图、后按照尺寸裁剪各两张。
5.模糊匹配两张图片,从而获取匹配结果以及位置信息 。
6.将位置信息与页面上的位移距离转化,并尽可能少的减少误差 。
7.变速的拖动滑块到指定位置,从而达到模拟登入。

效果图
1.png

代码实例
库安装好后,然后填写配置区域后即可运行。


[Python] 纯文本查看 复制代码
from PIL import Image
from time import sleep
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import cv2
import numpy as np
import math
############ 配置区域 #########

zh=''    #账号
pwd=''  #密码
    # chromedriver的路径
chromedriver_path = "C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe"

#######  end  #########

options = webdriver.ChromeOptions()
options.add_argument('--no-sandbox')
options.add_argument('--window-size=1020,720')
# options.add_argument('--start-maximized')  # 浏览器窗口最大化
options.add_argument('--disable-gpu')
options.add_argument('--hide-scrollbars')
options.add_argument('test-type')
options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors",
                                                    "enable-automation"])  # 设置为开发者模式
driver = webdriver.Chrome(options=options, executable_path=chromedriver_path)
driver.get('https://passport.bilibili.com/login')

# 登入
def login():
    driver.find_element_by_id("login-username").send_keys(zh)
    driver.find_element_by_id("login-passwd").send_keys(pwd)
    driver.find_element_by_css_selector("#geetest-wrap > div > div.btn-box > a.btn.btn-login").click()
    print("点击登入")

# 整个图,跟滑块整个图
def screen(screenXpath):
    img = WebDriverWait(driver, 20).until(
        EC.visibility_of_element_located((By.XPATH, screenXpath))
    )
    driver.save_screenshot("allscreen.png")  # 对整个浏览器页面进行截图
    left = img.location['x']+160 #往右
    top = img.location['y']+60 # 往下
    right = img.location['x'] + img.size['width']+230  # 往左
    bottom = img.location['y'] + img.size['height']+110  # 往上
    im = Image.open('allscreen.png')
    im = im.crop((left, top, right, bottom))  # 对浏览器截图进行裁剪
    im.save('1.png')
    print("截图完成1")
    screen_two(screenXpath)
    screen_th(screenXpath)
    matchImg('3.png','2.png')

# 滑块部分图
def screen_two(screenXpath):
    img = WebDriverWait(driver, 20).until(
        EC.visibility_of_element_located((By.XPATH, screenXpath))
    )
    left = img.location['x'] + 160
    top = img.location['y'] + 80
    right = img.location['x'] + img.size['width']-30
    bottom = img.location['y'] + img.size['height'] + 90
    im = Image.open('allscreen.png')
    im = im.crop((left, top, right, bottom))  # 对浏览器截图进行裁剪
    im.save('2.png')
    print("截图完成2")

# 滑块剩余部分图
def screen_th(screenXpath):
    img = WebDriverWait(driver, 20).until(
        EC.visibility_of_element_located((By.XPATH, screenXpath))
    )
    left = img.location['x'] + 220
    top = img.location['y'] + 60
    right = img.location['x'] + img.size['width']+230
    bottom = img.location['y'] + img.size['height'] +110
    im = Image.open('allscreen.png')
    im = im.crop((left, top, right, bottom))  # 对浏览器截图进行裁剪
    im.save('3.png')
    print("截图完成3")

#图形匹配
def matchImg(imgPath1,imgPath2):
    imgs = []
    #展示
    sou_img1= cv2.imread(imgPath1)
    sou_img2 = cv2.imread(imgPath2)
    # 最小阈值100,最大阈值500
    img1 = cv2.imread(imgPath1, 0)
    blur1 = cv2.GaussianBlur(img1, (3, 3), 0)
    canny1 = cv2.Canny(blur1, 100, 500)
    cv2.imwrite('temp1.png', canny1)
    img2 = cv2.imread(imgPath2, 0)
    blur2 = cv2.GaussianBlur(img2, (3, 3), 0)
    canny2 = cv2.Canny(blur2, 100, 500)
    cv2.imwrite('temp2.png', canny2)
    target = cv2.imread('temp1.png')
    template = cv2.imread('temp2.png')
    # 调整大小
    target_temp = cv2.resize(sou_img1, (350, 200))
    target_temp = cv2.copyMakeBorder(target_temp, 5, 5, 5, 5, cv2.BORDER_CONSTANT, value=[255, 255, 255])
    template_temp = cv2.resize(sou_img2, (200, 200))
    template_temp = cv2.copyMakeBorder(template_temp, 5, 5, 5, 5, cv2.BORDER_CONSTANT, value=[255, 255, 255])
    imgs.append(target_temp)
    imgs.append(template_temp)
    theight, twidth = template.shape[:2]
    # 匹配跟拼图
    result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)
    cv2.normalize( result, result, 0, 1, cv2.NORM_MINMAX, -1 )
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    # 画圈
    cv2.rectangle(target,max_loc,(max_loc[0]+twidth,max_loc[1]+theight),(0,0,255),2)
    target_temp_n = cv2.resize(target, (350, 200))
    target_temp_n = cv2.copyMakeBorder(target_temp_n, 5, 5, 5, 5, cv2.BORDER_CONSTANT, value=[255, 255, 255])
    imgs.append(target_temp_n)
    imstack = np.hstack(imgs)

    cv2.imshow('windows'+str(max_loc), imstack)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    # 计算距离
    print(max_loc)
    dis=str(max_loc).split()[0].split('(')[1].split(',')[0]
    x_dis=int(dis)+135
    t(x_dis)


#拖动滑块
def t(distances):
    draggable = driver.find_element_by_css_selector('div.geetest_slider.geetest_ready > div.geetest_slider_button')
    ActionChains(driver).click_and_hold(draggable).perform() #抓住
    print(driver.title)
    num=getNum(distances)
    sleep(3)
    for distance in range(1,int(num)):
        print('移动的步数: ',distance)
        ActionChains(driver).move_by_offset(xoffset=distance, yoffset=0).perform()
        sleep(0.25)
    ActionChains(driver).release().perform() #松开


# 计算步数
def getNum(distances):
    p = 1+4*distances
    x1 = (-1 + math.sqrt(p)) / 2
    x2 = (-1 - math.sqrt(p)) / 2
    print(x1,x2)
    if x1>=0 and x2<0:
        return x1+1
    elif(x1<0 and x2>=0):
        return x2+1
    else:
        return x1+1

def main():
    login()
    sleep(5)
    screenXpath = '/html/body/div[2]/div[2]/div[6]/div/div[1]/div[1]/div/a/div[1]/div/canvas[2]'
    screen(screenXpath)
    sleep(5)


if __name__ == '__main__':
    main()




有能力的朋友可以研究一下思路,可以参考文档学习,然后写出更好的解决办法。

最后请大佬勿喷。编程不易,麻烦评个分,给个热心值,都是给我最大的鼓励和动力~,谢谢

免费评分

参与人数 9威望 +1 吾爱币 +27 热心值 +8 收起 理由
精灵与法师 + 1 我很赞同!
科目呵 + 1 + 1 热心回复!
byho + 1 + 1 谢谢@Thanks!
ghy_37854 + 1 + 1 谢谢@Thanks!
辣丝丝小白菜 + 1 + 1 这个就厉害了,如果能分析js,直接用请求登录就好了。
苏紫方璇 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
夕临垓下 + 1 + 1 我很赞同!
HA_Linux + 1 谢谢@Thanks!
yuze0804007 + 1 + 1 厉害了,我的哥

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

pantherTL 发表于 2020-4-18 13:43
pythone用的越来越多了,感谢分享!
啸岳 发表于 2020-4-18 14:17
夕临垓下 发表于 2020-4-18 14:44
我叫郭靖啊 发表于 2020-4-20 16:40
成功率有多少
我叫郭靖啊 发表于 2020-4-20 16:54
你这没有模拟先加速后减速的过程吧,以极验现在的反爬程度,即使模拟先加速后减速成功率估计也是0
qqww3815 发表于 2020-4-28 01:48
轨迹太复杂又浪费资源
niu645509965 发表于 2020-8-18 16:13
下载下来试试看
18634200556 发表于 2020-8-18 16:31
厉害了我的大佬
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-26 01:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表