Selenium獲取動態圖片驗證碼

Selenium獲取動態圖片驗證碼

關於圖片驗證碼的文章,我想大家都有一定的了解了。

在我們做UI自動化的時候,經常會遇到圖片驗證碼的問題。

當開發不給咱們提供萬能驗證碼,或者測試第三方網站比如知乎的時候,我們就需要自己去識別驗證碼

OCR

OCR是一種影像文字識別的技術,例如圖中的驗證碼,我們用肉眼識別就是c5s3,但機器可不比咱們肉眼。所以我們要利用ocr技術,讓我們的Python腳本自動通過圖片識別出對應的文字

常見的識別類庫

在Python中其實有許多識別類庫,這裡只介紹部落客自己實踐過的成功率還不錯的: 百度ocr

簡單的說,就是百度提供了一個SDK,讓我們傳入圖片數據,從而拿到識別的結果。ocr的細節我們不需要關心。

申請開通OCR

首先我們得有一個百度帳號,這個相信大家都有,沒有的可以申請一個。

左上角展開->產品服務->文字識別

  • 創建應用

點擊創建應用按鈕

  • 填寫相關應用資訊

簡單描述下應用是幹嘛的就行,因為我們只需要識別文字,所以其他也不用勾上

創建好了之後可以看到具體的應用資訊,記住這3個關鍵資訊。待會會用到。

  • appid
  • apikey
  • secret key

熟悉OCR文檔

官方文檔地址: //cloud.baidu.com/doc/OCR/s/wkibizyjk

文檔會寫的比較清楚,簡單的說就是通過你的appid,api key和secret key獲取一個client,接著你就可以調用client的api去獲取圖片中的文字了。官方的SDK還是比較貼心的。

  • 安裝SDK
pip install baidu-aip

講完了文字怎麼識別,接著就來說說標題中的動態圖片驗證碼

動態圖片驗證碼

這個概念是我自己命名的,一般來說,我們的一張圖片都是對應唯一一個url的,比如:

//yuque.com?image=dshqadiau

(這個地址是我編的)

一般來說image欄位的值不同,圖片也就不同,都是一串隨機的或者規律的不重複數據,確保圖片不會重複

但是部落客最近遇到了這樣一種情況:

輸入一個url,每次輸入,拿到的圖片都不一樣。

這樣就會帶來一個很嚴重的問題,頁面上你雖然讀取了圖片的資訊。我們把圖片的url傳遞給百度sdk的時候,url由於再次調用,導致圖片發生了變化。

比如網站上顯示的是: c5s3,調用百度sdk的時候,百度會通過url讀取圖片,但再次讀取,圖片可能變成了lfew

不信大家可以看看這個圖片地址:

每次刷新,這個圖片都會變,但是url不變

怎麼解決呢?

好在百度sdk,他不僅僅支援url,還支援圖片文件和base64的圖片數據。我們看看官方文檔:

所以此時我們用圖片的base64數據就行了

再回到Selenium裡面,我們怎麼才能獲取到驗證碼那張圖片呢?

思考一下:

  1. 讀取img標籤的src,然後下載圖片,保存圖片文件再轉為base64

很顯然這個方法行不通,為什麼呢?

因為img的src屬性就是剛才這個url,你去獲取一遍url,它同樣會變化。

  1. 截圖,裁剪出驗證碼部分,扔給百度去識別

可行是可行,但是會不會太複雜了??

如果我只對驗證碼的img元素進行截圖,生成base64的數據是不是更方便?

其實呢,selenium作為一款老牌的自動化測試工具,很多方法供大於求了。所以它是有這樣的功能的!

Selenium對指定區域截圖

我們都知道,selenium有一些截圖方法。

driver.get_screenshot_as_file(filename)

但其實,針對元素,也是有截圖方法的。

偽程式碼如下:

# 通過id獲取到圖片
img = driver.find_element_by_id("image")
# 調用WebElement的screenshot_as_png屬性方法,獲取到png的數據,因為百度需要png
data = img.screenshot_as_png

接著我們就可以用這個獲取到的圖片數據去找百度要答案了!

完整版程式碼:

from aip import AipOcr 
from selenium import webdriver


client = AipOcr("你的appid", "你的app_key", "你的secret_key")
driver = webdriver.Chrome()
driver.get("//iam.pt.ouchn.cn/am/UI/Login")
img = driver.find_element_by_id("kaptchaImage")
data = img.screenshot_as_png

res = client.basicGeneral(data, {})
print(res)

更多圖片識別的配置可以查看度娘文檔哦

可以看到,只識別到了CFX,而且圖片沒有繼續變化了。

畢竟文字識別是從圖片裡面找文字,而且文字會有一些橫線這樣的干擾,所以如果一次不行,可以多試幾次。

思路就是寫一個while循環,不斷嘗試去識別驗證碼並登錄,接著判斷是否登錄成功,沒成功則重複上一個步驟

以我個人的經驗,一般1-10次就可以成功。

好了,以上是部落客簡單替大家嘗試一下UI自動化過程中對於驗證碼的識別。主要重點在於驗證碼的識別和對部分區域截圖。

有興趣的同學可以聯繫部落客探討哦。上一篇給點工們的進階教程好像漏發了一些人,這裡補發一下,希望大家都能夠取得進步!~

點工怎麼打怪升級為測開(記得收藏,看過的都賺到了)