验证码的识别

随着爬虫越来越多,许多网站都采取了各种各样的反爬虫机制,其中最常见的就是使用验证码,现在随着技术的发展,验证码已经由数字演变成了字母,滑动,九宫格等各种验证码

前言

由于tesserocr库是比较老的库,目前只更新到只吃python3.7,而由于我的是python3.8经过多次尝试之后,发现还是无法使用,经过查看大量的资料,我使用了另外一个库—pytesseract

pytesseract这个库原理几乎和tesserocr库相同

图形验证码识别

我们先识别一下最简单的一种验证码,即图形验证码。这种验证码最早出现,也很常见,一般是由4位字母或者数字组成。例如http://my.cnki.net/Register/CommonRegister.aspx的登录验证码

获取验证码

首先需要安装pytesseract库

为了便于实验,我们先将验证码图片保存在本地,先测试一下

首先F12打开开发者工具,查看验证码的url
avatar

接下来访问一下这个aspx
avatar
由于验证码是动态的 所以也没有什么太大的关系

加下来把这个aspx保存下来,命名为code.png

代码:

1
2
3
4
5
6
7
8
9
import pytesseract
from PIL import Image

image=Image.open('D:\\code.png')
image=image.convert('RGB')
print(pytesseract.image_to_string(image))

输出结果:
Gsee

这里新建了一个Image对象,调用了pytesseract的image_to_string()方法,传入该对象即可完成识别,但是要注意的是,由于pytesseract的特殊性,处理图片时,由于图片可能不是RGBA通路的,所以最后在打开图片后等增加image.convert(‘RGB’)语句,保证图片是RGB格式的

验证码处理

接下来我们换一个验证码,命名为code2.png
avatar

重新用以下代码来测试:

1
2
3
4
5
6
import pytesseract
from PIL import Image

image=Image.open('D:\\code2.png')
image=image.convert('RGB')
print(pytesseract.image_to_string(image))

我刷新的这个验证码并没有出现偏差,但是例如
avatar
就会出现偏差
1
2
3
4
5
6
7
8
9
import pytesseract
from PIL import Image

image=Image.open('D:\\test.jpg')
image=image.convert('RGB')
print(pytesseract.image_to_string(image))

输出结果:
thye

这个时候,其实是因为验证码多余的线条干扰了图片的识别,我们在这里还需要进行额外的处理,如转灰度,二值化等操作

我们可以利用Image对象的convert()方法传入L,即可将图片转为灰度图像

1
2
image=image.convert('L')
image.show()

avatar

这样就成功将其灰度化

传入1即可将图片进行二值化处理

1
2
image=image.convert('1')
image.show()

我们还可以指定二值化的阈值,上面的方法默认采用的是127.不过我们不能直接转换,需要将图片先灰度化,然后化再指定阈值
1
2
3
4
5
6
7
8
9
10
image=image.convert('L')
threshold=110
table=[]
for i in range(256):
if i<threshold:
table.append(0)
else:
table.append(1)
image=image.point(table,'1')
image.show()

avatar
这里将阈值调整为110 图片中的内容才能显示完成,阈值的值是根据验证码的情况来确定的,并不是一个定值

我们看到经过处理之后的验证码,线条已经被去除,验证码变得黑白分明,这个时候才重新识别验证码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import pytesseract
from PIL import Image

image=Image.open('D:\\test.png')
image=image.convert('RGB')
image=image.convert('L')
threshold=110
table=[]
for i in range(256):
if i<threshold:
table.append(0)
else:
table.append(1)
image=image.point(table,'1')
print(pytesseract.image_to_string(image))

输出结果:
fhYe

针对一些有干扰的图片,我们就可以做一些灰度和二值化的处理,以此来提高图片的正确率

总结

1.tesseror库比较过时,而且版本更新较慢,目前只支持到了python3.7的版本

2.由于tesseror库无法使用,所以采用了pytesseract库,但是由于pytesseract库的特性,只会识别RGB通道的图片,所以需要在每条语句的后面都添加上image.convert(‘RGB’)

3.文字验证码较为简单,但是会有一些斑点或线条等进行干扰,所以需要采用灰度和二值化来进行处理

4.二值化处理之前需要先进行灰度化的处理,并且每个图片需要设置的阈值可能会不同,阈值不是一个定值,需要经常进行更换