python實現圖文驗證碼識別


本文內容皆為作者原創,碼字不易,如需轉載,請注明出處:https://www.cnblogs.com/temari/p/13563429.html

 

一,驗證碼類別

以下為網站常見的驗證碼:

1.圖片驗證碼:常見的為英文、數字、漢字,計算題等類型的驗證碼。

2.行為式驗證碼: 常見的有滑動拼圖,文字點選,圖標點選,推理拼圖等類型的驗證碼。

3.手機短信驗證碼

4.語音驗證碼

二,web自動化驗證碼處理方法

我們在測試工作中,在測試登錄時經常會遇到需要注冊的場景,可以采取以下方式解決:

1.去掉驗證碼

這種方式最簡單,讓開發注釋掉驗證碼代碼即可。這種方法適用於在測試環境,但是在生產環境風險較大。

2.設置萬能的驗證碼

為了系統安全,我們可以采取不取消驗證碼,而是在程序中留一個“后門”,設置一個“萬能驗證碼”。只要輸入萬能驗證碼,程序就通過。

3.通過cookie繞過登錄

通過向瀏覽器中添加cookie可以繞過登錄的驗證碼,如記住密碼功能,默認登錄,自然就繞過了驗證碼。

4.驗證碼識別技術

現在市面上有很多第三方驗證碼識別平台,使用他們提供的識別工具,可以識別任何常規的驗證碼,但是大多驗證碼識別技術,識別率都很難達到100%。百度搜素驗證碼識別,可以看到多家驗證碼識別平台,如圖:

 

,圖形驗證碼識別實現案例

3.1  web自動化測試環境搭建

1.Python+PyCharm環境搭建

2.chromedriver安裝

3.Selenium安裝

4.pillow模塊安裝(處理圖像的庫)

3.2 驗證碼平台

1.注冊驗證碼平台:本案例使用超級鷹網站。

2.下載python示例代碼

 代碼保存到本地,如圖:

 

 

3.購買題分

驗證碼識別平台,不同的驗證碼類型有相應的價格,調用一次扣一次分值。使用前,要先給賬戶題分充值。我第一次運行代碼就是沒有注意這塊,導致調用幾次識別都為空,排查了很久才發現這個問題。超級鷹網站,初次綁定微信,可獲贈1000題分,這點比較友好。對於練習足夠用了。如圖:

 

 3.3  驗證碼識別思路
 
1.網站登錄頁面截屏保存,命名為a.png
2.使用Xpath定位驗證碼圖片元素
3.獲取驗證碼圖片元素在屏幕中的坐標
4.根據驗證碼的坐標將驗證碼圖片從登錄截屏圖片a.png中截取出來保存,命名為b.png
5.使用第三方驗證碼識別技術,讀取驗證碼圖片內容
 
3.4 涉及函數
 
1.截圖函數
 def get_screenshot_as_file(self, filename):
      """
      Saves a screenshot of the current window to a PNG image file. Returns
      False if there is any IOError, else returns True. Use full paths in
      your filename.

      :Args:
       - filename: The full path you wish to save your screenshot to. This
       should end with a `.png` extension.
         
      :Usage:
      driver.get_screenshot_as_file('/Screenshots/foo.png')
      """

2.獲取圖片坐標函數

(1)函數定義

 def rect(self):
     """A dictionary with the size and location of the element."""
     if self._w3c:
           return self._execute(Command.GET_ELEMENT_RECT)['value']
      else:
           rect = self.size.copy()
           rect.update(self.location)
           return rect

(2)函數作用

rect屬性返回一個矩形對象的寬度、高度,及左上角的橫坐標、縱坐標。以超級鷹登錄頁面為例,屏幕左上角為原點,X軸和Y軸方式如圖所示,獲取驗證碼的rect屬性,返回驗證碼圖片高度,寬度和左上角的坐標。

 

3.截取圖片函數
 
(1)函數定義
 
 def crop(self, box=None):
      """
      Returns a rectangular region from this image. The box is a
      4-tuple defining the left, upper, right, and lower pixel
      coordinate. See :ref:`coordinate-system`.

      Note: Prior to Pillow 3.4.0, this was a lazy operation.

      :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
      :rtype: :py:class:`~PIL.Image.Image`
      :returns: An :py:class:`~PIL.Image.Image` object.
      """

(2)函數作用

 截取一個矩形區域,參數為截圖對象在整個對象中的左、上、右和下的坐標。以超級鷹網站驗證碼示例,驗證碼的(left, upper, right, lower)=(x,y,x+width,y+height)。我理解的這個函數的截取操作,是截取四條直線的交叉部分,四條直線分別為x1=x,x2=x+width,y1=y,y2=y+height,如圖藍色區域:

 

4.第三方驗證碼識別函數
 
把第三方下載的函數,案例里是chaojiying.py,放到與驗證碼代碼VerificationCode.py同層目錄下,如圖:

5.價格體系

