【Python】Python3網絡爬蟲實戰-44、點觸點選驗證碼的識別

上一節我們實現了極驗驗證碼的識別,但是除了極驗其實還有另一種常見的且應用廣泛的驗證碼,比較有代表性的就是點觸驗證碼。

可能你對這個名字比較陌生,但是肯定見過類似的驗證碼,比如 12306,這就是一種典型的點觸驗證碼,如圖 8-18 所示:

圖 8-18 12306 驗證碼

我們需要直接點擊圖中符合要求的圖,如果所有答案均正確纔會驗證成功,如果有一個答案錯誤,驗證就會失敗,這種驗證碼就可以稱之爲點觸驗證碼。學習過程中有不懂的可以加入我們的學習交流秋秋圈784中間758後面214,與你分享Python企業當下人才需求及怎麼從零基礎學習Python,和學習什麼內容。相關學習視頻資料、開發工具都有分享

另外還有一個專門提供點觸驗證碼服務的站點,叫做 TouClick,其官方網站爲:https://www.touclick.com/,本節就以它爲例講解一下此類驗證碼的識別過程。

1. 本節目標

本節我們的目標是用程序來識別並通過點觸驗證碼的驗證。

2. 準備工作

本次我們使用的 Python 庫是 Selenium,使用的瀏覽器爲 Chrome,在此之前請確保已經正確安裝好了 Selenium 庫、Chrome瀏覽器並配置好了 ChromeDriver,相關流程可以參考第一章的說明。

3. 瞭解點觸驗證碼

TouClick 官方網站的驗證碼樣式如圖 8-19 所示:

圖 8-19 驗證碼樣式

和 12306 站點有相似之處,不過這次是點擊圖片中的文字,不是圖片了,另外還有各種形形色色的點觸驗證碼,其交互形式可能略有不同,但基本原理都是類似的。

接下來我們就來統一實現一下此類點觸驗證碼的識別過程。

4. 識別思路

此種驗證碼的如果依靠圖像識別的話識別難度非常之大。

例如就 12306 來說,其識別難點有兩個點,第一點是文字識別,如圖 8-20 所示:

圖 8-20 12306 驗證碼

如點擊圖中所有的漏斗,“漏斗”二字其實都經過變形、放縮、模糊處理了,如果要藉助於前面我們講的 OCR 技術來識別,識別的精準度會大打折扣,甚至得不到任何結果。第二點是圖像的識別,我們需要將圖像重新轉化文字,可以藉助於各種識圖接口,可經我測試識別正確結果的準確率非常低,經常會出現匹配不正確或匹配不出結果的情況,而且圖片本身的的清晰度也不夠,所以識別難度會更大,更何況需要同時識別出八張圖片的結果,且其中幾個答案需要完全匹配正確才能驗證通過,綜合來看,此種方法基本是不可行的。

再拿 TouClick 來說,如圖 8-21 所示:

圖 8-21 驗證碼示例

我們需要從這幅圖片中識別出植株二字,但是圖片的背景或多或少會有干擾,導致 OCR 幾乎不會識別出結果,有人會說,直接識別白色的文字不就好了嗎?但是如果換一張驗證碼呢?如圖 8-22 所示:

圖 8-22 驗證碼示例

這張驗證碼圖片的文字又變成了藍色,而且還又有白色陰影,識別的難度又會大大增加。

那麼此類驗證碼就沒法解了嗎?答案當然是有,靠什麼?靠人。

靠人解決?那還要程序做什麼?不要急,這裏說的人並不是我們自己去解,在互聯網上存在非常多的驗證碼服務平臺,平臺 7×24 小時提供驗證碼識別服務,一張圖片幾秒就會獲得識別結果,準確率可達 90% 以上,但是就需要花點錢來購買服務了,畢竟平臺都是需要盈利的,不過不用擔心,識別一個驗證碼只需要幾分錢。

在這裏我個人比較推薦的一個平臺是超級鷹,其官網爲:https://www.chaojiying.com,非廣告。

其提供的服務種類非常廣泛,可識別的驗證碼類型非常多,其中就包括此類點觸驗證碼。

