虽然cv2是直接通过导入cv2包使用,但是它不是通过import cv2
安装,需要通过pip install opencv-python
安装,直接pip安装可能会比较慢,可以使用pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple
安装
当点击滑块时,会显示缺口背景图和方块,将方块移动到背景图缺口处就能实现验证,我们可以看看验证通过整个过程的请求包来判断它的验证逻辑
当我们点击滑块时,会去请求方块和背景图,当我们滑动并停止滑动滑块后,会发起一个验证请求,推测这个请求会把我们的动作传给后端验证,而我们的动作直接产生的就是坐标的变化,一般验证码验证会根据两种方式验证,坐标参数验证
和滑动轨迹验证码
。坐标参数验证
是传递一个滑块停止后的坐标,而滑动轨迹验证码
是传递一个坐标数组,记录滑块整个滑动周期变化的坐标。
我们查看异步请求验证这个包,看看它传递的参数便可以知道属于哪种验证逻辑
观察参数可以确定它传递的是滑块移动停止时的坐标,那怎么拿到这个坐标呢,dragleft
我们假定是方块左侧坐标的距离,dragright
我们假定是方块右侧坐标的距离,然后模拟一下查看style样式中left的变化。
多次观察可以确定,这个left便是dragleft
的值,而dragright
比dragleft
要大32,这样我们只要知道dragleft
的值便能确定dragright
了。
使用cv2计算图片差异位置的坐标,我们需要拿到背景图片和方块图片,通过对比背景图片和方块图片之间的联系与差异从而定义差异的坐标。
cv2识别代码
# -*- coding: utf-8 -*-
from PIL import Image
from io import BytesIO
import numpy as np
import cv2
def identify_gap(bg, tp):
"""
:param bg: 背景图片
:param tp: 缺口图片
:return int
"""
# 读取背景图片和缺口图片
bg_img = get_cv2_img(bg) # 背景图片
tp_img = get_cv2_img(tp) # 缺口图片
if type(bg_img) == str or type(tp_img) == str:
print('图片格式存在问题,无法用cv2读取!')
return
# 识别图片边缘
bg_edge = cv2.Canny(bg_img, 100, 200)
tp_edge = cv2.Canny(tp_img, 100, 200)
# 转换图片格式
bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)
tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB)
# 缺口匹配
res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
print(min_val, max_val, min_loc, max_loc)
# 返回缺口的X坐标
return max_loc[0]
def get_cv2_img(img_object):
if type(img_object) == str:
cv_img = cv2.imread(img_object)
elif type(img_object) == bytes:
image_data = BytesIO(img_object)
img = Image.open(image_data)
cv_img = np.asarray(img)
else:
cv_img = None
return cv_img
if __name__ == '__main__':
print(identify_gap('背景图本地路径', '方块本地路径'))
print(identify_gap('背景图二进制流', '方块二进制流'))
测试识别结果
# -*- coding: utf-8 -*-
import requests
from sxSpider.check_open_cv.cv2_gap import identify_gap
header = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'Cookie': 'lnReGnsFlag=0; tbbysb=N; tbzbsy=N; LESB_SESSION=ZF9tq3-Avn6LnFE80mstxwI3QTwoHZdyPrz_FWuwwpPu_As9a2fy!46501968',
'Host': 'etax.ningxia.chinatax.gov.cn',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36',
}
before_img_url = 'https://etax.ningxia.chinatax.gov.cn/download.sword?ctrl=CheckcodeCtrl_initBgPic&0.1601673354750519&bgPicPath=/wsbs/images/bg4_style2.jpg&id=dragCheckCode'
after_img_url = 'https://etax.ningxia.chinatax.gov.cn/download.sword?ctrl=CheckcodeCtrl_initcutPic&0.14661519005791934&bgPicPath=/wsbs/images/bg4_style2.jpg&id=dragCheckCode'
before_img_resp = requests.get(before_img_url, headers=header)
before_img = before_img_resp.content
with open('image/before.png', 'wb') as fb:
fb.write(before_img_resp.content)
after_img_resp = requests.get(after_img_url, headers=header)
after_img = after_img_resp.content
with open('image/after.png', 'wb') as fb:
fb.write(after_img_resp.content)
drag_left = identify_gap(before_img, after_img)
drag_right = drag_left + 32
print(drag_left, drag_right)
如果想看看识别的到底对不对,可以圈出识别位置
# 绘制方框
th,tw = tp_pic.shape[:2]
tl = max_loc # 左上角点的坐标
br = (tl[0] + tw, tl[1] + th) # 右下角点的坐标
cv2.rectangle(bg_img, tl, br, (0, 0, 255), 2) # 绘制矩形
cv2.imwrite('存储路径', bg_img) # 保存在本地