利用selenium庫自動執行滑動驗證碼模擬登陸
阿新 • • 發佈:2020-01-05
破解流程
#1、輸入賬號、密碼,然後點選登陸
#2、點選按鈕,彈出沒有缺口的圖
#3、針對沒有缺口的圖片進行截圖
#4、點選滑動按鈕,彈出有缺口的圖
#5、針對有缺口的圖片進行截圖
#6、對比兩張圖片,找出缺口,即滑動的位移
#7、按照人的行為行為習慣,把總位移切成一段段小的位移
#8、按照位移移動
#9、完成登入
模擬登陸案例一:
from selenium import webdriver
from selenium.webdriver import ActionChains
from PIL import Image
import time
import random
option = webdriver.ChromeOptions()
# 新增啟動引數 (add_argument)
option.add_argument('disable-infobars') # 禁用瀏覽器正在被自動化程式控制的提示
driver = webdriver.Chrome(chrome_options=option)
def get_snap(driver):
# selenium自帶的截圖網頁全屏圖片
driver.save_screenshot('snap.png')
# 拿到驗證圖片所在的標籤,方便確認位置
img = driver.find_element_by_class_name('geetest_canvas_img')
# location 代表該圖片在整個頁面所在的位置(x, y),x:距離左邊多長,y:距離上面多長
# print(img.location)
# size 代表該圖片的大小
# print(img.size)
left = img.location.get('x')
upper = img.location.get('y')
right = left + img.size.get('width')
lower = upper + img.size.get('height')
# 拿到圖片四個邊的位置,就可以進行裁剪圖片了
# print(left, upper, right, lower)
img_obj = Image.open('snap.png')
# 對螢幕進行裁剪,獲取滑動驗證碼圖片
image = img_obj.crop((left, upper, right, lower))
# image.show()
return image
# 獲取完整圖片
def get_img1(driver):
time.sleep(0.2)
js_code = """
var x = document.getElementsByClassName('geetest_canvas_fullbg')[0].style.display="block";
console.log(x)
"""
# 執行js程式碼
driver.execute_script(js_code)
time.sleep(1)
# 擷取圖片
img_obj = get_snap(driver)
return img_obj
# 獲取有缺口的圖片
def get_img2(driver):
time.sleep(0.2)
js_code = """
var x = document.getElementsByClassName('geetest_canvas_fullbg')[0].style.display="none";
console.log(x)
"""
# 執行js程式碼
driver.execute_script(js_code)
time.sleep(1)
# 擷取圖片
img_obj = get_snap(driver)
return img_obj
def get_distance(img1, img2):
# 初始值
start = 60
# 模組色差
color_num = 60
for x in range(start, img1.size[0]):
for y in range(img1.size[1]):
rgb1 = img1.load()[x, y]
rgb2 = img2.load()[x, y]
# abs 獲取絕對值
r = abs(rgb1[0] - rgb2[0])
g = abs(rgb1[1] - rgb2[1])
b = abs(rgb1[2] - rgb2[2])
if not (r < color_num and g < color_num and b < color_num):
return x - 7 # 誤差值大概為7
def get_stacks(distance):
distance += 20
'''
拿到移動軌跡,模仿人的滑動行為,先勻加速後勻減速
變速運動基本公式:
① v=v0+at 勻加速\減速執行
② s=v0t+½at² 位移
③ v²-v0²=2as
'''
# 初速度
v0 = 0
# 加減速度列表
a_list = [50, 65, 80]
# 時間
t = 0.2
# 初始位置
s = 0
# 向前滑動軌跡
forward_stacks = []
mid = distance * 3 / 5
while s < distance:
if s < mid:
a = a_list[random.randint(0, 2)]
else:
a = -a_list[random.randint(0, 2)]
v = v0
stack = v * t + 0.5 * a * (t ** 2)
# 每次拿到的位移
stack = round(stack)
s += stack
v0 = v + a * t
forward_stacks.append(stack)
# 往後返回20距離,因為之前distance向前多走了20
back_stacks = [-5, -5, -5, -5,]
return {'forward_stacks': forward_stacks, 'back_stacks': back_stacks}
if __name__ == '__main__':
try:
driver.get('https://account.cnblogs.com/signin')
# 隱式等待
driver.implicitly_wait(5)
# 步驟一:找到輸入賬戶框
user_input = driver.find_element_by_id('LoginName')
# 步驟二:找到輸入密碼框
pwd_input = driver.find_element_by_id('Password')
user_input.send_keys('[email protected]')
time.sleep(1)
pwd_input.send_keys('123456')
# 步驟三:找到確認登入按鈕,並點選
login_btn = driver.find_element_by_id('submitBtn')
time.sleep(1)
login_btn.click()
time.sleep(3)
# 步驟四: 拿到沒有缺口的圖片並擷取
img1 = get_img1(driver)
# 步驟五: 拿到有缺口的圖片並擷取
img2 = get_img2(driver)
# 步驟六: 對比兩張圖片,獲取滑動距離
distance = get_distance(img1, img2)
# 步驟七: 模擬人為滑動軌跡
stacks = get_stacks(distance)
# 步驟八: 根據滑動軌跡進行滑動
forward_stacks = stacks['forward_stacks']
back_stacks = stacks['back_stacks']
# 步驟九:找到滑動按鈕,並點選與hole住
slider_btn = driver.find_element_by_class_name('geetest_slider_button')
time.sleep(0.2)
ActionChains(driver).click_and_hold(slider_btn).perform()
time.sleep(0.2)
# 步驟十:開始迴圈向前滑動
for forward_stack in forward_stacks:
ActionChains(driver).move_by_offset(xoffset=forward_stack, yoffset=0).perform()
time.sleep(0.1)
# 步驟十一:開始迴圈向後滑動20
for back_stack in back_stacks:
ActionChains(driver).move_by_offset(xoffset=back_stack, yoffset=0).perform()
time.sleep(0.1)
time.sleep(0.2)
# 步驟十二:為了防止極驗檢測到,再將滑塊前後小浮動5位置,再釋放
ActionChains(driver).move_by_offset(xoffset=5, yoffset=0).perform()
time.sleep(0.2)
ActionChains(driver).move_by_offset(xoffset=-5, yoffset=0).perform()
# 可能會出現識別不了,說圖片被怪物吃了,上面模擬人的行為都不要了,拿到距離後,直接執行下面程式碼,一步滑到缺口處即可
# ActionChains(driver).move_by_offset(xoffset=distance, yoffset=0).perform()
ActionChains(driver).release().perform()
time.sleep(50)
finally:
driver.close()