识别验证码
OCR(Optical Character Recognition)即光学字符识别技术,专门用于对图片文字进行识别,并获取文本。字符验证码的特点就是验证码中包含数字、字母或者掺杂着斑点与混淆曲线的图片验证码。识别此类验证码,首先需要找到验证码验证码图片在网页HTML代码中的位置,然后将验证码下载,最后再通过OCR技术进行验证码的识别工作。
- 字符验证码
1.1 OCR环境
Tesseract-OCR是一个免费、开源的OCR引擎,通过该引擎可以识别图片中的验证码,搭建OCR的具体步骤如下:
(1)这里以macOS操作系统为例,使用brew install安装tesseract,命令如下:
liuxiaowei@MacBookAir ~ % brew install --with-training-tools tesseract # 同时安装附加组件
安装完毕后用如下命令测试,示例代码如下:
liuxiaowei@MacBookAir ~ % tesseract -v
tesseract 5.0.1
leptonica-1.82.0
libgif 5.2.1 : libjpeg 9d : libpng 1.6.37 : libtiff 4.3.0 : zlib 1.2.11 : libwebp 1.2.1 : libopenjp2 2.4.0
Found AVX2
Found AVX
Found FMA
Found SSE4.1
Found libarchive 3.5.2 zlib/1.2.11 liblzma/5.2.5 bz2lib/1.0.8 liblz4/1.9.3 libzstd/1.5.0
Found libcurl/7.77.0 SecureTransport (LibreSSL/2.8.3) zlib/1.2.11 nghttp2/1.42.0
(2)安装tesseract模块,安装命令如下:
pip install tesseract
说 明
如果使用的的是Anaconda并在安装tesseract模块时出现错误,可以使用如下命令:
conda install -c simonflueckiger tesseract
1.2 下载验证码图片
以下面地址对应的网页为例,下载网页中的验证码图片,具体步骤如下:
测试页面地址:http://sck.rjkflm.com:666/spider/word/
(1)使用浏览器打开测试网页的地址,将显示如下图片所示的字符验证码:
(2)打开浏览器开发者工具,然后在HTML代码中获取验证码图片所在的位置,如下图所示:
(3) 对目标网页发送网络请求,并在返回的HTML代码中获取图片的下载地址,然后下载验证码图片。代码如下:
#_*_coding:utf-8_*_
# 作者 :liuxiaowei
# 创建时间 :2/15/22 7:47 PM
# 文件 :获取HTML代码中地址下载验证码图片.py
# IDE :PyCharm
# 导入网络请求模块
import requests
# 导入urllib.request模块
import urllib.request
# 导入随机请求头
from fake_useragent import UserAgent
# 导入ssl,否则ssl验证错误
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
# 导入解析HTML的模块
from bs4 import BeautifulSoup
# 创建随机请求头
header = {
'User-Agent':UserAgent().random}
# 网页请求地址
url = 'http://sck.rjkflm.com:666/spider/word/'
# 发送网络请求
resp = requests.get(url, header)
resp.encoding = 'utf-8'
# 解析HTML
html = BeautifulSoup(resp.text, 'html.parser')
src = html.find('img').get('src')
# 组合验证码图片请求地址
img_url = url+src
# 下载并设置图片名称
urllib.request.urlretrieve(img_url, 'code.png')
程序运行后项目文件夹中自动生成验证码图片,结果如下图:
1.3 识别验证码
验证码下载完成以后, 如果没有安装pillow模块,需要通过“pip install pillow“命令安装一下,如果tesserocr模块没安装也要通过"pip install tesserocr"先安装,然后导入tesserocr与Image模块,再通过Image.open()方法打开验证码图片,接着通过tesserocr.image_to_text()函数识别图片中的验证码信息即可。示例代码如下:
#_*_coding:utf-8_*_
# 作者 :liuxiaowei
# 创建时间 :2/16/22 7:21 AM
# 文件 :识别图中验证码.py
# IDE :PyCharm
# 导入tesserocr模块
import tesserocr
# 导入图像处理模块
from PIL import Image
# 打开验证码图片
img = Image.open('code.png')
# 将图片中的验证码转换为文本
code = tesserocr.image_to_text(img)
print('验证码为: ', code)
程序运行结果如下:
验证码为: uuuc
Process finished with exit code 0
OCR的识别技术虽然很强大,但是并不是所有的验证码都可以这么轻松地识别出来,如下图所示的验证码中就会掺杂很多干扰线条,那么在识别这样的验证码信息时,就需要对验证码图片进行相应的处理并识别。
如果直接通过OCR识别,识别结果将会受到干扰线的影响,下面通过OCR直接识别测试一下效果。示例代码如下:
#_*_coding:utf-8_*_
# 作者 :liuxiaowei
# 创建时间 :2/16/22 8:23 AM
# 文件 :识别带干扰线的验证码.py
# IDE :PyCharm
import tesserocr # 导入tesserocr模块
from PIL import Image # 导入图像处理模块
img =Image.open('code2.jpg') # 打开验证码图片
img = img.convert('L') # 将彩色图片转换为灰度图片
img.show() # 显示灰度图片
code = tesserocr.image_to_text(img) # 将图片中的验证码转换为文本
print('验证码为:',code)
程序运行结果如下:
验证码为: YSGN. # 多了一个.
Process finished with exit code 0
通过以上测试发现,直接通过OCR技术识别后的验证码中多了一个‘.’,遇到此类情况手写可以将彩色的验证码图片转为灰度图片在测试一下。示例代码如下:
#_*_coding:utf-8_*_
# 作者 :liuxiaowei
# 创建时间 :2/16/22 8:29 AM
# 文件 :将彩色验证码图片转为灰度图片测试.py
# IDE :PyCharm
import tesserocr # 导入tesserocr模块
from PIL import Image # 导入图像处理模块
img =Image.open('code2.jpg') # 打开验证码图片
img = img.convert('L') # 将彩色图片转换为灰度图片
img.show() # 显示灰度图片
code = tesserocr.image_to_text(img) # 将图片中的验证码转换为文本
print('验证码为:',code)
程序运行结果如下:
验证码为: YSGN. # 依然多一个‘.‘
Process finished with exit code 0
接下来需要将转为灰度的验证码图片进行二值化处理,将验证码二值化处理后再次通过OCR进行识别。示例代码如下:
#_*_coding:utf-8_*_
# 作者 :liuxiaowei
# 创建时间 :2/16/22 8:38 AM
# 文件 :将验证码图片二值化处理.py
# IDE :PyCharm
import tesserocr # 导入tesserocr模块
from PIL import Image # 导入图像处理模块
img =Image.open('code2.jpg') # 打开验证码图片
img = img.convert('L') # 将彩色图片转换为灰度图片
t = 155 # 设置阀值
table = [] # 二值化数据的列表
for i in range(256): # 循环遍历
if i <t:
table.append(0)
else:
table.append(1)
img = img.point(table,'1') # 将图片进行二值化处理
img.show() # 显示处理后图片
code = tesserocr.image_to_text(img) # 将图片中的验证码转换为文本
print('验证码为:',code) # 打印验证码
程序运行后将自动显示二值化处理后的验证码图片
程序运行结果如下:
验证码为: YSGN
Process finished with exit code 0
说 明
在识别以上具有干扰线的验证码图片时,我们可以做一些灰度和二值化处理,这样可以提高图片的验证码的识别度,如果二值化处理后还是无法识别到精确性,可以适当的上下调节二值化操作的阙值。
接下文 Python反爬机制-验证码(二)https://developer.aliyun.com/article/1617994