资讯专栏INFORMATION COLUMN

验证码识别

keke / 932人阅读

摘要:下面我们便来讲种验证码的识别方式和一些思路。哈哈库其实,验证码识别归根到底还是对各种各样图片的识别和操作,中有很对图像处理的库,其中就是其中之一。所以在处理验证码识别之前,必须先了解库和。第五步,按照规定轨迹进行拖动,完成验证。

写在前面

现在,很多网站采取各种各样的措施来反爬虫,其中之一就是使用验证码。当我们访问网页时,必须先通过验证码才能够访问页面。下面我们便来讲2种验证码的识别方式和一些思路。当然我们也可以直接使用付费的打码平台,那样可以增加识别的准确度,毕竟出了钱的嘛。哈哈!

PIL库

其实,验证码识别归根到底还是对各种各样图片的识别和操作,python中有很对图像处理的库,其中PIL就是其中之一。 所以在处理验证码识别之前,必须先了解PIL库和tesserocr。 下面附上其API源码地址,以及对应的学习博客。
源码地址:https://pillow-cn.readthedocs.io/zh_CN/latest/reference/index.html
参考博客:https://blog.csdn.net/louishao/article/details/69879981
下面我们就开始验证码识别之路了。

图形验证码

以中国知网为例:

首先,我们先拿到上图中绿线标记的验证码,下载到本地项目文件中,
然后,编写如下代码:

import tesserocr
from PIL import Image

image = Image.open("image.png")
res = tesserocr.image_to_text(image)
print(res)  # F8BS

输出结果为:F8BS, 可是实际图片为F8B8,这是因为验证码内多余线条干扰了图片的识别,像这类情况,还需要做出额外的处理,比如转灰度,二值化等。当然,实际处理中并不是这样,一般我们会先对模糊图片进行灰度处理后,再设定二值化的阈值,实际处理如下:

import tesserocr
from PIL import Image

image = Image.open("code.jpg")  # 创建image对象

image = image.convert("L")
threshold = 150  # 指定二值化阈值
table = []
for i in range(256):
    if i < threshold:
        table.append(0)
    else:
        table.append(1)

image = image.point(table, "1")
image.show()
res = tesserocr.image_to_text(image)
print(res) 

输出结果:F8B8
进行识别时,先设定好二值化阈值threshold,进行适当调试,直到图片能正常识别为止。

滑动验证码

过程分析:

滑动验证码主要的验证方式是拖动滑块,拼合图像;如图象完全拼合,则验证成功,即表单提交成功,否则需要重新验证。
如图:

下面,我们就以极验的验证码为例,来讲诉一下识别方法。
因为极验的验证码在拖动验证码后会生成一个加密的表单提交到后台,所有为了避免麻烦我们直接用selenium模拟浏览器行为来完成验证。
登陆网站:极验官网

目标站点:https://account.geetest.com/l...

首先,我们发现登陆界面有个智能按钮,一般来说,在输入邮箱之后,点击按钮就会弹出滑动验证窗口,然后我们在拖动验证码完成图像拼接,完成验证。

所以,滑块验证识别需要完成以下步骤:

模拟点击验证按钮

识别滑块的缺口位置

模拟拖动滑块

如何实现以上步骤呢?我们先需要将任务进行分解,看似只有三大步骤,其实里面坑还有很多的,稍后会做解释。

第一步,输入账号,获取智能按钮,使用selenium模拟点击,获取带有缺口的图片。

第二步,获取上面缺口图片中的完整图片。这里有个地方要注意,正常情况下我们在网页源代码里是找不到完整图的,因为它被隐藏了,必须执行javascript语句才能出现完整图。

我们将display参数改为block,opacity参数改为1,然后进行截图,就可以拿到完整的验证码图片了。

第三步,对比两张图片的所有RGB像素点,得到缺口位置。

第四步,模拟人的拖动习惯,这里也有坑,极验的验证码增加了机器轨迹识别,匀速移动,或者随机速度移动滑块都不能通过验证,所以我们将需要拖动的总位移分成一段一段小的轨迹,先匀加速拖动后匀减速拖动。

