前言:本篇主要记录在项目登录过程中验证码的问题,基于pytesseract和PIL组件实现简单的验证码图片识别;需要自行配置pytesseract,PIL环境。

目标:获取验证码、自动输入实现登录

一、截取验证码图片信息并保存

访问目标界面,截取全屏后,对验证码图片元素定位,获取元素的坐标数据,比如元素高、宽。精确截图获取验证码图片信息。

—代码展示

# 1访问界面
    url = '#手动打码#'
    driver = webdriver.Chrome()
    driver.get(url)
    # 2调整页面屏幕分辨率
    driver.execute_script('document.body.style.zoom="0.8"')
    time.sleep(2)
    # 验证码截取、保存
    img = driver.find_element(By.ID, 'randImage')  # 要截图的元素
    x, y = img.location.values()  # 元素 坐标数据
    h, w = img.size.values()  # 元素高宽
    # 将截图以二进制的形式返回
    img_data = driver.get_screenshot_as_png()
    # 以新图片的形式打开返回的数据
    sreenshots = Image.open(BytesIO(img_data))
    # 对截图进行剪切
    result = sreenshots.crop((x, y, x + w, y + h))  # 元素大小放缩
    # 存储
    imgpath = 'D:\\picture\\' + "001.png"
    result.save(imgpath)

—效果展示

python自动登录telnet Python自动登录验证码_验证码

二、识别验证码图片,获取代码

读取存储的图片信息,获取验证码。对图片进行两步处理:转化成灰度,二值化处理;经过处理的图片便于识别。

—代码展示

im= Image.open("D:\\picture\\001.png")
    #1.转化成灰度
    imgry = im.convert('L')
    #imgry.show()
    threshold = 101  # 140 这里需要自行调整,如果不能打印验证码自行调整
    table = []
    #2.二值化处理
    for i in range(256):
        if i < threshold:
            table.append(0)
        else:
            table.append(1)
    out = imgry.point(table, '1')
    out.show()
    #3.识别验证码
    code = pytesseract.image_to_string(out)
    print("验证码拿来吧->", code)

—效果展示

python自动登录telnet Python自动登录验证码_selenium_02

三、完整的示例

本示例将图片截取,验证码的识别分别进行了封装实现,使代码更加一目了然,功能点分明,助于后续的展开式使用。

—代码展示

from selenium import webdriver
from selenium.webdriver.common.by import By
from PIL import  Image
from io import BytesIO
import pytesseract
import time

## 截取验证码,保存
def img_save(img,driver):
    x, y = img.location.values()  # 元素 坐标数据
    h, w = img.size.values()  # 元素高宽
    # 将截图以二进制的形式返回
    img_data = driver.get_screenshot_as_png()
    # 以新图片的形式打开返回的数据
    sreenshots = Image.open(BytesIO(img_data))
    # 对截图进行剪切
    result = sreenshots.crop((x, y, x + w, y + h))  # 元素大小放缩
    # 存储
    imgpath = 'D:\\picture\\' + "003.png"
    result.save(imgpath)
    return imgpath

##识别验证码图片,获取代码
def get_imgCode(imgpath):
    im = Image.open(imgpath)
    #1.转化成灰度
    imgry = im.convert('L')
    threshold = 101.5  # 140
    table = []
    #2.二值化处理
    for i in range(256):
        if i < threshold:
            table.append(0)
        else:
            table.append(1)
    out = imgry.point(table, '1')
    out.show()
    #3.识别验证码
    code = pytesseract.image_to_string(out)
    return code

if __name__ == '__main__':

    # 1访问界面
    url = '#手动打码#'
    driver = webdriver.Chrome()
    driver.get(url)
    # 2调整页面屏幕分辨率
    driver.execute_script('document.body.style.zoom="0.8"')
    time.sleep(2)
    # 验证码截取、保存
    img = driver.find_element(By.ID, 'randImage')  # 要截图的元素
    imgpath = img_save(img,driver)
    code =  get_imgCode(imgpath)
    print("验证码拿来吧->", code)
    # 退出浏览器
    driver.quit()

小彩蛋

问题:无法正确截取验证码的位置

原因:本身笔记本放缩到125%,浏览器需要回滚到100%的缩放

解决:添加屏幕调节函数execute_script(N),其中系数N的计算方式是 原放缩比例*N=100%,比如当前的放缩为200%,则N为0.5

代码:

#1访问界面
    url = '#手动打码#'
    driver = webdriver.Chrome()
    driver.get(url)
    #2调整页面屏幕分辨率
    driver.execute_script('document.body.style.zoom="0.8"')
    time.sleep(2)
    #验证码截取、保存
    img = driver.find_element(By.ID, 'randImage')   # 要截图的元素
    x, y = img.location.values()      # 元素 坐标数据
    h, w = img.size.values()    # 元素高宽
    # 将截图以二进制的形式返回
    img_data = driver.get_screenshot_as_png()
    # 以新图片的形式打开返回的数据
    sreenshots = Image.open(BytesIO(img_data))
    # 对截图进行剪切
    result = sreenshots.crop((x, y, x + w, y + h))  # 元素大小放缩
    # 存储
    imgpath = 'D:' + '\\picture\\' + "003.png"
    result.save(imgpath)