python模拟⽹站登录——滑块验证码的识别
普通滑动验证
import time
from selenium import webdriver
from selenium.webdriver import ActionChains
# 新建selenium浏览器对象,后⾯是下载后本地路径
browser = webdriver.Firefox()
# ⽹站登陆页⾯
url = 'aotai/login.aspx'
# 浏览器访问登录页⾯
<(url)
browser.maximize_window()
browser.implicitly_wait(5)
draggable = browser.find_element_by_id('nc_1_n1z')
# 滚动指定元素位置
time.sleep(2)
ActionChains(browser).click_and_hold(draggable).perform()
# 拖动
ActionChains(browser).move_by_offset(xoffset=247, yoffset=0).perform()
ActionChains(browser).release().perform()
拼图滑动验证
我们以很多⽹站使⽤的都是类似的⽅式。因为验证码及拼图都有明显明亮的边界,图⽚辨识度⽐较⾼。所以我们尝试先⽤cv2的边缘检测识别出边界,然后进⾏模糊匹配,匹配出拼图在验证码图⽚的位置。
边缘检测
cv2模块提供了多种边缘检测算⼦,包括Sobel、Scharr、Laplacian、prewitt、Canny或Marr—Hildreth等,每种算⼦得出的结果不同。这⾥我们⽤Canny算⼦,测试了很多算⼦,这种效果最好。
我们通过⼀个程序调整⼀下canny算⼦的阈值,使得输出图⽚只包含拼图轮廓。
import cv2
lowThreshold = 0
maxThreshold = 100
# 最⼩阈值范围 0 ~ 500
# 最⼤阈值范围 100 ~ 1000
def canny_low_threshold(intial):
blur = cv2.GaussianBlur(img, (3, 3), 0)
canny = cv2.Canny(blur, intial, maxThreshold)
cv2.imshow('canny', canny)
def canny_max_threshold(intial):
blur = cv2.GaussianBlur(img, (3, 3), 0)
canny = cv2.Canny(blur, lowThreshold, intial)
cv2.imshow('canny', canny)
# 参数0以灰度⽅式读取
img = cv2.imread('vcode.png', 0)
cv2.namedWindow('canny', cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO)
canny_low_threshold(0)
# esc键退出
if cv2.waitKey(0) == 27:
cv2.destroyAllWindows()
测试了若⼲个图⽚发现最⼩阈值100、最⼤阈值500输出结果⽐较理想。
拼图匹配
我们⽤cv2的matchTemplate⽅法进⾏模糊匹配,匹配⽅法⽤CV_TM_CCOEFF_NORMED归⼀化相关系数匹配。
【1】平⽅差匹配 method=CV_TM_SQDIFF square dirrerence(error)
这类⽅法利⽤平⽅差来进⾏匹配,最好匹配为0.匹配越差,匹配值越⼤.
【2】标准平⽅差匹配 method=CV_TM_SQDIFF_NORMED standard square dirrerence(error)
【3】相关匹配 method=CV_TM_CCORR
这类⽅法采⽤模板和图像间的乘法操作,所以较⼤的数表⽰匹配程度较⾼,0标识最坏的匹配效果.
【4】标准相关匹配 method=CV_TM_CCORR_NORMED
【5】相关匹配 method=CV_TM_CCOEFF
这类⽅法将模版对其均值的相对值与图像对其均值的相关值进⾏匹配,1表⽰完美匹配,
-1表⽰糟糕的匹配,0表⽰没有任何相关性(随机序列).
【6】标准相关匹配 method=CV_TM_CCOEFF_NORMED
canndy_test.py:
import cv2
import numpy as np
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 = size(sou_img1, (350, 200))
target_temp = pyMakeBorder(target_temp, 5, 5, 5, 5, cv2.BORDER_CONSTANT, value=[255, 255, 255])
template_temp = size(sou_img2, (200, 200))
template_temp = pyMakeBorder(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)
# 归⼀化
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
# 匹配后结果画圈
target_temp_n = size(target, (350, 200))登录页面背景图
target_temp_n = pyMakeBorder(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('stack'+str(max_loc), imstack)
cv2.waitKey(0)
cv2.destroyAllWindows()
matchImg('vcode_data/out_'+str(1)+'.png','vcode_data/in_'+str(1)+'.png')
我们测试⼏组数据,发现准确率拿来玩玩尚可。max_loc就是匹配出来的位置信息,我们只需要按照位置进⾏拖动即可。完整程序
完整流程
1.实例化浏览器
2.点击登陆,弹出滑动验证框
3.分别新建标签页打开背景图及拼图
4.全屏截图后按照尺⼨裁剪
5.模糊匹配两张图⽚,获取匹配结果位置信息
6.将位置信息转为页⾯上的位移距离
7.拖动滑块到指定位置
import time
import cv2
import canndy_test
from selenium import webdriver
from selenium.webdriver import ActionChains
# 新建selenium浏览器对象,后⾯是下载后本地路径
browser = webdriver.Firefox()
# ⽹站登陆页⾯
url = '/login'
# 浏览器访问登录页⾯
<(url)
handle = browser.current_window_handle
# 等待3s⽤于加载脚本⽂件
browser.implicitly_wait(3)
# 点击登陆按钮,弹出滑动验证码
btn = browser.find_element_by_class_name('login_btn1')
btn.click()
# 获取iframe元素,切到iframe
frame = browser.find_element_by_id('tcaptcha_iframe')
browser.switch_to.frame(frame)
time.sleep(1)
# 获取背景图src
targetUrl = browser.find_element_by_id('slideBg').get_attribute('src')
# 获取拼图src
tempUrl = browser.find_element_by_id('slideBlock').get_attribute('src')
# 新建标签页
# 切换到新标签页
browser.switch_to.window(browser.window_handles[1])
# 访问背景图src
<(targetUrl)
time.sleep(3)
# 截图
browser.save_screenshot('temp_target.png')
w = 680
h = 390
img = cv2.imread('temp_target.png')
size = img.shape
top = int((size[0] - h) / 2)
height = int(h + ((size[0] - h) / 2))
left = int((size[1] - w) / 2)
width = int(w + ((size[1] - w) / 2))
cropped = img[top:height, left:width]
# 裁剪尺⼨
cv2.imwrite('temp_target_crop.png', cropped)
# 新建标签页
browser.switch_to.window(browser.window_handles[2])
<(tempUrl)
time.sleep(3)
browser.save_screenshot('temp_temp.png')
w = 136
h = 136
img = cv2.imread('temp_temp.png')
size = img.shape
top = int((size[0] - h) / 2)
height = int(h + ((size[0] - h) / 2))
left = int((size[1] - w) / 2)
width = int(w + ((size[1] - w) / 2))
cropped = img[top:height, left:width]
cv2.imwrite('temp_temp_crop.png', cropped)
browser.switch_to.window(handle)
# 模糊匹配两张图⽚
move = canndy_test.matchImg('temp_target_crop.png', 'temp_temp_crop.png') # 计算出拖动距离
distance = int(move / 2 - 27.5) + 2
draggable = browser.find_element_by_id('tcaptcha_drag_thumb') ActionChains(browser).click_and_hold(draggable).perform()
# 拖动
ActionChains(browser).move_by_offset(xoffset=distance, yoffset=0).perform()
ActionChains(browser).release().perform()
time.sleep(10)
tips:可能会存在第⼀次不成功的情况,虽然拖动到了指定位置但是提⽰⽹络有问题、拼图丢失。可以进⾏循环迭代直到拼成功为⽌。通过判断iframe中id为slideBg的元素是否存在,如果成功了则不存在,失败了会刷新拼图让你重新拖动。
if(isEleExist(browser,'slideBg')):
# retry
else:
return
def isEleExist(browser,id):
try:
browser.find_element_by_id(id)
return True
except:
return False
以上就是python 模拟⽹站登录——滑块验证码的识别的详细内容,更多关于python 模拟⽹站登录的资料请关注其它相关⽂章!