【前言】幾天研究驗證碼解決方案有三種吧。第1、手工輸入,即保存圖片後而後咱們手工輸入;第2、使用cookie,必須輸入密碼一次,獲取cookie;第3、圖像處理+深度學習方案,研究生也作相關課題,就用了這種。html
1、處理思路python
一、圖像處理,針對我要識別的期貨中心的驗證碼,有我針對性的處理。目標是獲得去噪後的二值圖片,而後使用深度學習神經網絡方法進行識別。web
二、第一次嘗試了用谷歌的開源tesseract-ocr方法,作了一個模型訓練。由於都是集成好的開發環境,自動分割,本身只需手動的調整一些識別錯誤的。準確率仍是能夠的。正則表達式
三、使用了騰訊的免費ocr接口,是被效果大大提高。最後用一個正則表達式加一個提取器,只提取字母和數字。識別率百分之90是有的。chrome
直接上代碼。親測可用自動登陸中國期貨市場監控中心的網站https://investorservice.cfmmc.com/數據庫
1 # /usr/bin/python 2 # encoding: utf-8 3 4 import time 5 from selenium import webdriver 6 import sys 7 import urllib2 8 import urllib 9 import time 10 import re 11 12 from PIL import Image 13 from pytesseract import * 14 import PIL.ImageOps 15 16 import requests 17 import hmac 18 import hashlib 19 import base64 20 import time 21 import random 22 23 #方案一:在線二維碼識別(也是先下載到本地,可是因爲動態二維碼緣由,兩次獲取的頁面不同,致使驗證碼不匹配。匹配不成功) 24 #下面有針對此方案的解決方法,就是解析同一個界面下的驗證碼,先下載到本地,而後上傳處理。這種適合服務器不能圖片截屏獲取二維碼,可使用session或者cookie方式。 25 def yanzheng_online(): 26 # 爬取圖片 27 reload(sys) 28 sys.setdefaultencoding('utf8') 29 30 headers = ("User-Agent", 31 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36") 32 opener = urllib2.build_opener() 33 opener.addheaders = [headers] 34 urllib2.install_opener(opener) 35 36 #循環爬取多張,創建數據集 37 # for i in range(1, 1500): 38 # url = "https://investorservice.cfmmc.com/veriCode.do?t=1531728079700" + str(i) 39 # data = urllib2.urlopen(url).read() 40 # # data=urllib2.quote(data).decode('utf-8') 41 # file = "G:/360Downloads/pic/" + str(i) + ".png" 42 # playFile = open(file, 'wb') 43 # playFile.write(data) 44 # playFile.close() 45 # time.sleep(1) 46 url = "https://investorservice.cfmmc.com/veriCode.do?t=1531728079700" 47 data = urllib2.urlopen(url).read() 48 file = "G:/360Downloads/pic/" + "yanzhengma" + ".png" 49 playFile = open(file, 'wb') 50 playFile.write(data) 51 playFile.close() 52 time.sleep(1) 53 54 # 圖像處理 55 im = Image.open('G:/360Downloads/pic/yanzhengma.png') 56 57 im = im.convert('L') 58 #im.show() 59 im2 = im.point(lambda x: 0 if x > 200 else 255) 60 #im2.show() 61 im3 = im2.save("G:/360Downloads/pic/yanzhengma.png") 62 63 # 藉助騰訊免費的OCR識別 64 appid = "1257XX2374" # 寫入本身的騰訊雲號碼,我修改了 65 # bucket = "你的bucket" # 不要也能夠 66 secret_id = "AKIDGKXXXXXXXXX1XnnWyA5sFgz" # 寫入本身的帳號裏面的地址 67 secret_key = "EDwRggaXXXXXXXXXXysY0CA" # 同上 68 expired = time.time() + 2592000 69 onceExpired = 0 70 current = time.time() 71 rdm = ''.join(random.choice("0123456789") for i in range(10)) 72 userid = "0" 73 fileid = "tencentyunSignTest" 74 75 info = "a=" + appid + "&k=" + secret_id + "&e=" + str(expired) + "&t=" + str(current) + "&r=" + str( 76 rdm) + "&u=0&f=" # 去掉bucket 77 78 signindex = hmac.new(secret_key, info, hashlib.sha1).digest() # HMAC-SHA1加密 79 sign = base64.b64encode(signindex + info) # base64轉碼 80 81 url = "http://recognition.image.myqcloud.com/ocr/general" 82 headers = {'Host': 'recognition.image.myqcloud.com', 83 "Authorization": sign, 84 } 85 files = {'appid': (None, appid), 86 # 'bucket': (None, bucket), 87 'image': ('yanzhengma.png', open('G:/360Downloads/pic/yanzhengma.png', 'rb'), 'image/jpeg') 88 89 } 90 91 r = requests.post(url, files=files, headers=headers) 92 responseinfo = r.content 93 #print responseinfo 94 # 建立內存中的word文檔對象 95 # file=docx.Document() 96 r_index = r'itemstring":"(.*?)"' # 作一個正則匹配,會匹配出一些特殊符號 97 result = re.findall(r_index, responseinfo) 98 #print result 99 # result2=re.findall(r'\w+',result) 100 # new_crazy = filter(str.isalnum, result) 101 # print new_crazy 102 a = 0 103 for i in result: 104 # file.add_paragraph(i) 105 # 只識別出數字和字母 106 new_crazy = filter(str.isalnum, i) 107 #print new_crazy 108 a = new_crazy 109 # file.save("D:\\writeResult.docx") 110 return a 111 112 #方案二:網頁裁剪驗證碼,本地識別識別。匹配成功!! 113 def yanzheng_local(): 114 #對截取的圖片處理 115 im = Image.open('G:/360Downloads/pic/yanzhengma.png') 116 box = (526, 247, 623, 273) # 設置要裁剪的區域96*25,根據本身驗證碼位置 117 region = im.crop(box) # 此時,region是一個新的圖像對象。 118 # region.show()#顯示的話就會被佔用,因此要註釋掉 119 region.save("G:/360Downloads/pic/yanzhengma.png") 120 # 爬取圖片 121 reload(sys) 122 sys.setdefaultencoding('utf8') 123 124 headers = ("User-Agent", 125 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36") 126 opener = urllib2.build_opener() 127 opener.addheaders = [headers] 128 urllib2.install_opener(opener) 129 130 # 圖像處理 131 im = Image.open('G:/360Downloads/pic/yanzhengma.png') 132 133 im = im.convert('L') 134 #im.show() 135 im2 = im.point(lambda x: 0 if x > 200 else 255) 136 #im2.show() 137 im3 = im2.save("G:/360Downloads/pic/yanzhengma.png") 138 139 # 騰訊ocr識別 140 appid = "1257XXX374" # 寫入本身的騰訊雲號碼 141 # bucket = "你的bucket" # 不要也能夠 142 secret_id = "AKIDGKXXXXXXXXnnWyA5sFgz" # 寫入本身的帳號裏面的地址 143 secret_key = "EDwRggaXXXXXXXXtVrysY0CA" # 同上 144 expired = time.time() + 2592000 145 onceExpired = 0 146 current = time.time() 147 rdm = ''.join(random.choice("0123456789") for i in range(10)) 148 userid = "0" 149 fileid = "tencentyunSignTest" 150 151 info = "a=" + appid + "&k=" + secret_id + "&e=" + str(expired) + "&t=" + str(current) + "&r=" + str( 152 rdm) + "&u=0&f=" # 去掉bucket 153 154 signindex = hmac.new(secret_key, info, hashlib.sha1).digest() # HMAC-SHA1加密 155 sign = base64.b64encode(signindex + info) # base64轉碼 156 157 url = "http://recognition.image.myqcloud.com/ocr/general" 158 headers = {'Host': 'recognition.image.myqcloud.com', 159 "Authorization": sign, 160 } 161 files = {'appid': (None, appid), 162 # 'bucket': (None, bucket), 163 'image': ('yanzhengma.png', open('G:/360Downloads/pic/yanzhengma.png', 'rb'), 'image/jpeg') 164 165 } 166 167 r = requests.post(url, files=files, headers=headers) 168 responseinfo = r.content 169 #print responseinfo 170 # 建立內存中的word文檔對象 171 # file=docx.Document() 172 r_index = r'itemstring":"(.*?)"' # 作一個正則匹配 173 result = re.findall(r_index, responseinfo) 174 #print result 175 # result2=re.findall(r'\w+',result) 176 # new_crazy = filter(str.isalnum, result) 177 # print new_crazy 178 a = 0 179 for i in result: 180 # file.add_paragraph(i) 181 # 只識別出數字和字母 182 new_crazy = filter(str.isalnum, i) 183 184 #print new_crazy 185 a = new_crazy 186 # print 'a' 187 # file.save("D:\\writeResult.docx") 188 return a 189 190 def login(username, password): 191 192 url = 'https://investorservice.cfmmc.com ' 193 194 driver = webdriver.Chrome(executable_path='C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe') 195 driver.get(url) 196 # print driver.title 197 name_input = driver.find_element_by_name('userID') # 找到用戶名的框框 198 pass_input = driver.find_element_by_name('password') # 找到輸入密碼的框框 199 yanzheng_input=driver.find_element_by_name('vericode') #驗證碼輸入框 200 login_button = driver.find_element_by_name('imageField2') # 找到登陸按鈕 201 202 name_input.clear() 203 name_input.send_keys(username) # 填寫用戶名 204 time.sleep(0.2) 205 pass_input.clear() 206 pass_input.send_keys(password) # 填寫密碼 207 #驗證碼獲取 208 #local方法專用,截取驗證碼所在的網頁 209 driver.get_screenshot_as_file('G:/360Downloads/pic/yanzhengma.png') # 截圖網頁保存 210 211 212 #yzm=yanzheng_online() 213 #使用本地裁剪識別,即方案二 214 yzm=yanzheng_local() 215 print yzm 216 yanzheng_input.send_keys(yzm) 217 time.sleep(1.2) 218 login_button.click() # 點擊登陸 219 220 time.sleep(1.2) 221 #print driver.get_cookies() 222 223 #打印「登陸成功」表示成功,不然從新運行 224 if('login'in driver.current_url): 225 print "登陸成功" 226 driver.close() 227 228 if __name__ == "__main__": 229 #帳號密碼 230 user = "xxxxxxx" 231 pw = "xxxxxxxx" 232 login(user, pw)
#後面會繼續實現cookie保存,爬取信息,存儲數據庫。
2、最好的解決方法
這幾天深刻了解了python爬蟲,由於要在登陸以後,請求新的網頁時要保持登陸,否則在請求新的網頁時又會跳轉到登陸頁面。如何保持登陸呢?兩種方式,本地攜帶cookie訪問,服務器端保持session.如此,不如在登陸的時候採用登陸保持的方式,保持session.(固然攜帶cookie也能夠)。這幾天學習了抓包分析表單,實現了請求cookie,提交token.還有一個驗證碼,就採用網頁抓取,正則解析出驗證碼地址,下載本地上傳深度學習模型,識別出驗證碼傳入post表單。
源碼地址:https://www.cnblogs.com/huangfuyuan/p/9356747.html
本方法適用於windows帶圖形界面的,不適用於服務器。
3、驗證碼生成原理及python代碼
1 def verifycode(request): 2 # 引入繪圖模塊 3 from PIL import Image, ImageDraw, ImageFont 4 # 引入隨機函數模塊 5 import random 6 # 定義變量,用於畫面的背景色、寬、高 7 bgcolor = (random.randrange(20, 100), random.randrange(20, 100), random.randrange(20, 100)) width = 100 height = 50 8 # 建立畫面對象 9 im = Image.new('RGB',(width, height),bgcolor) 10 # 建立畫筆對象 11 draw = ImageDraw.Draw(im) 12 # 調用畫筆的point()函數繪製噪點 13 for i in range(0, 100): 14 xy = (random.randrange(0, width), random,randrange(0, height)) 15 fill = (random.randrange(0, 255), 255, random.randrange(0, 255)) 16 draw.point(xy, fill=fill) 17 # 定義驗證碼的備選值 18 str = '1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM' 19 # 隨機選取四個值做爲驗證碼 20 rand_str = '' 21 for i in range(0,4): 22 rand_str += str[random.randrange(0, len(str))] 23 # 構建字體對象 ,讀取本地字體模板 24 font = ImageFont.truetype(r'C\Windows\Fonts\AdobeArabic-Bold.otf', 40) 25 # 構建字體顏色 26 fontcolor1 =(255, random.randrange(0, 255), random.randrange(0, 255)) 27 fontcolor2 =(255, random.randrange(0, 255), random.randrange(0, 255)) 28 fontcolor3 =(255, random.randrange(0, 255), random.randrange(0, 255)) 29 fontcolor4 =(255, random.randrange(0, 255), random.randrange(0, 255)) 30 # 繪製四個字 31 draw.text((5, 2), rand_str[0], font=font, fill=fontcolor1) 32 draw.text((25, 2), rand_str[1], font=font, fill=fontcolor2) 33 draw.text((50, 2), rand_str[2], font=font, fill=fontcolor3) 34 draw.text((75, 2), rand_str[3], font=font, fill=fontcolor4) 35 # 釋放畫筆 36 del draw 37 # 存入session , 用於作進一步驗證 38 request.session['verifycode'] = rand_str 39 # 內存文件操做 40 import io buf = io.BytesIO() 41 # 將圖片保存在內存中,文件類型爲png 42 im.safe(buf, 'png') 43 # 將內存中的圖片數據返回給客戶端,MIME類型爲圖片png 44 return HttpResponse(buf.getValue(), 'image/png')