爬蟲(chóng)系列(三十六):嘗試對(duì)知乎驗(yàn)證碼進(jìn)行處理

許多流行的內(nèi)容管理系統(tǒng)即使加了驗(yàn)證碼模塊,其眾所周知的注冊(cè)頁(yè)面也經(jīng)常會(huì)遭到網(wǎng)絡(luò) 機(jī)器人的垃圾注冊(cè)。

那么,這些網(wǎng)絡(luò)機(jī)器人究,竟是怎么做的呢?既然我們已經(jīng),可以成功地識(shí)別出保存在電腦上 的驗(yàn)證碼了,那么如何才能實(shí)現(xiàn)一個(gè)全能的網(wǎng)絡(luò)機(jī)器人呢?

大多數(shù)網(wǎng)站生成的驗(yàn)證碼圖片都具有以下屬性。

  • 它們是服務(wù)器端的程序動(dòng)態(tài)生成的圖片。驗(yàn)證碼圖片的 src 屬性可能和普通圖片不太一 樣,比如 <img src="WebForm.aspx?id=8AP85CQKE9TJ">,但是可以和其他圖片一樣進(jìn)行 下載和處理。

  • 圖片的答案存儲(chǔ)在服務(wù)器端的數(shù)據(jù)庫(kù)里。

  • 很多驗(yàn)證碼都有時(shí)間限制,如果你太長(zhǎng)時(shí)間沒(méi)解決就會(huì)失效。
    常用的處理方法就是,首先把驗(yàn)證碼圖片下載到硬盤(pán)里,清理干凈,然后-
    用 Tesseract 處理 圖片,最后返回符合網(wǎng)站要求的識(shí)別結(jié)果。

      #!/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 "機(jī)器識(shí)別后的驗(yàn)證碼為:" + text
          command = raw_input("請(qǐng)輸入Y表示同意使用,按其他鍵自行重新輸入:")
          if (command == "Y" or command == "y"):
              return text
          else:
              return raw_input('輸入驗(yàn)證碼:')
    
      def zhihuLogin(username,password):
    
          # 構(gòu)建一個(gè)保存Cookie值的session對(duì)象
          sessiona = requests.Session()
          headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0'}
    
          # 先獲取頁(yè)面信息,找到需要POST的數(shù)據(jù)(并且已記錄當(dāng)前頁(yè)面的Cookie)
          html = sessiona.get('https://www.zhihu.com/#signin', headers=headers).content
    
          # 找到 name 屬性值為 _xsrf 的input標(biāo)簽,取出value里的值
          _xsrf = BeautifulSoup(html ,'lxml').find('input', attrs={'name':'_xsrf'}).get('value')
    
          # 取出驗(yàn)證碼,r后面的值是Unix時(shí)間戳,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('xxxx@qq.com','ALAxxxxIME')
    

值得注意的是,有兩種異常情況會(huì)導(dǎo)致這個(gè)程序運(yùn)行失敗。第一種情況是,如果 Tesseract 從驗(yàn)證碼圖片中識(shí)別的結(jié)果不是四個(gè)字符(因?yàn)橛?xùn)練樣本中驗(yàn)證碼的所有有效答案都必須 是四個(gè)字符),結(jié)果不會(huì)被提交,程序失敗。第二種情況是雖然識(shí)別的結(jié)果是四個(gè)字符, 被提交到了表單,但是服務(wù)器對(duì)結(jié)果不認(rèn)可,程序仍然失敗。

在實(shí)際運(yùn)行過(guò)程中,第一種 情況發(fā)生的可能性大約為 50%,發(fā)生時(shí)程序不會(huì)向表單提交,程序直接結(jié)束并提示驗(yàn)證碼 識(shí)別錯(cuò)誤。第二種異常情況發(fā)生的概率約為 20%,四個(gè)字符都對(duì)的概率約是 30%(每個(gè)字 母的識(shí)別正確率大約是 80%,如果是五個(gè)字符都識(shí)別,正確的總概率是 32.8%)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容