Python中处理验证码有什么好的方法或思路?

验证码 captcha

验证码字符只有 英文加数字; 我的思路:转为灰度,二值化处理,除去干扰横线(正在做),然后用 pytesseract 识别。干扰线除去有点儿复杂 正在做还不知道识别率有多大...

干掉干扰线 你们有没有啥头绪? 干扰线纵向都是 3 个像素,我目前的想法就是:纵向检测 3 像素的黑线

这是简单处理后的 还没有解决干扰线 captcha


Python中处理验证码有什么好的方法或思路?

32 回复

用 CNN


处理验证码通常分两种情况:自己生成和自动识别。

生成验证码
Pillow 库画图,加上随机字符、干扰线、噪点就行。下面是个简单例子:

from PIL import Image, ImageDraw, ImageFont
import random
import string

def generate_captcha():
    width, height = 180, 60
    img = Image.new('RGB', (width, height), color='white')
    draw = ImageDraw.Draw(img)
    
    # 画干扰线
    for _ in range(5):
        x1 = random.randint(0, width)
        y1 = random.randint(0, height)
        x2 = random.randint(0, width)
        y2 = random.randint(0, height)
        draw.line([(x1, y1), (x2, y2)], fill='gray', width=2)
    
    # 生成随机字符
    chars = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))
    font = ImageFont.truetype('arial.ttf', 36)
    
    # 画文字(每个字符位置随机偏移一点)
    x_offset = 10
    for ch in chars:
        y_offset = random.randint(-5, 5)
        draw.text((x_offset, 10 + y_offset), ch, fill='black', font=font)
        x_offset += 40
    
    # 加噪点
    for _ in range(200):
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw.point((x, y), fill='gray')
    
    img.save('captcha.png')
    return chars, img

# 使用
text, image = generate_captcha()
print(f'验证码文本:{text}')

自动识别验证码
简单的可以用 pytesseract(OCR),但复杂验证码效果差。这时候要么用机器学习(CNN训练),要么直接找打码平台(第三方API)。

import pytesseract
from PIL import Image

def recognize_captcha(image_path):
    img = Image.open(image_path)
    # 预处理:转灰度、二值化等能提升识别率
    img = img.convert('L')
    text = pytesseract.image_to_string(img, config='--psm 8')
    return text.strip()

复杂验证码就上 CNN 或者 EasyOCR 这类库,但需要自己标注数据训练。

总结:简单验证码自己生成和识别都不难,复杂的建议用现成API。

直接用 OCR 呢

安利一下简单粗暴的卷积神经网络脚本: https://github.com/nickliqian/cnn_captcha

这个是用谷歌开源的 kaptcha 生成的,可以使用机器学习进行训练

似乎不是,但方法是一样的

不用机器学习的话,看上去字比线粗,可以使用一个像素周围一定范围不是黑就去掉的办法,结果是线没了,字变细

这种样本量少的话真不好做,建议使用收费的打码平台 api。

pytesseract 暑假里面用的时候发现其对手写文本的识别率极差,这种倾斜变形的字体可能识别效果也不会很好。

如果没有图像处理的知识,建议还是打码吧! 简单粗暴效率超高!

图像处理里有一个操作叫 erosion,你可以试试看

一楼说的对,cnn 比较好。

这种类型的验证码用传统的图像算法和 tesseract 效果应该都不会好。会算法技术就试下训练网络,不行的话找打码平台吧

看了以后,我还是选择第三方的接口吧

只有数字和字母?? CNN100 张就够,在线训练的网址也有

打码平台挺便宜的,可以考虑一下,30 块可以打 1000 张。。。

不行的 老哥,项目上线了远不止 1000 张 而且只是个 个人项目,没有收入来源。

我了解一下

之前写爬虫用过 pytesseract,用各种常规方法处理验证码图片,最后效果反而不好,我最终的解决方案是不处理图片,直接识别,识别失败则重新请求验证码,再识别,无限循环。一般十几次之内能识别出来。

个人项目的话如果不是后台跑着帮用户 24 小时收集数据的项目的话,就直接把验证码扔给用户让用户填啊。

剩下打码平台用不起的话,那就只能自己学图像处理了。或者简单粗暴上 cnn

这有干扰线的 根本识别不出来。有干扰线的 肯定要解决干扰线

老哥 求个链接

把高为 3 个像素的黑点都去掉,然后正常的字母中间会有白色的空白线,然后在把上线都有黑色像素点且空白宽度为 3 的空白像素点置为黑色,这样字母部分就补齐了。不知道行不行

pytesseract 不能识别这种会变形的文字,所以还是上 cnn 吧

好的点子就是悬赏。。。出个 500、800 的,问题就解决了。。。

腐蚀再膨胀说不定能去掉

有个问题,你能写出生成这种验证码的代码吗?可以的话,就可以用 CNN 开心的训练了
数据量足够的话,这种的 case 肯定能解决的

那我就爱莫能助了

你或许需要一些 hacker 思维,寻找干扰线与正常字符之间的差别规律,然后针对这个规律写处理代码。其实还挺有意思的,这是测试效果:





只要能做到有效分割,也就基本意味着破解成功了,分割之后大概只需要标注 100 张左右,这点体力活比起直接用 CNN 撸(需要标注上万张)还是很容易接受的,后面再随便在 sklearn 里挑一个算法来训练就行了。

对了,对于你这种验证码,如上图连在一起的,直接从中间分开就行了,不会差很多,对于单个字符,只要你人能认出来,多层感知器训练后认出来没问题。大不了就跳过,从新刷新一张。识别成功率能到 50%就能用了。

思路很棒,谢谢

回到顶部