超級鷹可以識別英文、數字、漢字、坐標、選擇等任何類型的驗證碼。不同類型的驗證碼題分不一樣,調用識別函數時要傳驗證碼類型。調用前明確驗證碼類型代碼。

 

 

 

 3.5 完整代碼

VerificationCode.py

from selenium import webdriver
from PIL import Image
from chaojiying import Chaojiying_Client
from time import sleep

""" 
代碼功能:驗證碼識別
作者:檸檬草不孤單
Date:2020/08/06 20:25
驗證碼識別思路:登錄頁面截屏,使用Xpath定位驗證碼圖片元素,使用rect屬性獲取驗證碼圖片元素的長,寬及在屏幕中的坐標,計算出驗證碼圖片上下左右四個方位的坐標,
從登錄截屏圖片中將驗證碼圖片截取出來另存,然后使用第三方驗證碼識別技術,操作驗證碼圖片,讀取驗證碼內容。
注意事項:
1.計算坐標時,要注意屏幕的縮放設置,如屏幕按照150%縮放,計算坐標要乘以1.5
2.使用第三方驗證碼平台,賬戶題分需要充值,確保余額滿足驗證碼官方單價題分
"""
driver=webdriver.Chrome()
#隱式等待
driver.implicitly_wait(10)
driver.get("http://www.chaojiying.com/user/login/")
#窗口最大化
driver.maximize_window()
#login=driver.find_element_by_xpath("/html/body/div[2]/div/ul/li[7]/a").click()
driver.find_element_by_xpath("//div[@class='login_form']/form/p[1]/input").clear()
#輸入用戶名
username=driver.find_element_by_xpath("//div[@class='login_form']/form/p[1]/input").send_keys("xxxx")
#輸入密碼
password=driver.find_element_by_xpath("//div[@class='login_form']/form/p[2]/input").send_keys("xxxx")

#截屏
driver.get_screenshot_as_file("register.png")
VerficationCode=driver.find_element_by_xpath("//div[@class='login_form']/form/div[1]/img")
#返回一個坐標字典,獲取驗證碼長和寬,驗證碼左上角的坐標位置
location=VerficationCode.rect
print(location)
#計算驗證碼圖片四個方位的坐標
left=location['x']*1.5
top=location['y']*1.5
bottom=(location['y']+location['height'])*1.5
right=(location['x']+location['width'])*1.5
#驗證碼的位置:左,上,右,下
CodeLocation=(left,top,right,bottom)
print(CodeLocation)
#打開圖片
Page=Image.open("register.png")
#根據坐標位置切割出驗證碼圖片,並保存
image=Page.crop(CodeLocation)
image.save("code.png")
#調用驗證碼識別函數
#用戶中心>>軟件ID 生成一個替換
chaojiying = Chaojiying_Client('xxxx', 'xxxx', '907004')
#本地圖片文件路徑
im = open("C:/Users/xiaoy/PycharmProjects/VerificationCode/code.png", 'rb').read()
#點擊官方網站>>價格體系,查看驗證碼類型
result=chaojiying.PostPic(im,1004)
print(result)
print (result.get('pic_str'))
sleep(5)
driver.find_element_by_xpath("//div[@class='login_form']/form/p[3]/input").send_keys(result.get('pic_str'))
driver.find_element_by_xpath("//div[@class='login_form']/form/p[4]/input").click()

chaojiying.py

#!/usr/bin/env python
# coding:utf-8

import requests
from hashlib import md5

class Chaojiying_Client(object):

    def __init__(self, username, password, soft_id):
        self.username = username
        password =  password.encode('utf8')
        self.password = md5(password).hexdigest()
        self.soft_id = soft_id
        self.base_params = {
            'user': self.username,
            'pass2': self.password,
            'softid': self.soft_id,
        }
        self.headers = {
            'Connection': 'Keep-Alive',
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
        }

    def PostPic(self, im, codetype):
        """
        im: 圖片字節
        codetype: 題目類型 參考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
        }
        params.update(self.base_params)
        files = {'userfile': ('ccc.jpg', im)}
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
        return r.json()

    def ReportError(self, im_id):
        """
        im_id:報錯題目的圖片ID
        """
        params = {
            'id': im_id,
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
        return r.json()

if __name__ == '__main__':
    chaojiying = Chaojiying_Client('超級鷹用戶名', '超級鷹用戶名的密碼', '96001')    #用戶中心>>軟件ID 生成一個替換 96001
    im = open('a.jpg', 'rb').read()                                                    #本地圖片文件路徑 來替換 a.jpg 有時WIN系統須要//
    print (chaojiying.PostPic(im, 1902))                                            #1902 驗證碼類型  官方網站>>價格體系 3.4+版 print 后要加()

 

 3.6 注意事項
 
1.計算驗證碼圖片坐標時,注意屏幕縮放設置,如屏幕按照150%縮放,計算坐標要乘以1.5。如圖:
 
 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM