python实现验证码识别

前言

大家在做自动化的过程中,应该遇到过登录,需要输入验证码的场景,一般的话,解决方案就是,需要后台的开发同学提供万能验证码,这样每次都麻烦开发也不是很好,所以,还是自己搞一下把!

一、图片识别

验证码识别,选择使用ddddocr这个开源库,优点:识别率高,使用简单方便,实现了多种验证码识别的方式。有兴趣的朋友可以自行前往github查看:https://github.com/sml2h3/ddddocr。
使用时别忘了安装一下:pip install ddddocr
数字以及字母的识别:

import ddddocr

ocr = ddddocr.DdddOcr()

with open("test.jpg", 'rb') as f:
    image = f.read()

res = ocr.classification(image)
print(res)

ok,最复杂的识别部分,有大佬的开源软件解决了,我们只需要拿到图片,就可以了。

1、获取app中验证码图片

此处一般是点击登录,会弹出验证码和输入框,此时我们想要获取验证码图片,拆解为两步:
1.截取整个页面的截图 ;2.截取出我们想要的验证码图片的图。
第一步很简单,直接调用:

driver.get_screenshot_as_file("你想要存储的路径")

第二步我们稍微麻烦一点,需要先获取验证码图片的元素信息,然后在获取验证码图片的x,y点以及宽高:

ele = driver.find_element(By.ID,'XXXXX')
x = ele.location['x']
y = ele.location['y']
width = x + ele.size['width']
height = y + ele.size['height']

最后,将它截取出来就好了:

img = Image.open("此处填写第一步全屏截图输出的路径")
img = im.crop((x, y, width, height))
print(x, y, width, height)
img.save("此处为验证码截图保存到的路径")

2、识别并填写验证码

我们可以将上面两补都封装到方法中,在放到一个公共的类中,想要使用的时候调用一下就好了。
大致过程为:
首先,调用第二步的方法,获取到验证码的截图;
其次,使用ddddocr,将验证码截图的路径传入ddddocr中进行识别
最后,将识别到的验证码,回填到你app验证码的输入栏
以上,大功告成!!!

import ddddocr
from PIL import Image


def use_ocr(img):
    ocr = ddddocr.DdddOcr()
    with open(img, 'rb') as f:
        image = f.read()
    res = ocr.classification(image)
    print(res)
    return res
    
def screenshot_by_element(driver, ele, screen_img_path, out_img_path):
	driver.get_screenshot_as_file(screen_img_path)
	x = ele.location['x']
	y = ele.location['y']
	width = x + ele.size['width']
	height = y + ele.size['height']
	img = Image.open(screen_img_path)
	img = img.crop((x, y, width, height))
	print(x, y, width, height)
	img.save(out_image_path)
*****************************实现代码大致如下*********************************
screen_img_path = "D:/screen/xxx.png"
out_img_path = "D:/out/xxx.png"
ele = driver.find_element(By.ID, 'XXXX')
screenshot_by_element(driver, ele, screen_img_path, out_img_path)
code = use_ocr(out_img_path)
验证码输入框元素.send_keys(code)

为了确保程序的稳定性,每步之间都要根据实际情况加上等待。

二、滑动验证码

ddddocr提供了丰富的验证码识别方式,下面介绍一下滑动识别:
github上的样例:
在这里插入图片描述

  slide = ddddocr.DdddOcr(det=False, ocr=False)

  with open('bg.jpg', 'rb') as f:
      target_bytes = f.read()
  
  with open('fullpage.jpg', 'rb') as f:
      background_bytes = f.read()
  
  img = cv2.imread("bg.jpg")
  
  res = slide.slide_comparison(target_bytes, background_bytes)

  print(res)

1.获取验证码的滑块图片以及背景图

滑动解锁,可以根据ddddocr获取滑块滑动到的位置坐标,那我们首先要做的就是获取滑块以及背景图 然后将图片保存到本地。在调用ocr方法获取返回值,滑动滑块即可。
老样子,我们还是将ocr代码,封装成方法,方便后面直接调用:

    def ocr_slide(slide_pic, bg_pic):
        """
        计算滑块滑动位置
        :param slide_pic:  滑块的路径
        :param bg_pic: 背景的路径
        :return: 移动到的坐标位置
        """
        det = ddddocr.DdddOcr(det=False, ocr=False)
        with open(slide_pic, 'rb') as f:
            target_bytes = f.read()
        with open(bg_pic, 'rb') as f:
        background_bytes = f.read()
        res = det.slide_match(target_bytes, background_bytes, simple_target=True)
        print(res.get("target"))
        return res

2.移动滑块

步骤1,返回图片需要滑动到凹槽的坐标点,使用
ActionChains(driver).drag_and_drop_by_offset()方法进行滑动滑块:

#将返回值赋值给x1,y1,x2,y2
x1, y1, x2, y2 = res.get("target")
#ele:拖动的滑块坐标,
ActionChains(driver).drag_and_drop_by_offset(source=ele, xoffset=(x1+x2)/2-(slide.size.get("width")/2), yoffset=0).perform()

perform千万别忘记写。

实际应用

因为没实际应用场景,我们现在选择一个web网站测试一下:https://www.geetest.com/adaptive-captcha-demo,

from time import sleep
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from common.utils import Utils
import re

driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.maximize_window()#窗口最大化
driver.get("https://www.geetest.com/adaptive-captcha-demo")

js = "window.scrollBy(0,130);"
driver.execute_script(js)
sleep(3)
bt = driver.find_element(By.XPATH, '//button[text()="滑动拼图验证"]')
ActionChains(driver).move_to_element(bt).click(bt).perform()

bt2 = driver.find_element(By.XPATH, '//div[@aria-label="点击按钮开始验证"]')
ActionChains(driver).move_to_element(bt2).click(bt2).perform()
sleep(5)
# 滑动验证码
#slide
slide = driver.find_element(By.XPATH, '//*[@id="captcha"]/div[2]/div[1]/div[4]/div[1]/div[2]/div/div/div[1]/div[1]/div[1]')
print(slide.size.get("width"))
slide_url = slide.get_attribute("style")
slide_url = re.findall(r'[(](.*?)[)]', slide_url)[0]
slide_url = eval(slide_url)
Utils.save_img_loc(slide_url, "D:/", "slide")
sleep(1)
#bg
bg = driver.find_element(By.XPATH, '//*[@id="captcha"]/div[2]/div[1]/div[4]/div[1]/div[2]/div/div/div[1]/div[2]')
bg_url = bg.get_attribute("style")
bg_url = re.findall(r'[(](.*?)[)]', bg_url)[0]
bg_url = eval(bg_url)
Utils.save_img_loc(bg_url, "D:/", "bg")
sleep(5)
res = Utils.ocr_slide("D:/slide.png", "D:/bg.png")
js = "window.scrollBy(0,130);"
driver.execute_script(js)
x1, y1, x2, y2 = res.get("target")
ele = driver.find_element(By.XPATH, '//*[@id="captcha"]/div[2]/div[1]/div[4]/div[1]/div[2]/div/div/div[2]/div/div[3]')
ActionChains(driver).drag_and_drop_by_offset(source=ele, xoffset=(x1+x2)/2-(slide.size.get("width")/2), yoffset=0).perform()

写的比较凌乱,未做整理,仅做记录~

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值