• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    爬虫Python验证码识别入门

    爬虫Python验证码识别

    前言:

    二值化、普通降噪、8邻域降噪
    tesseract、tesserocr、PIL
    参考文献--代码地址:https://github.com/liguobao/python-verify-code-ocr

     1、批量下载验证码图片

    import shutil
    import requests
    from loguru import logger
    
    for i in range(100):
        url = 'http://xxxx/create/validate/image'
        response = requests.get(url, stream=True)
        with open(f'./imgs/{i}.png', 'wb') as out_file:
            response.raw.decode_content = True
            shutil.copyfileobj(response.raw, out_file)
            logger.info(f"download {i}.png successfully.")
        del response
     
     
    

    2、识别代码看看效果

    from PIL import Image
    import tesserocr
    img = Image.open("./imgs/98.png")
    img.show()
    img_l = img.convert("L")# 灰阶图
    img_l.show()
    verify_code1 = tesserocr.image_to_text(img)
    verify_code2 = tesserocr.image_to_text(img_l)
    print(f"verify_code1:{verify_code1}")
    print(f"verify_code2:{verify_code2}")
     

    毫无疑问,无论是原图还是灰阶图,一无所有。

     3、折腾降噪、去干扰

    Python图片验证码降噪 - 8邻域降噪

    from PIL import Image
    # https://www.cnblogs.com/jhao/p/10345853.html Python图片验证码降噪 — 8邻域降噪
    
     
    def noise_remove_pil(image_name, k):
        """
        8邻域降噪
        Args:
            image_name: 图片文件命名
            k: 判断阈值
        Returns:
        """
    
        def calculate_noise_count(img_obj, w, h):
            """
            计算邻域非白色的个数
            Args:
                img_obj: img obj
                w: width
                h: height
            Returns:
                count (int)
            """
            count = 0
            width, height = img_obj.size
            for _w_ in [w - 1, w, w + 1]:
                for _h_ in [h - 1, h, h + 1]:
                    if _w_ > width - 1:
                        continue
                    if _h_ > height - 1:
                        continue
                    if _w_ == w and _h_ == h:
                        continue
                    if img_obj.getpixel((_w_, _h_))  230:  # 这里因为是灰度图像,设置小于230为非白色
                        count += 1
            return count
    
        img = Image.open(image_name)
        # 灰度
        gray_img = img.convert('L')
    
        w, h = gray_img.size
        for _w in range(w):
            for _h in range(h):
                if _w == 0 or _h == 0:
                    gray_img.putpixel((_w, _h), 255)
                    continue
                # 计算邻域非白色的个数
                pixel = gray_img.getpixel((_w, _h))
                if pixel == 255:
                    continue
    
                if calculate_noise_count(gray_img, _w, _h)  k:
                    gray_img.putpixel((_w, _h), 255)
        return gray_img
    
    
    if __name__ == '__main__':
        image = noise_remove_pil("./imgs/1.png", 4)
        image.show()
     
    
    

    看下图效果:

    这样差不多了,不过还可以提升

    提升新思路:

    这边的干扰线是从某个点发出来的红色线条,

    其实我只需要把红色的像素点都干掉,这个线条也会被去掉。

    from PIL import Image
    import tesserocr
    img = Image.open("./imgs/98.png")
    img.show()
    
    # 尝试去掉红像素点
    w, h = img.size
    for _w in range(w):
        for _h in range(h):
            o_pixel = img.getpixel((_w, _h))
            if o_pixel == (255, 0, 0):
                img.putpixel((_w, _h), (255, 255, 255))
    img.show()
    
    img_l = img.convert("L")
    # img_l.show()
    verify_code1 = tesserocr.image_to_text(img)
    verify_code2 = tesserocr.image_to_text(img_l)
    print(f"verify_code1:{verify_code1}")
    print(f"verify_code2:{verify_code2}")
    
    

    看起来OK,上面还有零星的蓝色像素掉,也可以用同样的方法一起去掉。

    甚至OCR都直接出效果了
    好了,完结撒花。
    不过,后面发现,有些红色线段和蓝色点,是和验证码重合的。
    这个时候,如果直接填成白色,就容易把字母切开,导致识别效果变差。
    当前点是红色或者蓝色,判断周围点是不是超过两个像素点是黑色。
    是,填充为黑色。
    否,填充成白色。

    最终完整代码:

    from PIL import Image
    import tesserocr
    from loguru import logger
    
    
    class VerfyCodeOCR():
        def __init__(self) -> None:
            pass
    
        def ocr(self, img):
            """ 验证码OCR
    
            Args:
                img (img): imgObject/imgPath
    
            Returns:
                [string]: 识别结果
            """
            img_obj = Image.open(img) if type(img) == str else img
            self._remove_pil(img_obj)
            verify_code = tesserocr.image_to_text(img_obj)
            return verify_code.replace("\n", "").strip()
    
        def _get_p_black_count(self, img: Image, _w: int, _h: int):
            """ 获取当前位置周围像素点中黑色元素的个数
    
            Args:
                img (img): 图像信息
                _w (int): w坐标
                _h (int): h坐标
    
            Returns:
                int: 个数
            """
            w, h = img.size
            p_round_items = []
            # 超过了横纵坐标
            if _w == 0 or _w == w-1 or 0 == _h or _h == h-1:
                return 0
            p_round_items = [img.getpixel(
                (_w, _h-1)), img.getpixel((_w, _h+1)), img.getpixel((_w-1, _h)), img.getpixel((_w+1, _h))]
            p_black_count = 0
            for p_item in p_round_items:
                if p_item == (0, 0, 0):
                    p_black_count = p_black_count+1
            return p_black_count
    
        def _remove_pil(self, img: Image):
            """清理干扰识别的线条和噪点
    
            Args:
                img (img): 图像对象
    
            Returns:
                [img]: 被清理过的图像对象
            """
            w, h = img.size
            for _w in range(w):
                for _h in range(h):
                    o_pixel = img.getpixel((_w, _h))
                    # 当前像素点是红色(线段) 或者 绿色(噪点)
                    if o_pixel == (255, 0, 0) or o_pixel == (0, 0, 255):
                        # 周围黑色数量大于2,则把当前像素点填成黑色;否则用白色覆盖
                        p_black_count = self._get_p_black_count(img, _w, _h)
                        if p_black_count >= 2:
                            img.putpixel((_w, _h), (0, 0, 0))
                        else:
                            img.putpixel((_w, _h), (255, 255, 255))
    
            logger.info(f"_remove_pil finish.")
            # img.show()
            return img
    
    
    if __name__ == '__main__':
        verfyCodeOCR = VerfyCodeOCR()
        img_path = "./imgs/51.png"
        img= Image.open(img_path)
        img.show()
        ocr_result = verfyCodeOCR.ocr(img)
        img.show()
        logger.info(ocr_result)
    
    


    到此这篇关于爬虫Python验证码识别入门的文章就介绍到这了,更多相关Python验证码识别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • 关于python爬虫应用urllib库作用分析
    • python爬虫Scrapy框架:媒体管道原理学习分析
    • python爬虫Mitmproxy安装使用学习笔记
    • Python爬虫和反爬技术过程详解
    • python爬虫之Appium爬取手机App数据及模拟用户手势
    • Python爬虫技术
    • Python爬虫爬取商品失败处理方法
    • Python获取江苏疫情实时数据及爬虫分析
    • Python爬虫之Scrapy环境搭建案例教程
    • Python爬虫中urllib3与urllib的区别是什么
    • 教你如何利用python3爬虫爬取漫画岛-非人哉漫画
    • Python爬虫分析汇总
    上一篇:python爬虫竟然被小伙用来算命
    下一篇:Python音乐爬虫完美绕过反爬
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    爬虫Python验证码识别入门 爬虫,Python,验证,码,识别,