許多流行的內(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%)。