01_验证码之字符验证码
认识验证码
什么是验证码
验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart” (全自动区分计算机和人类的图灵测试)的缩写, 是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水, 有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。 这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答CAPTCHA的问题, 所以回答出问题的用户就可以被认为是人类
验证码类别
图像验证码
对图像验证码来讲,这类验证码大多是数字、字母的组合,国内也有使用汉字的。在这个基础上增加噪点、干扰线、变形、重叠、不同字体颜色等方法来增加识别难度。 相应的这种验证码的识别大概分为以下几个步骤: 1.灰度处理 2.二值化 3.降噪 4.识别
滑动验证码
滑动验证码也可以叫做行为验证,其中最出名的就是极验。 现在极验验证码已经更新到了 3.0 版本,截至 2017 年 7 月全球已有十六万家企业正在使用极验,每天服务响应超过四亿次,广泛应用于直播视频、金融服务、电子商务、游戏娱乐、政府企业等各大类型网站。 滑动验证码的原理就是使用机器学习中的深度学习技术,根据一些特征来区分是否为正常用户。 比如,可以通过记录用户的滑动平均速度,还有每一小段时间的瞬时速度,用户鼠标点击情况,以及滑动后的匹配程度来识别。而且,不是说滑动到正确位置就是验证通过,而是根据特征识别来区分是否为真用户,滑到正确位置只是一个必要条件。
点触验证码
点击验证码 常见的点击类验证码都是给出一张包含文字的图片,通过文字提醒用户点击图中相同字的位置进行验证。 如:
PIL或pillow库
PIL介绍
PIL (Python Image Library) 是 Python 平台处理图片的事实标准,兼具强大的功能和简洁的 API。
另外虽然介绍的是 PIL,但实际上安装的却是 Pillow。PIL 的更新速度很慢,而且存在一些难以配置的问题,不推荐使用;
而 Pillow 库则是 PIL 的一个分支,维护和开发活跃,Pillow 兼容 PIL 的绝大多数语法,推荐使用。
安装: sudo pip install pillow 安装好之后,打开 Python 解释器,输入 from PIL import Image 来测试是否安装成功。
PIL的基本概念
PIL中所涉及的基本概念有如下几个:通道(bands)、尺寸(size)、坐标系统(coordinate system)。
通道:每张图片都是由一个或者多个数据通道构成。PIL允许在单张图片中合成相同维数和深度的多个通道。
以RGB图像为例,每张图片都是由三个数据通道构成,分别为R、G和B通道。而对于灰度图像,则只有一个通道。
对于一张图片的通道数量和名称,可以通过方法getbands()来获取。
方法getbands()是Image模块的方法,它会返回一个字符串元组(tuple)。该元组将包括每一个通道的名称。
尺寸 通过size属性可以获取图片的尺寸。这是一个二元组,包含水平 和垂直方向上的像素的个数。
以一下图片为例:
from PIL import Image image = Image.open('code.jpg') # 打开验证码 print(image.size) # 获取大小 print(image.getbands()) # 获取通道
打印结果:
PIL图像操作
PIL 的主要功能定义在 Image 类当中,而 Image 类定义在同名的 Image 模块当中。使用 PIL 的功能,一般都是从新建一个 Image 类的实例开始。
新建 Image 类的实例有多种方法。你可以用 Image 模块的 open() 函数打开已有的图片档案,
也可以处理其它的实例,或者从零开始构建一个实例。
生成图片 Image.new(mode, size, color) ⇒ image 其中mode表示模式,size表示大小,color表示颜色
# 创建一个新图片,mode,size, color im = Image.new("RGB", (128, 128), "#FF0000") im.save('red.jpg') # 保存图片
Image 类的实例有 4 个常用属性,分别是:
format: 以 string 返回图片档案的格式(JPG, PNG, BMP, None, etc),如果不是从打开文件得到的实例,则返回 None。
mode: 以 string 返回图片的模式(RGB, CMYK, etc)
size: 以二元 tuple 返回图片档案的尺寸 (width, height)
info: 以字典形式返回示例的信息
Image中还有一些常用的实例方法:
convert 将当前图像转换为其他模式,并且返回新的图像。
from PIL import Image im = Image.open('code.jpg') print(im.mode) im1 = im.convert('1') print(im1.mode)
getpixel((x,y)) 返回给定位置的像素值。如果图像为多通道,则返回一个元组。
from PIL import Image im1 = Image.open("code.jpg") print(im1.getpixel((1,1))) # 获取某个点的像素值 print(im1.getpixel((6,6)))
crop()图像中剪切出某个矩形大小的图像。
它接收一个四元素的元组作为参数,各元素为(left, upper, right, lower),坐标系统的原点(0, 0)是左上角。
例如(0,0,10,10),其实相当于x取值0-10,y取值0-10,裁剪得到一个10x10的图片。
简单验证码识别
简单验证码识别一般需要3个步骤:
灰度处理
灰度图像是R、G、B三个分量相同的一种特殊的彩色图像。 简单来讲就是R=G=B.
依旧以上文的验证码为例:
from PIL import Image image = Image.open('code.jpg') im = image.convert('L')
im.show()
得到灰度处理后的图片如下:
二值化
图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。
def binarizing(img, threshold=127): """传入image对象进行灰度、二值处理""" img = img.convert("L") # 转灰度 pixdata = img.load() # 加载该图片 w, h = img.size # 拿到该图片的宽度和长度 # 遍历所有像素,大于阈值的为黑色 for y in range(h): for x in range(w): # 设定阈值,像素点小于阈值,就取0;大于就取255 # 此阈值可以根据具体图片稍作调整 if pixdata[x, y] < threshold: pixdata[x, y] = 0 else: pixdata[x, y] = 255 return img
依旧以上图为例,二值化之后的图片效果:
可以看到,经过二值化后的验证码上,字母基本是可以识别的,但是依旧还有几个点点,因此,降噪处理,将这些点点也去掉。
降噪
根据一个点A的RGB值,与周围的8个点的RBG值比较,
设定一个值N(0 <N <8),当A的RGB值与周围8个点的RGB相等或者小于N时,此点为噪点
一般设置为4或者8。
def depoint(img): """ 传入二值化后的图片进行降噪 就是遍历图片上的每个点,如果这个点周围的4个点都为白色点, 则说明这个点是孤立的点,可以考虑去除 """ pixdata = img.load() # 加载图片 w, h = img.size # 获取图片的长度和宽度 # 遍历图片的每个像素点 for y in range(1, h-1): for x in range(1, w-1): count = 0 if pixdata[x, y-1] > 245: # 上 判断上方的点是否为白色点 count = count + 1 if pixdata[x, y+1] > 245: # 下 判断下方的点是否为白色点 count = count + 1 if pixdata[x-1, y] > 245: # 左 同理 count = count + 1 if pixdata[x+1, y] > 245: # 右 count = count + 1 if count > 4: pixdata[x, y] = 255 return img
当然,如果二值化处理好的话,可能会没有噪声点,此时基本上就可以进行直接识别了。
字符识别
结果上述处理后的图片,基本效果如下:
处理后的图片,借用python的pytesser3包进行简单的识别。使用该插件进行识别需要结果以下几步:
1.使用:
pip install pytesser3
进行安装。
2.下载:Tesseract OCR
3.修改pytesser3包下面__init__文件内tesseract_exe_name的值为你的tesseract.exe的路径
from PIL import Image from pytesser3 import image_to_string image = Image.open('code.jpg') print(image_to_string(image))
运行结果:
显然,已经识别出来了。当然,这个库只能识别一些简单的的验证码,复杂的可能存在一些问题。
基本上复杂的字符验证码,可以借助神经网络,识别准确率高达98%
如果没有机器学习的基础,也可以借助一下打码平台,直接调用接口进行识别验证码。