目录

用Python写网络爬虫(5)-验证码处理

验证码处理

验证码(CAPTCHA)的全称为全自动区分计算机和人类的公开图灵测试(Completely Automated Public Turing test to tell Computersand Humans Apart)。验证码用于测试用户是否为真实人类。

自动化处理字符验证码主要有光学字符识别(OCR)验证码处理API(打码平台)

光学字符识别OCR

通常在对验证码图像进行识别之前,要先对图像进行预处理,以提高识别效率。

预处理主要包括:

  • 将图像阈值化(二值化);
  • 对图像进行增强,突出字符形状;
  • 调整图像大小;

然后使用开源的Tesseract OCR引擎进行识别,目前该引擎由Google主导。

1
2
import pytesseract
pytesseract.image_to_string(img)

如果需要进一步改善验证码OCR的性能,可以:

  • 根据验证码字体训练OCR工具;
  • 限制结果为组成验证码的字符(数字、字母等);

图像二值化

图像二值化,即是将图像转换为黑白图像。但不能直接使用PIL.Image.convert('1')方法,因为我们二值化的目的是将验证码文字与背景干扰区分开来。

首先将验证码图像转换为灰度图像:

1
2
3
4
5
from PIL import Image
from io import BytesIO

img = Image.open(BytesIO(img_bindata))
gray_img = img.convert('L') # 转换为灰度图像

得到图像的灰度直方图:

1
gray_img.histogram()    # 得到的是一个list

一般来说,验证码直方图上会有两个峰值,一个是背景干扰,一个是验证码文字,取两峰中间的值作为阈值进行二值化。

1
2
table = [0 if i <= 180 else 1 for i in range(256)]
bilevel_img = gray_img.point(table, '1')

table是转换映射表。此处取阈值为180,灰度低于180的映射为黑色0,灰度高于180的映射为白色。使用point方法进行转换。转换后,验证码图像的背景干扰应该已经被去除了。

图像增强

经过二值化的图像,背景干扰可能已经被去除了,但验证码文字可能过胖或有缺失,此时直接进行ocr识别成功率会比较低,可以先进行图像增强,再进行OCR识别。

如果文字过胖,可以对图像进行腐蚀;如果文字缺失,可以干啥来着,我忘了= =;如果图像过小,可以先进行放大。挖坑待更。

Tesseract OCR识别

1
2
import pytesseract
pytesseract.image_to_string(bilevel_img, lang='eng', config='-psm 13')

lang可以指定识别文字的语言,默认为英文;config默认为-psm 3,调整成不同值会有不同的效果,具体参见

tesseract命令行参数帮助。

使用打码平台

将验证码提交给打码平台API,打码平台通过人工查看,在HTTP响应中给出解析后的文本,一般来讲该过程在30秒内。但是打码平台一般属于黑产,谨慎使用为妙。

国外有一网站9kw,允许用户人工处理验证码以获取积分,然后花费积分处理自己的验证码。不用花钱哟!但是其只会返回普通字符串,且返回时间取决于当时在线的人数,不是很稳定。