另外超級鷹平臺同樣支持簡單的圖形驗證碼識別,如果 OCR 識別有難度,同樣可以用本節相同的方法藉助此平臺來識別,下面是此平臺提供的一些服務:

  • 英文數字,提供最多20位英文數字的混合識別
  • 中文漢字,提供最多7個漢字的識別
  • 純英文,提供最多12位的英文的識別
  • 純數字,提供最多11位的數字的識別
  • 任意特殊字符,提供不定長漢字英文數字、拼音首字母、計算題、成語混合、 集裝箱號等字符的識別
  • 座標選擇識別,如複雜計算題、選擇題四選一、問答題、點擊相同的字、物品、動物等返回多個座標的識別

具體如有變動以官網爲準:https://www.chaojiying.com/price.html

而本節我們需要解決的就是屬於最後一類,座標多選識別的情況,我們需要做的就是將驗證碼圖片提交給平臺,然後平臺會返回識別結果在圖片中的座標位置,接下來我們再解析座標模擬點擊就好了。

原理非常簡單,下面我們就來實際用程序來實驗一下。

5. 註冊賬號

在開始之前,我們需要先註冊一個超級鷹賬號並申請一個軟件ID,註冊頁面鏈接爲:https://www.chaojiying.com/user/reg/,註冊完成之後還需要在後臺開發商中心添加一個軟件ID,最後一件事就是充值一些題分,充值多少可以根據價格和識別量自行決定。

6. 獲取API

做好上面的準備工作之後我們就可以開始用程序來對接驗證碼的識別了。

首先我們可以到官方網站下載對應的 Python API

修改之後的API如下:


import requests

from hashlib import md5

class  Chaojiying(object):

    def __init__(self,  username,  password,  soft_id):

        self.username  =  username

        self.password  =  md5(password.encode('utf-8')).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 post_pic(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 report_error(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()

這裏定義了一個 Chaojiying 類,其構造函數接收三個參數,分別是超級鷹的用戶名、密碼以及軟件ID,保存好以備使用。

接下來是最重要的一個方法叫做 post_pic(),這裏需要傳入圖片對象和驗證碼的代號,該方法會將圖片對象和相關信息發給超級鷹的後臺進行識別,然後將識別成功的 Json 返回回來。

另一個方法叫做 report_error(),這個是發生錯誤的時候的回調,如果驗證碼識別錯誤,調用此方法會返還相應的題分。

接下來我們以 TouClick 的官網爲例來進行演示點觸驗證碼的識別過程,鏈接爲:http://admin.touclick.com/,如果沒有註冊賬號可以先註冊一個。

7. 初始化

首先我們需要初始化一些變量,如 WebDriver、Chaojiying對象等等,代碼實現如下:


EMAIL  =  '[email protected]'

PASSWORD  =  ''

# 超級鷹用戶名、密碼、軟件ID、驗證碼類型

CHAOJIYING_USERNAME  =  'Germey'

CHAOJIYING_PASSWORD  =  ''

CHAOJIYING_SOFT_ID  =  893590

CHAOJIYING_KIND  =  9102

class  CrackTouClick():

    def __init__(self):

        self.url  =  'http://admin.touclick.com/login.html'

        self.browser  =  webdriver.Chrome()

        self.wait  =  WebDriverWait(self.browser,  20)

        self.email  =  EMAIL

        self.password  =  PASSWORD

        self.chaojiying  =  Chaojiying(CHAOJIYING_USERNAME,  CHAOJIYING_PASSWORD,  CHAOJIYING_SOFT_ID)

這裏的賬號和密碼請自行修改。

8. 獲取驗證碼

接下來的第一步就是完善相關表單,然後模擬點擊呼出驗證碼,此步非常簡單,代碼實現如下:

def open(self):

    """

    打開網頁輸入用戶名密碼

    :return: None

    """

    self.browser.get(self.url)

    email  =  self.wait.until(EC.presence_of_element_located((By.ID,  'email')))

    password  =  self.wait.until(EC.presence_of_element_located((By.ID,  'password')))

    email.send_keys(self.email)

    password.send_keys(self.password)

def get_touclick_button(self):

    """

    獲取初始驗證按鈕

    :return:

    """

    button  =  self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME,  'touclick-hod-wrap')))

    return  button

在這裏 open() 方法負責填寫表單,get_touclick_button() 方法則是獲取驗證碼按鈕,隨後觸發點擊即可。

