python爬蟲模擬登陸驗證碼解決方案

【前言】幾天研究驗證碼解決方案有三種吧。第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')
相關文章
相關標籤/搜索