验证码识别【1】

【学习笔记】----只做个人记录,以下内容中极验验证码部分实用性不大

  • 利用OCR技术识别图形验证码
  • 使用到tesserocr库,需要下载安装
  • 获取验证码的方式这里采用本地保存的方式,比较简便
    在这里插入图片描述

识别图形验证码

  • 识别测试代码:
import tesseror
from PIL import Image

image = Image.open('code.jpg')
result = tesseror.image_to_text(image)
# 另一个方法: tesseror.file_t_text('code.jpg')  效果没那么好
print(result)
  • 然而有时候识别并不是准确的,因此还需要将图片做额外的处理

    • 例如:转灰度、二值化等操作。。。
      • 二值化处理需要先将图片转灰度
  • 代码

image = image.convert('L')  # 传入参数L->转灰度
image = image.convert('1')  # 传入参数1->二值化处理(默认阈值127)

还能确定阈值

# 转灰度
image = image.convert('L')
# 阈值设置
threhold = 150  
# 还是需要根据图片来挑的可能,书中使用80,但缺失了一半内容

table = [0 if i < threhold else 1 for i in range(256) ]
image = image.point(table, '1')
image.show()

在这里插入图片描述

接下来只要使用一行代码就可以识别啦!

print(tesseror.image_to_text(image))

由于使用的python是3.8版本的,没有对应的包,便使用另外的tesseract代替了,搞了好久才搞明白。咳咳。以下是实验中的代码

from PIL import Image
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
image = Image.open('picture/code.jpg')

# 另一个方法: tesseror.file_t_text('code.jpg')  效果没那么好

# 转灰度
image = image.convert('L')
# 阈值设置
threhold = 107  # 可变阈值
table = [0 if i < threhold else 1 for i in range(256) ]  # 固定 256
image = image.point(table, '1')
image.show()
result = pytesseract.image_to_string(image)
print(result)

利用这个办法似乎还是无法很准确的将其识别出来。调了许多次参数,但没有正确识别bgll

在这里插入图片描述

极验验证(该部分代码只用来记录思路,代码不可用)

《Python3网络爬虫开发实战》中的一些内容似乎有些过时了,滑动验证码并没有提供缺口不存在的原图片。因此这个方法找不到对应的缺口位置。 这里也简单学习记录一下

==注:==现在的验证码图片都是由一小块一小块组成的,需要将所有图片的url收集下载并且重组才能得到最终的完整图片。而且这些url并没有在源代码中直接呈现出来T_T