第五步,按照规定轨迹进行拖动,完成验证。

第六步,完成账号登陆。

过程分析完了,下面我们就来写代码试一下:
首先,我们先将整个代码的一个逻辑思路做一个大致的概括吧。

def main():
    """主函数"""

    # 获取带缺口验证码图片image1, 传入的参数后缀为: .png
    image1 = get_unFull_captcha("unfull_captcha.png")
    # print(image1.load()[12,25])
    # 获取完整验证码图片image2
    image2 = get_full_captcha("full_captcha.png")
    # 对比上述图片像素点,获取缺口位置,得到偏移距离
    distance = get_quekou_distance(image1, image2)
    print("缺口偏移量:", distance)
    # 获取滑块的移动轨迹
    track = get_track(distance)
    # 模拟人的行为,拖动滑块,完成验证
    slider = get_slider()
    move(slider, track)
    success = wait.until(EC.text_to_be_present_in_element((By.CLASS_NAME, "geetest_success_radar_tip_content"), "验证成功"))
    print(success)
    if success:
        login()
    else:
        main()

接下来,我们便来逐一完成main函数里要实现的功能了。

代码示例:
通过以上代码我们便拿到了完整的验证码和带有缺口的验证码。
缺口图片:

def get_unFull_captcha(name):
    """
    获取带缺口验证码图片
    :return: unfull captcha
    """
    top, bottom, left, right = get_captcha_position("geetest_canvas_slice")
    print("验证码1位置:", top, bottom, left, right)
    screenshot = get_screenshot()
    unfull_captcha = screenshot.crop((left, top, right, bottom)) # 按图片位置裁剪
    unfull_captcha.save(name)     # 这里传入的name要以xxx.png命名
    return unfull_captcha

完整图片:

def get_full_captcha(name):
    """
    获取完整验证码图片
    :return: full_captcha
    """
    # 这里要执行JavaScript脚本才能拿到完整图片的截图
    show_Full_img1= "document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="block""
    browser.execute_script(show_Full_img1)
    show_Full_img2 = "document.getElementsByClassName("geetest_canvas_fullbg")[0].style.opacity=1"
    browser.execute_script(show_Full_img2)
    # 等待完整图片加载
    time.sleep(2)
    top, bottom, left, right = get_captcha_position("geetest_canvas_fullbg")
    print("验证码2位置:", top, bottom, left, right)
    screenshot = get_screenshot()
    full_captcha = screenshot.crop((left, top, right, bottom))  # 同上
    full_captcha.save(name)
    return full_captcha

这里我在调试的时候碰到一个坑,因为chrome中,location方法不滚动,直接返回相对整个html的坐标,我的电脑是15.6寸的,显示设置上布局的缩放大小被放大到1.25倍,导致location返回的坐标与验证码的坐标有误差。修改布局为100%后就解决了。 下面便是对比图片找出缺口位置。这里我们需要遍历图片的坐标点,获取像素点的RGB数据。

代码示例

def get_quekou_distance(image1, image2):
    """
    对比像素点,获取缺口位置
    :param image1: 缺口图片
    :param image2: 完整图片
    :return: 缺口的偏移距离
    """
    # 缺口在滑块右侧,设定遍历初始横坐标left为59
    left = 60
    # 像素对比阈值
    threshold = 60

    for i in range(left, image2.size[0]):
        for j in range(image2.size[1]):
            rgb1 = image1.load()[i, j]
            rgb2 = image2.load()[i, j]

            res1 = abs(rgb2[0] - rgb1[0])
            res2 = abs(rgb2[1] - rgb1[1])
            res3 = abs(rgb2[2] - rgb1[2])
            if not (res1 < threshold and res2 < threshold and res3 < threshold):
                return i-7 # 返回缺口偏移距离,这里需测试几次

接下来就是获取滑块的移动路径和模拟拖动行为了。

执行代码:

