Python爬虫:验证码识别

有段日子没写博客了,工作略忙~(这是借口)

回归正题,验证码是爬虫永远绕不过去的坎。无论你是常规爬取还是用selenium+无头浏览器进行用户的登陆操作,都需要识别验证码。为了搞验证码,搞得对图像也有了初步的了解,不废话说结论。

安装:

环境:win10,anaconda3 ,python3.6

1、开源OCR tesseract 下载网址  https://digi.bib.uni-mannheim.de/tesseract/  ,建议选择tesseract-ocr-setup-3.05.01- 20170602.exe,4.0的那几个eng.traineddata训练效果都不咋样,4.0的真的折腾了我好久怎么也训练不好。

2、python适配的包 tesserocr 联网直接 conda install -c simonflueckiger tesserocr pillow。

      离线方法: https://github.com/simonflueckiger/tesserocr-windows_build/releases 下载对应tesseract版本的whl,进入conda文件夹下cmd,pip install whl。(经测试 tesserocr v2.4.0  兼容3.05的tesseract)

3、记得配环境path。具体操作别的博客有介绍。

     path D:\Tesseract-OCR\ 和 D:\Tesseract-OCR\tessdata\
     TESSDATA_PREFIX  D:\Tesseract-OCR\tessdata

 

本文以 http://asone.safesvc.gov.cn/asone/    国家外汇管理局网上服务平台的验证码为例进行识别。从该网站下载了验证码进行实践,样例如下:

tesseract只能识别最简单的图片,像本文使用的这种验证码无法直接识别,需要经过变灰度图、二值化、去边框、降点噪声才能进行识别。

对图片进行处理前首先要确定它是三通道还是单通道,三通道的图要先变成灰度图才能进行二值化。转灰度、二值化的代码如下:

#灰度 二值化
def binarizing(img, threashold):
    img = img.convert("L")  # 转灰度
    pixdata = img.load()
    w, h = img.size
    for y in range(h):
        for x in range(w):
            if pixdata[x, y] < threashold:
                pixdata[x, y] = 0
            else:
                pixdata[x, y] = 255
    return img

threashold取200的样例结果:

然后进行去边框,代码如下:

def removeFrame(img, width):
    w, h = img.size
    pixdata = img.load()
    for x in range(width):
        for y in range(0, h):
            pixdata[x, y] = 255
    for x in range(w - width, w):
        for y in range(0, h):
            pixdata[x, y] = 255
    for x in range(0, w):
        for y in range(0, width):
            pixdata[x, y] = 255
    for x in range(0, w):
        for y in range(h - width, h):
            pixdata[x, y] = 255
    return img

width取1的样例结果:

此时还有很多点噪声,用tesseract依然不能成功识别,采用八领域去噪声法进行去噪声。代码如下:

# 点降噪
def depoint(img):
    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 pixdata[x-1, y-1] > 245:
                count = count + 1
            if pixdata[x-1, y+1] > 245:
                count = count + 1
            if pixdata[x+1, y-1] > 245:
                count = count + 1
            if pixdata[x+1, y+1] > 245:
                count = count + 1
            if count > 5:
                pixdata[x,y] = 255
    return img

这里count选择的大于5效果最好,这个得根据实际需求去调试最优结果。样例结果:

此时图像已经处理的很清晰了。然后用tesserocr库进行识别,识别成功率还是挺高的,识别结果有的时候中间有空格,和换行符,具体原因不清楚,去掉就好。再强调一次,一定要用tesseract-ocr-setup-3.05.01-20170602.exe安装包!

主程序代码:

import tesserocr
import vc_processing
from PIL import Image

img = Image.open('image.bmp')
img = vc_processing.binarizing(img,200)
img.save('binarizing.bmp')
img = vc_processing.removeFrame(img,1)
img.save('removeFrame.bmp')
img = vc_processing.depoint(img)
img.save('depoint.bmp')
result = tesserocr.image_to_text(img,lang = "eng")
print(result.replace(' ','').strip())

输出结果:4100

理论上,本文的处理方法对彩色的验证码也应该有效果,对有横线的验证码还没有过测试,有机会再进行吧。

现在的验证码类型很多,还有一种拼图的,工作需要时再实践吧。

本文结束~

题外话,有个关于图像保存格式的小坑坑了我好久,当我用jpg格式储存二值化后的图片时,放大图片总会看到一些灰点,一度搞得让我觉得二值化有问题,折腾了好久,严重影响了测试验证码识别的效率,实际上是jpg格式储存失真的原因,用bmp格式就解决了 = =。。。

有机会写一篇关于模拟登陆  http://asone.safesvc.gov.cn/asone/    国家外汇管理局网上服务平台的博客,在不用selenium的情况下还是挺麻烦的。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值