1. 程式人生 > >Tesseract:識別知乎網站登入驗證碼

Tesseract:識別知乎網站登入驗證碼

機器視覺

從 Google 的無人駕駛汽車到可以識別假鈔的自動售賣機,機器視覺一直都是一個應用廣 泛且具有深遠的影響和雄偉的願景的領域。

我們將重點介紹機器視覺的一個分支:文字識別,介紹如何用一些 Python庫來識別和使用線上圖片中的文字。

我們可以很輕鬆的閱讀圖片裡的文字,但是機器閱讀這些圖片就會非常困難,利用這種人類使用者可以正常讀取但是大多數機器人都沒法讀取的圖片,驗證碼 (CAPTCHA)就出現了。驗證碼讀取的難易程度也大不相同,有些驗證碼比其他的更加難讀。

將影象翻譯成文字一般被稱為光學文字識別(Optical Character Recognition, OCR)。可以實現OCR的底層庫並不多,目前很多庫都是使用共同的幾個底層 OCR 庫,或者是在上面 進行定製。

 

ORC庫概述

在讀取和處理影象、影象相關的機器學習以及建立影象等任務中,Python 一直都是非常出色的語言。雖然有很多庫可以進行影象處理,但在這裡我們只重點介紹:Tesseract

 

Tesseract

Tesseract 是一個 OCR 庫,目前由 Google 贊助(Google 也是一家以 OCR 和機器學習技術聞名於世的公司)。Tesseract 是目前公認最優秀、最精確的開源 OCR 系統。 除了極高的精確度,Tesseract 也具有很高的靈活性。它可以通過訓練識別出任何字型,也可以識別出任何 Unicode 字元。

安裝Tesseract

Windows 系統

下載可執行安裝檔案https://code.google.com/p/tesseract-ocr/downloads/list安裝。

Linux 系統

可以通過 apt-get 安裝: $sudo apt-get tesseract-ocr

Mac OS X系統

