本文参考https://www.cnblogs.com/chenjy1225/p/11810895.html,但是经过我的实际测试,该文所使用的代码已经不能顺利通过原作者所测试的网站(https://www.om.cn/login),故本人在此基础上对其进行改进。
改进之处如下:
1.该网站当前增加了二维码登录,故首先需要在初始登录界面切换至账户密码传统登录。如图所示
需要添加如下代码进行跳转
btn = browser.find_element_by_class_name('toggle-icon.toggle-icon-tel')
btn.click()
类名通过查看网页源代码可得
在进入主页面后,需要先输入账号密码,点击登录才能弹出拼图验证窗,增加的代码如下:
browser.find_element_by_xpath('//input[@placeholder="请输入手机或邮箱"]').send_keys('xxxxxxxxx@qq.com')
browser.find_element_by_xpath('//input[@placeholder="请输入密码"]').send_keys('123456')
在此之后需要进行拼图的配对,与原作者提供的代码类似,但是原作者的代码可能忘记增加了返回值,故修改如下:
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 = 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)
return max_loc
# cv2.imshow('stack'+str(max_loc), imstack)
#
# cv2.waitKey(0)
# cv2.destroyAllWindows()
matchImg(r'C:xxx1.png',r'C:xxx2.png')
此外修改的部分还包括验证图片的获取以及后续鼠标的动作,之间异同可以参考两个代码。
完整版代码如下:
import requests
import time
import cv2
import match
import requests
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options
def download_img(img_url, img_name):
# 添加http请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}
r = requests.get(img_url, headers=headers, stream=True)
# print(r.status_code) # 返回状态码
if r.status_code == 200:
with open(img_name, 'wb') as f:
f.write(r.content)
return True
chrome_options = Options()
# 新建selenium浏览器对象,本文使用的是chrome浏览器驱动
browser = webdriver.Chrome(executable_path=r'C:xxxchromedriver', chrome_options=chrome_options)
# 网站登陆页面
url = 'https://www.om.cn/login'
# 浏览器访问登录页面
browser.get(url)
handle = browser.current_window_handle
# 等待3s用于加载脚本文件
browser.implicitly_wait(3)
# 点击二维码切换图标,切换至常规登录界面
btn = browser.find_element_by_class_name('toggle-icon.toggle-icon-tel')
btn.click()
#输入用户名及密码
browser.find_element_by_xpath('//input[@placeholder="请输入手机或邮箱"]').send_keys('xxxxxx@qq.com')
browser.find_element_by_xpath('//input[@placeholder="请输入密码"]').send_keys('123456')
btn = browser.find_element_by_class_name('submit-btn')
btn.click()
# 获取iframe元素,切到iframe
frame = browser.find_element_by_id('tcaptcha_iframe')
browser.switch_to.frame(frame)
# 等待两秒钟让验证图片加载完毕,否则可能获取不到
time.sleep(2)
# 获取背景图src
targetUrl = browser.find_element_by_id('slideBg').get_attribute('src')
# 获取拼图src
tempUrl = browser.find_element_by_id('slideBlock').get_attribute('src')
# 获取拼图初始位置
loc = browser.find_element_by_id('slideBlock').get_attribute('style')
start = int(loc[loc.rfind(' '):loc.rfind('p')])
if not download_img(targetUrl, 'temp_target.png'):
print('fail0')
if not download_img(tempUrl, 'temp_temp.png'):
print('fail1')
time.sleep(1)
img1 = cv2.imread('temp_target.png')
img2 = cv2.imread('temp_temp.png')
# 因为每个人电脑的分辨率不一样,如用原作者方法会导致处理图片比较费劲
# 新建标签页
# browser.execute_script("window.open('');")
# # 切换到新标签页
# browser.switch_to.window(browser.window_handles[1])
#
# # 访问背景图src
#
# browser.get(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.execute_script("window.open('');")
#
# browser.switch_to.window(browser.window_handles[2])
#
# browser.get(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 = match.matchImg('temp_target.png', 'temp_temp.png')
# 计算出拖动距离,iframe中的图片大小为原尺寸的一半
distance = int(move[0]/2 - loc + 1.5)
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(draggable).perform()
time.sleep(2)
最后感谢原作者提供的宝贵经验,原作地址:https://www.cnblogs.com/chenjy1225/p/11810895.html



