[Python] 01. pytesseract 驗證碼自動識別

 · 4 mins read

[10.31更新] 在爬某間公司的驗證碼發現,爬 html 中的圖片的 url,另開顯示的是"Access Denied"字樣,不同於之前爬蟲的平台是顯示驗證碼圖片本人啊!其原因是他的驗證碼是使用動態產生,後來研究之後解決方式是使用打 api 的方式,必須帶 cookie,回應的就會是驗證碼圖片了。(詳細教學在爬蟲篇在說明)

[前言碎念] 最進公司系統新增了登入驗證碼了功能,有了這個功能在自動化測試上就一定要破解它了!

此篇主要針對驗證碼辨識,如登入的驗證碼,為了防止被破解一般會增加噪點,干擾線,變形等方式,這些就是我們現在要解決的。




win7 開發環境 1

  • Python3.5
  • PIL

  • pytesseract

      $ sudo pip install pytesseract
    
  • tesseract-ocr

      下载安装:http://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-setup-3.05.00dev.exe 
      環境變數: path | C:\Program Files (x86)\Tesseract-OCR #安裝路徑
                  TESSDATA_PREFIX | C:\Program Files (x86)\Tesseract-OCR\tessdata
      $ tesseract --version #查看版本
    




Tesseract-OCR 介紹 1

由 Google 維護的開源 OCR(Optical Character Recognition,光學字符識別)。



程式範例

  • 識別下面這個驗證碼: ​

  • 編寫代碼

      import pytesseract
      from PIL import Image
        
      image = Image.open("code.png")
      code = pytesseract.image_to_string(image)
      print(code)
    
  • 這邊僅便是單純無變型,無干擾的驗證碼,一般來說辨識成功機率高。




基本流程 1 2

針對圖片的噪點,干擾線,變形做圖片處理辨識。

對於字符型驗證碼的識別流程如下:

  1. 原始圖片
  2. 圖片預處理
    • 2.1 讀取原始圖片素材
    • 2.2 二值化為黑白圖片
    • 2.3 去除背景干擾線
  3. 新增辨識白名單
  4. 進行辨識



1. 原始圖片

  • 有利識別的特點 :
    • 由純阿拉伯數字組成。
    • 字數為 4 位。
    • 字體是用的統一字體。
  • 不利識別的特點 :
    • 圖片背景有乾擾線。



2. 圖片預處理

此階段處理項目有:

  1. 讀取原始圖片素材。
  2. 二值化為黑白圖片。
  3. 去除背景干擾線。



2.1 讀取原始圖片素材

    img = Image.open("test.png").convert("L")



2.2 灰度處理二值化

  • 將原本為灰階的圖片轉為黑白的。

      def binarizing(img,threshold): #input: gray image
          pixdata = img.load()
          w, h = img.size
          for y in range(h):
              for x in range(w):
                  if pixdata[x, y] < threshold:
                      pixdata[x, y] = 0
                  else:
                      pixdata[x, y] = 255
          return img
    



2.3 去除背景干擾線 

  • 利用了點降噪和線降噪:一般噪點像素和周圍像素差別較大,使用遍歷像素,就是檢測這個點相鄰的四個點,判定這四個點中是白點的個數,假如有兩個以上的白色像素點,那麼就認為這個點是白色的,從而去除整個滋擾線。

      def depoint(img):   #input: gray image
          pixdata = img.load()
          w,h = img.size
          for y in range(1,h-1):
              for x in range(1,w-1):
                  count = 0
                  if pixdata[x,y-1] > 245:
                      count = count + 1
                  if pixdata[x,y+1] > 245:
                      count = count + 1
                  if pixdata[x-1,y] > 245:
                      count = count + 1
                  if pixdata[x+1,y] > 245:
                      count = count + 1
                  if count > 2:
                      pixdata[x,y] = 255
          #return img
          img.save("test.png","png")
    
  • 處理過後的圖片,可看到已經處理掉大部分的噪點了:



3. 新增辨識白名單

因為驗證碼只有數字,可以新增內容為 0123456789 的白名單。

  • 打開 tesseract 安裝目錄,進入 tessdata/configs/
  • 將 digits 複製一份,改名為:sfz
  • 打開文件 sfz 編輯內容,在 tessedit_char_whitelist 後面跟隨要識別的字符,如:

      tessedit_char_whitelist 0123456789X
    



4. 執行辨識

  • 加上參數 config 設定為 ‘-psm 7 sfz’

      import pytesseract
      from PIL import Image
        
      image = Image.open("../pic/c.png")
      card_no = tess.image_to_string(cardImage,config='-psm 7 sfz')
      print(card_no)
    




結論

那麼如果是以下這種驗證碼,需要key上前位加後位的總和去驗證,分析驗證碼的規則是"_+_",不一定數字還文字在前,白名單則可新增1~0 & 壹~零,經過辨識之後取得文字之後在進行加法並輸入。

以上使用 pytesseract 的辨識僅是透過像素點分析來達到辨識的效過,其結果非百分之百,甚至只有 60%,後續加上在進行驗證碼數字的分割,來進行機器學習,將在之後發表機器學習部分在進行說明。




ref:

  • https://blog.csdn.net/a349458532/article/details/51490291
  • https://segmentfault.com/a/1190000014091417
  • https://uhomework.com/a/Pythonjiaocheng/20171120/8558.html
  • https://www.jianshu.com/p/41127bf90ca9
  • https://my.oschina.net/u/2396236/blog/1621590
  • https://www.itread01.com/articles/1476089156.html