在这里插入图片描述
在这里插入图片描述

  • 验证方式:滑动图片,使得图像完成即成功,失败得重来。

  • 特点:

    1. 多次验证:
      1. 首先点击智能验证
      2. 不通过就要进行滑动验证
      3. 最后形成三个加密参数形成表单提交后台进行验证
    2. 还增加了机器学习方法识别拖动轨迹
      • 防模拟
      • 防伪造
      • 防暴力
    3. 安全性和易用性高
  • 完成验证需要的3步

    class CrackGeetest(object):
        def __init__(self):
            self.url = 'xxxx'
            self.browser = webdriver.Chrome()
            self.wait = WebDriverWait(self.browser, 20)
            self.phoneNumber = phoneNumber
            self.pwd = pwd
    
    1. 点击模拟验证按钮

      • 这个使用selenium可以做到
      button = self.wait.until(EC.element_to_be_clickable((By.XPATH, "//xxx")))
      button.click()
      
    2. 识别模拟滑动缺口的位置

      • 获取验证码图片位置 -> 截图1(原图) -> 点击验证呼出缺口 -> 截图2(带缺口)
      """
      	这个方式是获取位置的
      """
      def get_position(self):
          # 获取图片信息
          img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img')))  
          time.sleep(2)
          location = img.location
          size = img.size
          top, bottom, left, right = 
          location['y'], location['y'] + size['height'],location['x'],location['x'] + size['width']
          return (top, bottom, left, right)  # 返回坐标元组
      
      """
      	这个方式是截图的
      """
      def get_screenshot(self):
          screenshot = self.browser.get_screenshot_as_png()  # 网页截图
          screenshot = Image.open(BytesIO(screenshot))
          return screenshot
      
      
      """
      	接着使用crop()进行裁剪,并且保存
      """
      capt_ = screenshot.crop((left, top, right, bottom))
      capt_.save('path/name')
      
      """
      	呼出缺口
      """
       def get_slider(self):
              """
              获取滑块
              :return: 滑块对象
              """
              slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button')))
              return slider
      # 加上一个方法包含 slider.click() 图片就是带有缺口的了,接下来进一步的截图,裁剪,保存
      
      """
      	比较图片中每一个像素点,看看同一位置的像素是否相同,需要判断RGB的绝对值是否都小于阈值。
      	不同就返回当前位置
      """
       def get_gap(self, image1, image2):
              left = 60  # 从60的位置也就是滑块右侧的位置
              for i in range(left, image1.size[0]):  # 行坐标
                  for j in range(image1.size[1]):  # 列坐标
                      if not self.is_pixel_equal(image1, image2, i, j):
                          left = i  # 找到不同的点,直接返回该点, 该点表示缺口左边坐标
                          return left
              return left
          
       def is_pixel_equal(self, image1, image2, x, y):
              """
              判断两个像素是否相同
              :param image1: 图片1
              :param image2: 图片2
              :param x: 位置x
              :param y: 位置y
              :return: 像素是否相同
              """
              # 取两个图片的像素点
              pixel1 = image1.load()[x, y]  # 该行列(该点)的RGB三通道数值
              pixel2 = image2.load()[x, y]  # 同上
              threshold = 60  # 阈值
              if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(
                      pixel1[2] - pixel2[2]) < threshold:  # 看绝对值
                  return True  # 在阈值之内表明该点相同,不是缺口
              else:
                  return False
      
    3. 滑动

      • 在模拟拖动的之前,需要考虑的是:人无法做到绝对的均匀速度滑动,在验证中,极验验证码利用机器学习模型筛选此类操作形成的数据为机器操作。因此需要利用变速运动公式进行模拟,这里采用匀变速运动(前段加速,后段减速,比较符合人的操作过程)。
      """
      根据偏移量获取移动轨迹
      :param distance: 偏移量, 缺口位置
      :return: 移动轨迹
      """
      def get_track(self, distance):
      
              # 移动轨迹
              track = []
              # 当前位移
              current = 0
              # 减速阈值,在最后的1/5的位置开始匀减速
              mid = distance * 4 / 5  
              # 计算间隔
              t = 0.2
              # 初速度
              v = 0
              
              while current < distance:
                  if current < mid:
                      # 加速度为正2
                      a = 2
                  else:
                      # 加速度为负3
                      a = -3
                  # 初速度v0  刚开始时0,后来的初速度是上0.2秒末尾的速度
                  v0 = v
                  # 当前速度v = v0 + at  加速
                  v = v0 + a * t
                  # 移动距离x = v0t + 1/2 * a * t^2
                  move = v0 * t + 1 / 2 * a * t * t  # 则是计算每0.2秒内行走的距离,初速度每次都变
                  # 当前位移
                  current += move  # 总位移是每次移动距离的叠加
                  # 加入轨迹
                  track.append(round(move))  #将每次移动距离计算为整数
              return track
      
      • 开始滑动
        • 利用在前两篇学习到的 动作链 进行拖动
      """
         拖动滑块到缺口处
         :param slider: 滑块
         :param track: 轨迹
         :return:
      """  
          def move_to_gap(self, slider, track):
      
              ActionChains(self.browser).click_and_hold(slider).perform()  # 在此网页 点击并按住 slider
              for x in track:  # 遍历轨迹
                  ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform()  # 每次都滑动到相应位置
              time.sleep(0.5)  
              ActionChains(self.browser).release().perform()  # 释放
      
# 这是crack 过程完整思路
    def crack(self):
        # 输入用户名密码
        self.open()
        # 点击验证按钮
        button = self.get_geetest_button()
        button.click()
        # 获取验证码图片
        image1 = self.get_geetest_image('captcha1.png')
        # 点按呼出缺口
        slider = self.get_slider()
        slider.click()
        # 获取带缺口的验证码图片
        image2 = self.get_geetest_image('captcha2.png')
        # 获取缺口位置
        gap = self.get_gap(image1, image2)
        print('缺口位置', gap)
        # 减去缺口位移
        gap -= BORDER
        # 获取移动轨迹
        track = self.get_track(gap)
        print('滑动轨迹', track)
        # 拖动滑块
        self.move_to_gap(slider, track)

        success = self.wait.until(
            EC.text_to_be_present_in_element((By.CLASS_NAME, 'geetest_success_radar_tip_content'), '验证成功'))
        print(success)

        # 失败后重试
        if not success:
            self.crack()
        else:
            self.login()

到此,基本的原理和代码就结束了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JamePrin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值