当前位置:   article > 正文

python 对动态验证码、滑动验证码的降噪和识别

动态验证码

目录

一、动态验证码 

二、滑动验证码

三、验证码的降噪

四、验证码的识别


一、动态验证码 

  • 动态验证码是服务端生成的,点击一次,就会更换一次,这就会造成很多人在识别的时候,会发现验证码一直过期
  • 这是因为,如果你是把图片下载下来,进行识别的话,其实在下载的这个请求中,其实相当于点击了一次,这个验证码的内容已经被更换了
  • 最好的方法是,打开这个页面后,将页面进行截图,然后定位到验证码的位置,将验证码从截图上面裁剪下来进行识别,这样就不会造成多次请求,验证码更换的情况了

  1. from selenium import webdriver
  2. from PIL import Image
  3. # 实例化浏览器
  4. driver = webdriver.Chrome()
  5. # 最大化窗口
  6. driver.maximize_window()
  7. # 打开登陆页面
  8. driver.get(# 你的url地址)
  9. # 保存页面截图
  10. driver.get_screenshot_as_file('./screen.png')
  11. # 定位验证码的位置
  12. location = driver.find_element_by_id('login_yzm_img').location
  13. size = driver.find_element_by_id('login_yzm_img').size
  14. left = location['x']
  15. top = location['y']
  16. right = location['x'] + size['width']
  17. bottom = location['y'] + size['height']
  18. # 裁剪保存
  19. img = Image.open('./screen.png').crop((left,top,right,bottom))
  20. img.save('./code.png')
  21. driver.quit()

二、滑动验证码

  • 滑动验证码,通常是两个滑块图片,将小图片滑动到大图片上的缺口位置,进行重合,即可通过验证
  • 对于滑动验证码,我们就要识别大图上面的缺口位置,然后让小滑块滑动响应的位置距离,即可
  • 而为了让你滑动起来,更加的拟人化,你需要一个滑动的路径,模拟人为去滑动,而不是机器去滑动

  1. # 下载两个滑块
  2. bg = self.driver.find_element_by_xpath('//*[@id="captcha_container"]/div/div[2]/img[1]').get_attribute('src')
  3. slider = self.driver.find_element_by_xpath('//*[@id="captcha_container"]/div/div[2]/img[2]').get_attribute('src')
  4. request.urlretrieve(bg, os.getcwd() + '/bg.png')
  5. request.urlretrieve(slider, os.getcwd() + '/slider.png')
  6. # 获取两个滑块偏移量方法
  7. def getGap(self, sliderImage, bgImage):
  8. '''
  9. Get the gap distance
  10. :param sliderImage: the image of slider
  11. :param bgImage: the image of background
  12. :return: int
  13. '''
  14. bgImageInfo = cv2.imread(bgImage, 0)
  15. bgWidth, bgHeight = bgImageInfo.shape[::-1]
  16. bgRgb = cv2.imread(bgImage)
  17. bgGray = cv2.cvtColor(bgRgb, cv2.COLOR_BGR2GRAY)
  18. slider = cv2.imread(sliderImage, 0)
  19. sliderWidth, sliderHeight = slider.shape[::-1]
  20. res = cv2.matchTemplate(bgGray, slider, cv2.TM_CCOEFF)
  21. a, b, c, d = cv2.minMaxLoc(res)
  22. # print(a,b,c,d)
  23. # 正常如下即可
  24. # return c[0] if abs(a) >= abs(b) else d[0]
  25. # 但是头条显示验证码的框跟验证码本身的像素不一致,所以需要根据比例计算
  26. if abs(a) >= abs(b):
  27. return c[0] * bgWidth / (bgWidth - sliderWidth)
  28. else:
  29. return d[0] * bgWidth / (bgWidth - sliderWidth)
  30. # 移动路径方法
  31. def getTrack(self, distance):
  32. '''
  33. Get the track by the distance
  34. :param distance: the distance of gap
  35. :return: list
  36. '''
  37. # 移动轨迹
  38. track = []
  39. # 当前位移
  40. current = 0
  41. # 减速阈值
  42. mid = distance * 4 / 5
  43. # 计算间隔
  44. t = 0.2
  45. # 初速度
  46. v = 0
  47. while current < distance:
  48. if current < mid:
  49. # 加速度为正2
  50. a = 2
  51. else:
  52. # 加速度为负3
  53. a = -3
  54. # 初速度v0
  55. v0 = v
  56. # 当前速度v = v0 + at
  57. v = v0 + a * t
  58. # 移动距离x = v0t + 1/2 * a * t^2
  59. move = v0 * t + 1 / 2 * a * t * t
  60. # 当前位移
  61. current += move
  62. # 加入轨迹
  63. track.append(round(move))
  64. return track
  65. # 滑动到缺口位置
  66. def moveToGap(self, track):
  67. '''
  68. Drag the mouse to gap
  69. :param track: the track of mouse
  70. :return: None
  71. '''
  72. ActionChains(self.driver).click_and_hold(self.driver.find_element_by_xpath('//*[@id="captcha_container"]/div/div[3]/div[2]/div[2]/div')).perform()
  73. while track:
  74. x = random.choice(track)
  75. ActionChains(self.driver).move_by_offset(xoffset=x, yoffset=0).perform()
  76. track.remove(x)
  77. time.sleep(0.5)
  78. ActionChains(self.driver).release().perform()

三、验证码的降噪

  • 验证码的降噪,只是为了处理验证码图像上的多余的线条和干扰线,让你后期识别更加的准确,提高识别的准确度
  • 第一步:可以进行灰度转化

  1. img = cv2.imread('yzm.png')
  2. # 将图片灰度化处理,降维,加权进行灰度化c
  3. gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  4. cv2.imshow('min_gray',gray)
  5. cv2.waitKey(0)
  6. cv2.destroyAllWindows()
  • 第二步: 二值化处理

  1. import cv2
  2. img = cv2.imread('yzm.png')
  3. # 将图片灰度化处理,降维,加权进行灰度化c
  4. gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  5. t,gray2 = cv2.threshold(gray,220,255,cv2.THRESH_BINARY)
  6. cv2.imshow('threshold',gray2)
  7. cv2.waitKey(0)
  8. cv2.destroyAllWindows()
  •  第三步:噪点过滤

  1. import cv2
  2. img = cv2.imread('yzm.png')
  3. # 将图片灰度化处理,降维,加权进行灰度化c
  4. gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  5. t,gray2 = cv2.threshold(gray,220,255,cv2.THRESH_BINARY)
  6. def remove_noise(img, k=4):
  7. img2 = img.copy()
  8. # img处理数据,k过滤条件
  9. w, h = img2.shape
  10. def get_neighbors(img3, r, c):
  11. count = 0
  12. for i in [r - 1, r, r + 1]:
  13. for j in [c - 1, c, c + 1]:
  14. if img3[i, j] > 10: # 纯白色
  15. count += 1
  16. return count
  17. # 两层for循环判断所有的点
  18. for x in range(w):
  19. for y in range(h):
  20. if x == 0 or y == 0 or x == w - 1 or y == h - 1:
  21. img2[x, y] = 255
  22. else:
  23. n = get_neighbors(img2, x, y) # 获取邻居数量,纯白色的邻居
  24. if n > k:
  25. img2[x, y] = 255
  26. return img2
  27. result = remove_noise(gray2)
  28. cv2.imshow('8neighbors', result)
  29. cv2.waitKey(0)
  30. cv2.destroyAllWindows()

四、验证码的识别

  • 通常我们会使用 tesserocr 识别验证码,但是这个库有很大的局限性,识别率低,即时降噪效果很好,有很少的线条,也会不准确,这种识别方式并不十分推荐

  • 所以我们一般会使用第三方的接口进行识别,比如阿里的图片识别、腾讯也都是有的

  • 这些第三方接口需要自己接入识别接口

  1. import tesserocr
  2. #识别降噪后的图片
  3. code = tesserocr.image_to_text(nrImg)
  4. #消除空白字符
  5. code.strip()
  6. #打印
  7. print(code)
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/527738
推荐阅读
相关标签
  

闽ICP备14008679号