之前发了一个国航的滑块模拟操作,没有计算滑块到缺口的位置。 本篇则是用opencv selenium来对QQ邮箱的滑块进行模拟测试。
QQ邮箱链接: https://mail.qq.com/
QQ邮箱这个登录机制,需要我们输入一个错误的账号或密码会有机会弹出滑块验证码,所以我下面就一直用错误的账号进行测试。 其实部分账号,或者说异地登录的QQ账号也都需要滑动解锁验证码才能继续登录。所以这个测试以后可能用的上。
首先是用selenium登录:
访问过来以后,看到的是一个如下图所示的页面。我们需要点击账号密码登录才能进行我们的模拟操作。
刚开始我直接用selenium获取ID点击账号登录,发现没什么作用。 后来仔细一看这是一个iframe框,我们直接是不能点击到的。 要进行frame切换。 selenium中有这样的操作:
代码语言:javascript复制driver.switch_to.frame("login_frame") # login_frame是该登录窗口iframe的id
这样才能点击到。以供我们接下来的操作。
代码语言:javascript复制 driver.get('https://mail.qq.com')
time.sleep(2)
driver.switch_to.frame("login_frame") # 切换frame。login_frame是该登录窗口id
time.sleep(1)
driver.find_element_by_id('switcher_plogin').click() #点击账号密码登录
time.sleep(1)
username = '1234567{}@qq.com'.format(random.randint(0,99)) #随机获取一个账号
driver.find_element_by_id("u").send_keys(username) #输入账号
time.sleep(1)
driver.find_element_by_id("p").send_keys('wwwwwwwwwwwww') #输入一个密码
time.sleep(1)
driver.find_element_by_id("login_button").click() #点击登录
time.sleep(1)
如果出现了这么个玩意,没有出现滑块。那你就再试一次=。=
正常情况出现滑块后:
开始进行缺口位置识别:
我这里使用的方法,是通过selenium中的xpath把图片的src获取到,然后下载下来保存到本地。再通过opencv来进行图像缺口检测。
那我们先获取两个图片(滑块和验证图)的src:
代码语言:javascript复制 src_big = driver.find_element_by_xpath('//div[@id="slideBgWrap"]/img').get_attribute('src')
代码语言:javascript复制 src_small = driver.find_element_by_xpath('//div[@id="slideBlockWrap"]/img').get_attribute('src')
然后保存到本地:
代码语言:javascript复制 img_big = requests.get(src_big).content
img_small = requests.get(src_small).content
with open('yanzhengtu.jpg','wb') as f:
f.write(img_big)
with open('huakuai.png','wb') as f:
f.write(img_small)
开始识别图片缺口位置: 写一个shibie函数:
代码语言:javascript复制def shibie():
otemp = 'huakuai.png' #滑块
oblk = 'yanzhengtu.jpg' # 验证图
target = cv2.imread(otemp, 0) #读入图片
template = cv2.imread(oblk, 0)
w, h = target.shape[::-1] #获取数组转置后的结构
temp = 'temp.jpg'
targ = 'targ.jpg'
cv2.imwrite(temp, template)
cv2.imwrite(targ, target)
target = cv2.imread(targ)
target = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY) #图像颜色空间转换
target = abs(255 - target)
cv2.imwrite(targ, target)
target = cv2.imread(targ)
template = cv2.imread(temp)
result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED) #进行图像模板匹配
x, y = np.unravel_index(result.argmax(), result.shape) #获取一个/组int类型的索引值在一个多维数组中的位置
# 展示圈出来的区域
cv2.rectangle(template, (y, x), (y w, x h), (7, 249, 151), 3) #通过对角线画矩形
# print(y)
# show(template)
return y
然后调用我们写好的识别函数: 返回保存在本地的图片中0左标到缺口位置的距离:y
我们本地图片的宽是 680 像素 而QQ邮箱给的验证图的宽为 280 像素
那我们移动的距离是: y = y/(680/280) 但是在浏览器上面显示的滑块起始位置不是为0的。
所以我们移动的距离应该是: y = (y 22.5)/(680/280) k 当然可能存在有些许误差k,需要我们再观察并补充。
我们就可以使用selenium中的ActionChains来进行鼠标移动操作。
代码语言:javascript复制huakuai = driver.find_element_by_id('tcaptcha_drag_thumb')
action = ActionChains(driver)
action.click_and_hold(huakuai).perform()
y = (y 20)/(680/280)-27
try:
action.move_by_offset(y,0).perform()
time.sleep(0.5)
action.release(on_element=huakuai).perform() #松开鼠标左键,完成操作
time.sleep(1)
except:
pass
测试结果:
因为这里发不了视频。我用gif图来演示下:
图质量太烂了、不过不影响看结果。现在已经能识别并正确拖动到位置了。
完整代码:
代码语言:javascript复制from selenium import webdriver
import cv2,numpy as np,random,requests,time
from selenium.webdriver import ActionChains
'''识别缺口位置、计算偏移值'''
def shibie():
otemp = 'huakuai.png' #滑块
oblk = 'yanzhengtu.jpg' # 验证图
target = cv2.imread(otemp, 0)
template = cv2.imread(oblk, 0)
w, h = target.shape[::-1]
temp = 'temp.jpg'
targ = 'targ.jpg'
cv2.imwrite(temp, template)
cv2.imwrite(targ, target)
target = cv2.imread(targ)
target = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY) #图像颜色空间转换
target = abs(255 - target)
cv2.imwrite(targ, target)
target = cv2.imread(targ)
template = cv2.imread(temp)
result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)#进行图像模板匹配
x, y = np.unravel_index(result.argmax(), result.shape) #获取一个/组int类型的索引值在一个多维数组中的位置
# 展示圈出来的区域
cv2.rectangle(template, (y, x), (y w, x h), (7, 249, 151), 3) #通过对角线画矩形
# print(y)
# show(template)
return y
'''Selenium模拟登陆 获取滑块'''
def main():
driver = webdriver.Chrome(executable_path=r'C:UserslenovoDesktopchromedriver_win32chromedriver.exe')
driver.get('https://mail.qq.com')
# driver.find_element_by_xpath('//div[@calss="bottom hide"]/a[@class="link"]').click()
time.sleep(2)
driver.switch_to.frame("login_frame") # 切换frame。login_frame是该登录窗口iframe的id
time.sleep(1)
driver.find_element_by_id('switcher_plogin').click()
time.sleep(1)
username = '1234567{}@qq.com'.format(random.randint(0,99))
driver.find_element_by_id("u").send_keys(username)
time.sleep(1)
driver.find_element_by_id("p").send_keys('wwwwwwwwwwwww')
time.sleep(1)
driver.find_element_by_id("login_button").click()
time.sleep(1)
try:
driver.switch_to.frame("tcaptcha_iframe")
time.sleep(1)
if driver.find_element_by_id('slideBgWrap'):
time.sleep(0.5)
src_big = driver.find_element_by_xpath('//div[@id="slideBgWrap"]/img').get_attribute('src')
src_small = driver.find_element_by_xpath('//div[@id="slideBlockWrap"]/img').get_attribute('src')
img_big = requests.get(src_big).content
img_small = requests.get(src_small).content
with open('yanzhengtu.jpg','wb') as f:
f.write(img_big)
with open('huakuai.png','wb') as f:
f.write(img_small)
time.sleep(3)
y = shibie()
time.sleep(1)
# print(y)
huakuai = driver.find_element_by_id('tcaptcha_drag_thumb')
action = ActionChains(driver)
action.click_and_hold(huakuai).perform()
y = (y 20)/(680/280)-27
try:
action.move_by_offset(y,0).perform()
time.sleep(0.5)
action.release(on_element=huakuai).perform() #松开鼠标左键,完成操作
time.sleep(1)
except:
pass
except:
time.sleep(1)
driver.close()
main()
main()