接下來我們需要類似上一節極驗驗證碼圖像獲取一樣,首先獲取驗證碼圖片的位置和大小,隨後從網頁截圖裏面截取相應的驗證碼圖片就好了。代碼實現如下:


def get_touclick_element(self):

    """

    獲取驗證圖片對象

    :return: 圖片對象

    """

    element  =  self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,  'touclick-pub-content')))

    return  element

def get_position(self):

    """

    獲取驗證碼位置

    :return: 驗證碼位置元組

    """

    element  =  self.get_touclick_element()

    time.sleep(2)

    location  =  element.location

    size  =  element.size

    top,  bottom,  left,  right  =  location['y'],  location['y']  +  size['height'],  location['x'],  location['x']  +  size[

        'width']

    return  (top,  bottom,  left,  right)

def get_screenshot(self):

    """

    獲取網頁截圖

    :return: 截圖對象

    """

    screenshot  =  self.browser.get_screenshot_as_png()

    screenshot  =  Image.open(BytesIO(screenshot))

    return  screenshot

def get_touclick_image(self,  name='captcha.png'):

    """

    獲取驗證碼圖片

    :return: 圖片對象

    """

    top,  bottom,  left,  right  =  self.get_position()

    print('驗證碼位置',  top,  bottom,  left,  right)

    screenshot  =  self.get_screenshot()

    captcha  =  screenshot.crop((left,  top,  right,  bottom))

    return  captcha

在這裏 get_touclick_image() 方法即爲從網頁截圖中截取對應的驗證碼圖片,其中驗證碼圖片的相對位置座標由 get_position() 方法返回得到,最後我們得到的是一個 Image 對象。

9. 識別驗證碼

隨後我們調用 Chaojiying 對象的 post_pic() 方法即可把圖片發送給超級鷹後臺,在這裏發送的圖像是字節流格式,代碼實現如下:


image  =  self.get_touclick_image()

bytes_array  =  BytesIO()

image.save(bytes_array,  format='PNG')

# 識別驗證碼

result  =  self.chaojiying.post_pic(bytes_array.getvalue(),  CHAOJIYING_KIND)

print(result)

這樣運行之後 result 變量就是超級鷹後臺的識別結果,可能運行需要等待幾秒,畢竟後臺還有人工來完成識別。

返回的結果是一個 Json,如果識別成功後一個典型的返回結果類似如下:


{'err_no':  0,  'err_str':  'OK',  'pic_id':  '6002001380949200001',  'pic_str':  '132,127|56,77',  'md5':  '1f8e1d4bef8b11484cb1f1f34299865b'}

其中 pic_str 就是識別的文字的座標,是以字符串形式返回的,每個座標都以 | 分隔,所以接下來我們只需要將其解析之後再模擬點擊即可,代碼實現如下:


def get_points(self,  captcha_result):

    """

    解析識別結果

    :param captcha_result: 識別結果

    :return: 轉化後的結果

    """

    groups  =  captcha_result.get('pic_str').split('|')

    locations  =  [[int(number)  for  number in  group.split(',')]  for  group in  groups]

    return  locations

def touch_click_words(self,  locations):

    """

    點擊驗證圖片

    :param locations: 點擊位置

    :return: None

    """

    for  location in  locations:

        print(location)

        ActionChains(self.browser).move_to_element_with_offset(self.get_touclick_element(),  location[0],  location[1]).click().perform()

        time.sleep(1)

在這裏我們用 get_points() 方法將識別結果變成了列表的形式,最後 touch_click_words() 方法則通過調用 move_to_element_with_offset() 方法依次傳入解析後的座標,然後點擊即可。

這樣我們就可以模擬完成座標的點選了,運行效果如圖 8-23 所示:

圖 8-23 點選效果

最後我們需要做的就是點擊提交驗證的按鈕等待驗證通過,再點擊登錄按鈕即可成功登錄,後續實現在此不再贅述。

這樣我們就藉助於在線驗證碼平臺完成了點觸驗證碼的識別,此種方法也是一種通用方法,用此方法來識別 12306 等驗證碼也是完全相同的原理。

10. 結語

本節我們通過在線打碼平臺輔助完成了驗證碼的識別,這種識別方法非常強大,幾乎任意的驗證碼都可以識別,如果遇到難題,藉助於打碼平臺無疑是一個極佳的選擇。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章