用 Homebrew(http://brew.sh/)等第三方庫可以很方便地安裝 brew install tesseract

要使用 Tesseract 的功能,比如後面的示例中訓練程式識別字母,要先在系統中設定一 個新的環境變數 $TESSDATA_PREFIX,讓 Tesseract 知道訓練的資料檔案儲存在哪裡,然後搞一份tessdata資料檔案,放到Tesseract目錄下。

在大多數 Linux 系統和 Mac OS X 系統上,你可以這麼設定:

 $export TESSDATA_PREFIX=/usr/local/share/Tesseract

在 Windows 系統上也類似,你可以通過下面這行命令設定環境變數:

 #setx TESSDATA_PREFIX C:\Program Files\Tesseract OCR\Tesseract

安裝pytesseract

Tesseract 是一個 Python 的命令列工具,不是通過 import 語句匯入的庫。安裝之後,要用 tesseract 命令在 Python 的外面執行,但我們可以通過 pip 安裝支援Python 版本的 Tesseract庫:

pip install pytesseract

 

Tesseract處理給規範的文字

你要處理的大多數文字都是比較乾淨、格式規範的。格式規範的文字通常可以滿足一些需求,不過究竟什麼是“格式混亂”,什麼算“格式規範”,確實因人而異。 通常,格式規範的文字

具有以下特點:

 

  • 使用一個標準字型(不包含手寫體、草書,或者十分“花哨的”字型) • 雖然被複印或拍照,字型還是很清晰,沒有多餘的痕跡或汙點
  • 排列整齊,沒有歪歪斜斜的字
  • 沒有超出圖片範圍,也沒有殘缺不全,或緊緊貼在圖片的邊緣
  • 文字的一些格式問題在圖片預處理時可以進行解決。例如,可以把圖片轉換成灰度圖,調 整亮度和對比度,還可以根據需要進行裁剪和旋轉(詳情請關注影象與訊號處理),但是,這些做法在進行更具擴充套件性的 訓練時會遇到一些限制。

 

格式規範文字的理想示例

 

 

程式碼實現

import pytesseract
from PIL import Image

image = Image.open('test.jpg')
text = pytesseract.image_to_string(image)
print text

 

執行結果:


This is some text, written in Arial, that will be read by
Tesseract. Here are some symbols: [email protected]#$%"&*()

 

 

Tesseract對模糊圖片進行閾值過濾和降噪處理

 

很多時候我們在網上會看到這樣的圖片:

Tesseract 不能完整處理這個圖片,主要是因為圖片背景色是漸變的,最終結果是這樣:

 

隨著背景色從左到右不斷加深,文字變得越來越難以識別,Tesseract 識別出的 每一行的最後幾個字元都是錯的。

遇到這類問題,可以先用 Python 指令碼對圖片進行清理。利用 Pillow 庫,我們可以建立一個 閾值過濾器來去掉漸變的背景色,只把文字留下來,從而讓圖片更加清晰,便於 Tesseract 讀取:

 

程式碼實現

from PIL import Image 
import subprocess

def cleanFile(filePath, newFilePath): 
    image = Image.open(filePath)

    # 對圖片進行閾值過濾,然後儲存
    image = image.point(lambda x: 0 if x<143 else 255)     
    image.save(newFilePath)

    # 呼叫系統的tesseract命令對圖片進行OCR識別     
    subprocess.call(["tesseract", newFilePath, "output"])

    # 開啟檔案讀取結果
    file = open("output.txt", 'r')     
    print(file.read()) 
    file.close()

cleanFile("text2.jpg", "text2clean.png")

 

執行結果:

通過一個閾值對前面的“模糊”圖片進行過濾的結果

除了一些標點符號不太清晰或丟失了,大部分文字都被讀出來了。Tesseract 給出了最好的 結果:

對知乎網驗證碼進行處理:

許多流行的內容管理系統即使加了驗證碼模組,其眾所周知的註冊頁面也經常會遭到網路 機器人的垃圾註冊。

那麼,這些網路機器人究,竟是怎麼做的呢?既然我們已經,可以成功地識別出儲存在電腦上 的驗證碼了,那麼如何才能實現一個全能的網路機器人呢?

大多數網站生成的驗證碼圖片都具有以下屬性。

 

  • 它們是伺服器端的程式動態生成的圖片。驗證碼圖片的 src 屬性可能和普通圖片不太一 樣,比如 <img src="WebForm.aspx?id=8AP85CQKE9TJ">,但是可以和其他圖片一樣進行 下載和處理。
  • 圖片的答案儲存在伺服器端的資料庫裡。
  • 很多驗證碼都有時間限制,如果你太長時間沒解決就會失效。
  • 常用的處理方法就是,首先把驗證碼圖片下載到硬盤裡,清理乾淨,然後用 Tesseract 處理 圖片,最後返回符合網站要求的識別結果。
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import requests
import time
import pytesseract
from PIL import Image
from bs4 import BeautifulSoup

def captcha(data):
    with open('captcha.jpg','wb') as fp:
        fp.write(data)
    time.sleep(1)
    image = Image.open("captcha.jpg")
    text = pytesseract.image_to_string(image)
    print "機器識別後的驗證碼為:" + text
    command = raw_input("請輸入Y表示同意使用,按其他鍵自行重新輸入:")
    if (command == "Y" or command == "y"):
        return text
    else:
        return raw_input('輸入驗證碼:')

def zhihuLogin(username,password):

    # 構建一個儲存Cookie值的session物件
    sessiona = requests.Session()
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0'}

    # 先獲取頁面資訊,找到需要POST的資料(並且已記錄當前頁面的Cookie)
    html = sessiona.get('https://www.zhihu.com/#signin', headers=headers).content

    # 找到 name 屬性值為 _xsrf 的input標籤,取出value裡的值
    _xsrf = BeautifulSoup(html ,'lxml').find('input', attrs={'name':'_xsrf'}).get('value')

    # 取出驗證碼,r後面的值是Unix時間戳,time.time()
    captcha_url = 'https://www.zhihu.com/captcha.gif?r=%d&type=login' % (time.time() * 1000)
    response = sessiona.get(captcha_url, headers = headers)


    data = {
        "_xsrf":_xsrf,
        "email":username,
        "password":password,
        "remember_me":True,
        "captcha": captcha(response.content)
    }

    response = sessiona.post('https://www.zhihu.com/login/email', data = data, headers=headers)
    print response.text

    response = sessiona.get('https://www.zhihu.com/people/maozhaojun/activities', headers=headers)
    print response.text


if __name__ == "__main__":
    #username = raw_input("username")
    #password = raw_input("password")
    zhihuLogin('[email protected]','ALAxxxxIME')

 

值得注意的是,有兩種異常情況會導致這個程式執行失敗。第一種情況是,如果 Tesseract 從驗證碼圖片中識別的結果不是四個字元(因為訓練樣本中驗證碼的所有有效答案都必須 是四個字元),結果不會被提交,程式失敗。第二種情況是雖然識別的結果是四個字元, 被提交到了表單,但是伺服器對結果不認可,程式仍然失敗。

在實際執行過程中,第一種 情況發生的可能性大約為 50%,發生時程式不會向表單提交,程式直接結束並提示驗證碼 識別錯誤。第二種異常情況發生的概率約為 20%,四個字元都對的概率約是 30%(每個字 母的識別正確率大約是 80%,如果是五個字元都識別,正確的總概率是 32.8%)。