python模擬嗶哩嗶哩滑塊登入驗證的實現

前言

本文的文字及圖片來源於網絡,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。

作者:卡卡叮

PS:如有需要Python學習資料的小夥伴可以加點擊下方鏈接自行獲取http://t.cn/A6Zvjdun

這篇文章主要介紹了python模擬嗶哩嗶哩滑塊登入驗證的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨着小編來一起學習學習吧

準備工具

  • 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邊緣檢測算法進行圖像識別匹配。

Canny邊緣檢測算法參考鏈接:https://www.jb51.net/article/185336.htm

具體使用的是Canny的matchTemplate方法進行模糊匹配,匹配方法用CV_TM_CCOEFF_NORMED歸一化相關係數匹配。得出的max_loc就是匹配出來的位置信息。從而達到位置的距離。

難點

由於圖像採用放大的效果匹配出的距離偏大,難以把真實距離,並存在誤差。

由於嗶哩嗶哩滑塊驗證進一步採取做了措施,如果滑動時間過短,會導致驗證登入失敗。所以我這裏採用變速的方法,在相同時間內滑動不同的距離。

誤差的存在是必不可少的,有時會導致驗證失敗,這都是正常現象。

流程

1.實例化谷歌瀏覽器 ,並打開嗶哩嗶哩登入頁面。

2.點擊登陸,彈出滑動驗證框。

3.全屏截圖、後按照尺寸裁剪各兩張。

5.模糊匹配兩張圖片,從而獲取匹配結果以及位置信息 。

6.將位置信息與頁面上的位移距離轉化,並儘可能少的減少誤差 。

7.變速的拖動滑塊到指定位置,從而達到模擬登入。

效果圖

在這裏插入圖片描述

代碼實例

庫安裝好後,然後填寫配置區域後即可運行。

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+2
 elif(x1<0 and x2>=0):
  return x2+2
 else:
  return x1+2

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()

有能力的可以研究一下思路,然後寫出更好的解決辦法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章