【作者主页】:吴秋霖
【作者介绍】:Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作!
【作者推荐】:对JS逆向感兴趣的朋友可以关注《爬虫JS逆向实战》,对分布式爬虫平台感兴趣的朋友可以关注《分布式爬虫平台搭建与开发实战》
还有未来会持续更新的验证码突防、APP逆向、Python领域等一系列文章
今天给大家带来一个爬虫领域过花式验证码小技巧,这是最近来源于一位铁子的分享,验证码是下面这样的(可以看到附带了某些条件,比如说输入特定颜色的字符):
在此之前我专门去开源社区找了找一些成熟的解决方案,确实有多种花式处理的方案,相比于自己去收集样本,训练一个识别模型,其中数据样本的标注是比较耗时的,想要保持较高的准确率,这是一件持续的事情,因为你需要让你的模型有能够适应更新带来的对抗。又或者是打码平台的低效率,这次分享的方式更加实用:
话不多说,核心代码其实也就几十行,轻轻松松识别上面类型的验证码,代码的核心思想就下面四步:
1、颜色空间转换
2、根据HSV颜色阈值生成掩码
3、生成黑白结果图
4、OCR文字内容识别
通俗点讲就是剔除与需提取颜色无关的内容,最后识别!
HSV颜色阈值参考如下(具体自己可以调节):
首先将事先准备好的验证码图片,然后通过程序读取图片,代码如下:
def read_image(image_path):
img = cv2.imread(image_path)
if img is None:
raise ValueError(f"读取图片失败: {image_path}")
return img
HSV(色调、饱和度、亮度)颜色空间是一种表示颜色空间的模型,类似于 RGB 颜色模型
我们可以根据上面HSV范围的阈值范围,使用cv2.inRange函数生成二值掩码。掩码中的目标颜色对应的区域被设为白色(255),其他颜色对应的区域被设为黑色(0)
def apply_color_mask(hsv, lower, upper):
return cv2.inRange(hsv, np.array(lower), np.array(upper))
生成黑白结果图的目的就是将指定颜色的内容从原始图像中提取出来,以便进行后续的OCR文字识别。在验证码的应用场景中,验证码可能包含多个颜色,而我们只对其中某一种颜色感兴趣。通过生成黑白结果图,我们可以将感兴趣的颜色保留下来,而将其他颜色置为白色,从而突出需要识别的内容,代码如下:
def generate_result_image(img, mask, result_path):
result = np.zeros_like(img)
result[mask == 255] = [0, 0, 0]
result[mask != 255] = [255, 255, 255]
cv2.imwrite(result_path, result)
这是验证码图片处理完生成黑白图的效果:
最后借助OCR对黑白结果图进行识别,基本上成功率在90%以上,基本够用,识别代码如下:
def ocr_classification(image_path):
try:
with open(image_path, 'rb') as f:
img_bytes = f.read()
ocr = ddddocr.DdddOcr(show_ad=False)
return ocr.classification(img_bytes)
except Exception as e:
raise ValueError(f"OCR识别出错: {e}")
def verification_ocr(image_path, tips):
"""验证码识别主函数
Args:
image_path: 图像文件路径
tips: 识别提示, 包括"红色"、"黄色"、"蓝色"、"全部"
Returns:
result: OCR识别结果
"""
result_path = "1.png"
img = read_image(image_path)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
color_ranges = {
"红色": ([0, 50, 50], [10, 255, 255], [170, 50, 50], [180, 255, 255]),
"黄色": ([17, 45, 50], [34, 255, 255]),
"蓝色": ([100, 50, 50], [130, 255, 255]),
}
if tips in color_ranges:
ranges = color_ranges[tips]
mask = apply_color_mask(hsv, *ranges[:3])
if tips == "红色":
mask2 = apply_color_mask(hsv, *ranges[2:])
mask = cv2.bitwise_or(mask, mask2)
generate_result_image(img, mask, result_path)
with open(result_path, 'rb') as f:
img_bytes = f.read()
ocr = ddddocr.DdddOcr(show_ad=False)
res = ocr.classification(img_bytes)
#输出识别内容
print(res)
tips参数代表传入的颜色,并根据颜色去选择阈值
cv2.cvtColor(img, cv2.COLOR_BGR2HSV)将图像从BGR色彩空间转换为HSV色彩空间。HSV(色调、饱和度、明度)通常更适合基于颜色的图像处理
ddddocr这个库自然不用多说了,很好用。可以满足很对场景下的使用需求,开源的力量!
如果你只是为了解决这类验证码识别为目的,那么这个方案完全是够用的!最后,其实还是建议大家体验一下自己训练样本的过程,打造一个高质量的model
好了,到这里又到了跟大家说再见的时候了。创作不易,帮忙点个赞再走吧。你的支持是我创作的动力,希望能带给大家更多优质的文章