vlambda博客
学习文章列表

验证码识别--封装版

这里是清安,前面我们说过了数字英文的验证码识别操作,本章我们对其进行完善一下,结合selenium来实际操作操作。

  
    
    
  
import os
import time


def coding_path(path):
    Base_Path = os.path.abspath(os.path.dirname(os.path.abspath(__file__)) +  '/..')
    Base_image = os.path.join(Base_Path +  r'\PIC', path)
     return Base_image


def time_():
     # %Y_%m_%d_%H_%M_%S
    file_name = time.strftime( "%Y_%m_%d_%H_%M") +  ".png"
     return file_name
首先先来写一个时间戳,你没看错,我想用时间戳来保存截图。至于coding_path就是一个相对路径,读取文件位置的一个函数。里面Base_Path是获取相对路径,Base_image是用的路径拼接的方式存放截图图片的。
接下来就是正文了

  
    
    
  
class Brouse:

         def __init__(self):
            self.fox = webdriver.Firefox()

         def save_image(self):
             """
            截图
            :return:
            """

           self.fox.save_screenshot(coding_path(time_()))

         def location_(self, loc):
             """
            :param loc:
            :return:获取图片位置
            """

            location = loc.location
             return location

         def location_size(self, loc):
             """
            :param loc:
            :return:获取图片大小
            """

            location_size = loc.size
             return location_size
这里我写的是类,里面写了各种方法。因为是结合selenium来写的,所以,这里我需要初始化驱动。至于为什么是火狐,这里我没做多的判断,各位自行更改成喜欢的就好。
里面我写了一个selenium截图的方法、获取图片位置的方法、以及获取图片大小的方法。并将后两者的值全部返回,至于为什么返回,后面用的到。一下往下看。

  
    
    
  
     def image_size(self, image):
             """截图验证码大小,根据实际修改"""
            rangle = (int(self.location_(image)[ 'x'] -  5), int(self.location_(image)[ 'y'] -  5),
                      int(self.location_(image)[ 'x'] + self.location_size(image)[ 'width'] +  11),
                      int(self.location_(image)[ 'y'] + self.location_size(image)[ 'height'] +  7))
             return rangle

         def crop_image(self):
             """
            :return: 识别截图验证码
            """

            ocr = DdddOcr()
            file_image = open(coding_path(time_()),  'rb')
            result = ocr.classification(file_image.read())
             return result

同样的,这两个方法我是写在了类中的,只是分开来写了。截取验证码这一块,根据不同的电脑尺寸来,以及现实所设置布局。所以这里需要自己做一部分调整。另外,此处也可以采用*一定的比例来进行截取,例如self.location_(image)['x'] * 1.25。
我们需要得到截取后的验证码图片,所以,我们这里也需要返回一个值。
接下来就是识别验证码了,上一篇讲过,但是这里的方法需要在后续才能展现用处,往下看。同样用的是二进制读取。并将读取的值进行返回。

  
    
    
  
     def eles_crop_image(self, ele, num):
             """
            元素组截图定位
            :param ele:
            :param num:
            :return:
            """

            pic = self.fox.find_elements_by_xpath(ele)[num]
            sleep( 1)
             # 保存截图,调用时间戳
            self.save_image()
             # 获取位置
            self.location_(pic)
             # 获取大小
            self.location_size(pic)
             # 确定所需要的图片大小
            self.image_size(pic)
             # 打开之前截图图片
            image = Image.open(coding_path(time_()))
             # 开始裁剪
            image1 = image.crop(self.image_size(pic))
             # 保存裁剪后的截图
            image1.save(coding_path(time_()))
             # 图片内容
            number = self.crop_image()
             while  1:
                 if len(number) <  3:
                    number = self.crop_image()
                     return number
                 break
             return number

这里我们就是用到了上述的识别验证码了。但是在这之前,需要怼图片进行一些处理,也就是上面写到了的裁剪,裁剪出属于验证码的那一部分。上述的注释写了哦,需要一步步来最后得到完整的验证码图片,并对它进行识别,返回识别的值。

  
    
    
  
     def Fox_test(self):
            self.fox.get( 'https://d2.shopxo.vip/admin.php?s=admin/logininfo.html')
            self.fox.find_element_by_xpath( "//input[@name='accounts']").send_keys( 'admin')
            self.fox.find_element_by_xpath( "//input[@name='pwd']").send_keys( 'shopxo')
            self.fox.find_element_by_xpath( "//input[@name='verify']").send_keys(
                self.eles_crop_image( "//span[@class='am-input-group-btn']"1))
            self.fox.find_element_by_xpath( "//*[text()='登录']").click()
            self.fox.close()


if __name__ ==  '__main__':
    Brouse().Fox_test()

此处就不用多说了吧,selenium基础,打开网址,定位元素,再加上调用方法传值,输入验证码,最后完成登录。
这里只写了元素组的方法,全部代码可参考:https://gitee.com/qinganan/OCR.git,在pro_pic_orc文件中。
此外,如果还有更好的方法,可以私信我,一起探讨。