先貼代碼
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/3/12 11:39
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
from lxml.html import etree
from PIL import Image
from time import sleep
import re, requests
from urllib.request import urlretrieve
from bs4 import BeautifulSoup
class B_login(object):
def __init__(self): # 初始化一些信息
self.left = 60 # 定義一個左邊的起點(diǎn) 缺口一般離圖片左側(cè)有一定的距離 有一個滑塊
self.url = 'https://passport.bilibili.com/login'
self.driver = webdriver.Chrome('chromedriver')
self.driver.maximize_window()
self.wait = WebDriverWait(self.driver, 20) # 設(shè)置等待
self.username = "用戶名"
self.password = "密碼"
def input_name_password(self): # 輸入用戶名和密碼
self.driver.get(self.url)
self.user = self.wait.until(EC.presence_of_element_located((By.ID, 'login-username')))
self.passwd = self.wait.until(EC.presence_of_element_located((By.ID, 'login-passwd')))
self.user.send_keys(self.username)
self.passwd.send_keys(self.password)
def click_login_button(self): # 點(diǎn)擊登錄按鈕,出現(xiàn)驗(yàn)證碼圖片
login_button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'btn-login')))
login_button.click()
sleep(1)
self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_refresh_1'))).click()
sleep(1)
#以下是獲取圖片驗(yàn)證碼計(jì)算滑塊移動距離代碼
def get_geetest_image(self): # 通過截圖的方式獲取兩張驗(yàn)證碼圖片堂飞,一張帶缺口一張不帶缺口
# print(self.driver.page_source)
#獲取帶缺口的圖片1 geetest_canvas_bg
gapimg = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_bg')))
# sleep(2)
gapimg.screenshot(r'./captcha1.png') # 將class為geetest_canvas_bg的區(qū)域截屏保存
# 通過js代碼修改標(biāo)簽樣式 顯示圖片2并截圖 geetest_canvas_fullbg
js = 'var change = document.getElementsByClassName("geetest_canvas_fullbg");change[0].style = "display:block;"'
self.driver.execute_script(js)
# sleep(2)
fullimg = self.wait.until(
EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_fullbg')))
fullimg.screenshot(r'./captcha2.png') # 將class為geetest_canvas_fullbg的區(qū)域截屏保存
def is_similar(self, image1, image2, x, y): #判斷兩張圖片良拼,各個位置的像素是否相同
'''判斷兩張圖片 各個位置的像素是否相同
#image1:帶缺口的圖片
:param image2: 不帶缺口的圖片
:param x: 位置x
:param y: 位置y
:return: (x,y)位置的像素是否相同
'''
# 獲取兩張圖片指定位置的像素點(diǎn)
pixel1 = image1.load()[x, y]
pixel2 = image2.load()[x, y]
# 設(shè)置一個閾值 允許有誤差
threshold = 60
# 彩色圖 每個位置的像素點(diǎn)有三個通道
if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(
pixel1[2] - pixel2[2]) < threshold:
return True
else:
return False
def get_diff_location(self): # 獲取缺口圖起點(diǎn),找到缺口的左側(cè)邊界 在x方向上的位置
captcha1 = Image.open('captcha1.png')
captcha2 = Image.open('captcha2.png')
for x in range(self.left, captcha1.size[0]): # 從左到右 x方向
for y in range(captcha1.size[1]): # 從上到下 y方向
if not self.is_similar(captcha1, captcha2, x, y):
return x # 找到缺口的左側(cè)邊界 在x方向上的位置
def move_slider(self, track):# 移動滑塊完成登錄
slider = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.geetest_slider_button')))
ActionChains(self.driver).click_and_hold(slider).perform()
sleep(0.5)
ActionChains(self.driver).move_by_offset(xoffset=0.70*track, yoffset=0).perform()
sleep(0.5)
ActionChains(self.driver).move_by_offset(xoffset=0.30*track, yoffset=0).perform()
sleep(0.5) #0.70和0.30可以是其他隨意數(shù)值,也可以生成隨機(jī)數(shù)
ActionChains(self.driver).release().perform() # 松開鼠標(biāo)
def main(self):
self.input_name_password()#輸入用戶名密碼
self.click_login_button()#點(diǎn)擊登錄
self.get_geetest_image()# 通過截圖的方式獲取兩張驗(yàn)證碼圖片,一張帶缺口一張不帶缺口
gap = self.get_diff_location() # 計(jì)算缺口左起點(diǎn)位置 , 獲取缺口圖起點(diǎn)婿失,找到缺口的左側(cè)邊界 在x方向上的位置
gap = gap - 8 # 減去滑塊左側(cè)距離圖片左側(cè)在x方向上的距離 即為滑塊實(shí)際要移動的距離
self.move_slider(gap)# 根據(jù)軌跡移動滑塊完成登錄
if __name__ == "__main__":
bilibiliSlider = B_login()
bilibiliSlider.main()
但是沒用參考鏈接里的滑塊軌跡移動啄寡,因?yàn)閯蛩龠\(yùn)動會被檢測出來