def get_track(distance):
    """
    获取移动路径
    :param distance: 偏移量
    :return: track:移动轨迹
    """
    # 存放移动轨迹
    track = []
    # 当前位置
    current = 0
    # 设定加速段和减速段临界点为路径的3/4处
    mid = distance*4/5
    # 时间间隔time, 取0.2~0.3之间随机数,避免被网站识别出来
    t = random.randint(2, 3)/10
    # 初速度
    v = 0

    while current < distance:
        if current < mid:
            # 匀加速移动,加速度a
            a = 2
        else:
            a = -3
        # 初速度
        v0 = v
        # 当前速度
        v = v0 + a*t
        # 移动距离
        s = v0*t + 1/2 * a * t*t
        # 当前位移
        current += s
        # 加入到移动轨迹
        track.append(round(s))
    return track

def move(slider, track):
    """
    模拟鼠标操作,点击,移动滑块按钮
    :param: 滑块
    :param: 轨迹
    :return:
    """
    ActionChains(browser).click_and_hold(slider).perform()
    # 操作鼠标按轨迹移动
    for x in track:
        ActionChains(browser).move_by_offset(xoffset=x, yoffset=0).perform()
    time.sleep(0.3)
    # 松开
    ActionChains(browser).release().perform()

最后终于成功了,踩了这么多坑,终于完成了滑块验证码的破解。。。现在已经实现功能,因为还可能出现其他情况,接下来我们还需要完善一下代码,其实也可封装成一个类,测试的时候我们会发现,图片会弹出小怪兽被吃了,那是因为系统识别我们是机器行为,所以不通过,这里我们需要修改加速度参数,再增加一个回调。

这样我们就成功破解验证码,并登陆到网页界面了。。。忙活了一上午,吃饭去了。
好像现在极验官网改了, 但是滑动验证码思路基本上就是这样的...

源码地址:https://github.com/appleguardu/spider_projects/tree/master/Captcha

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/54803.html

相关文章

  • windows下简单验证识别——完美验证识别系统

    摘要:可惜收费的,今天要介绍的完美验证码识别系统是类似的免费产品。调用函数相当简单的,对比复杂的参数,这个识别是相当的快捷。 此文已由作者徐迪授权网易云社区发布。 欢迎访问网易云社区,了解更多网易技术产品运营经验。 讲到验证码识别,大家第一个可能想到tesseract。诚然,对于OCR而言,tesseract确实很强大,自带的字模能识别绝大多数规整的中英文。但是验证码毕竟不是OCR。对于现在...

    shleyZ 评论0 收藏0
  • 如何识别图片验证

    摘要:图片验证码是目前最常用的一种。神经网络以上验证码识别都依赖于字符切分,切分的好坏几乎直接决定识别的准确程度。目前验证码识别最先进的是谷歌在识别街景图像中门牌号码中使用的一套的算法。 全自动区分计算机和人类的图灵测试(Completely Automated Public Turing test to tell Computers and Humans Apart,简称CAPTCHA),...

    y1chuan 评论0 收藏0
  • node识别验证

    摘要:验证码的识别成功率跟图片质量关系密切,一般拿到后的验证码都得经过灰度化,二值化,去噪,利用就可以很方便的做到。 了解验证码 什么是验证码? 所谓验证码,就是将一串随机产生的数字或符号,生成一幅图片,图片里加上一些干扰象素(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证,验证成功后才能使用某项功能,通俗说就是一种区分用户是计算机和人的公共全自动程序 验证码的作用 可以...

    levy9527 评论0 收藏0
  • 为什么很多网站的验证都设置得肉眼都很难识别

    摘要:为了应付这种情况,很多网站加大验证码识别难度,复杂的验证码甚至让用户都很难识别了,这种方式劣势十分明显,糟糕的用户体验最终会让网站流失用户,这便是为什么有人吐槽网站的验证码的原因了。 欢迎访问网易云社区,了解更多网易技术产品运营经验。 首先来谈谈验证码的机制,验证码作为一种人机识别手段,其终极目的,就是区分正常人和机器的操作。而对于没有验证码的场景,比如用户登陆,则机器可以同时、大批量...

    lauren_liuling 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<