4、python+selenium實現12306模擬登入
阿新 • • 發佈:2020-12-22
簡介:
這裡是利用了selenium+圖片識別驗證,來實現12306的模擬登入,中間也參考了好幾個專案,實現了這個小demo,中間也遇到了很多的坑,主要難點在於圖片識別和滑動驗證這兩個方面,圖片識別是利用超級鷹的服務進行驗證識別的,其次一個難點就是在賬戶密碼和圖片識別都過了以後的滑動驗證,因為12306網站做了反爬,利用selenium滑動時,會報錯,提示你一直重新整理,這裡也是更改了滑動框。
技術棧:
python、selenium、圖片驗證、滑動驗證
思路:
提前臥槽,12306網站的併發真的牛逼。
在模擬登入的時候,第一個難點就是圖片驗證,這裡不會底層的演算法,只能通過圖片識別平臺的api介面服務進行解密,返回驗證座標以後,通過selenium的點選動能,進行點選,在這裡提前說明一下,網上有很多專案在例項化瀏覽器時,需要調整桌面解析度,然後最大化視窗,這樣截圖才不會出現截不全的情況,我這邊是比較省事的,直接用xpath定位到驗證碼的png檔案。直接寫入到本地,然後傳到圖片識別平臺進行識別。
裡面涉及了一些selenium的方法,我基本上都是現查現用,比如按住滑鼠不放、按左鍵什麼的。
具體的程式碼和註解貼在下面,
fromseleniumimportwebdriver fromhashlibimportmd5 importrequests importtime fromselenium.webdriverimportActionChains #這個類是超級鷹平臺寫的呼叫服務的介面程式碼,也是比較容易看懂的 classChaojiying_Client(object): def__init__(self,username,password,soft_id): self.username=username password=password.encode('utf8') self.password=md5(password).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;MSIE8.0;WindowsNT5.1;Trident/4.0)', } defPostPic(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) returnr.json() defReportError(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) returnr.json() #這裡進入模擬登入的主程式 #例項化瀏覽器,並且最大化。然後請求12306主網站,我這裡是從首頁請求的,大家可以直接從登陸頁面請求 browser=webdriver.Chrome() browser.maximize_window() browser.get('http://12306.cn/') time.sleep(5) #因為是從首頁請求的,所以下面有兩個點選的動作,都是為了點進登陸頁面 browser.find_element_by_xpath('//*[@id="J-header-login"]/a[1]').click() time.sleep(0.3) #這裡比較重要了,這裡就是利用這個程式碼,來更改selenium中的滑動功能,讓網站不報錯 script='Object.defineProperty(navigator,"webdriver",{get:()=>undefined,});' browser.execute_script(script) time.sleep(1) #這裡進入帳號登入 browser.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click() time.sleep(0.3) #這裡直接定位驗證碼的png檔案,然後儲存 img=browser.find_element_by_xpath('//*[@id="J-loginImg"]') img.screenshot('cde.png') #呼叫超級鷹的引數 chaojiying=Chaojiying_Client('使用者名稱','密碼','ID')#這個在超級鷹的例項程式碼中有解釋 im=open('../12306/cde.png','rb').read() #注意,這裡返回的是一個字典格式,所以直接取要用的key,來返回座標 result=chaojiying.PostPic(im,9004)['pic_str'] print(result) #這裡就是處理超級鷹返回座標的方法了 all_list=[] #通過判斷超級鷹返回座標的格式進行座標處理, #返回的座標有兩種形式,一種是以|隔開的,一種是用,隔開的,對應下面兩種處理方式 #處理好的座標存入list if'|'inresult: list=result.split('|') foriinrange(len(list)): x_y=[] x=int(list[i].split(',')[0]) y=int(list[i].split(',')[1]) x_y.append(x) x_y.append(y) all_list.append(x_y) else: x_y=[] x=int(result.split(',')[0]) y=int(result.split(',')[1]) x_y.append(x) x_y.append(y) all_list.append(x_y) print(all_list) #處理好的座標進行迴圈,並帶入selenium進行點選點選 forlinall_list: x=l[0] y=l[1] ActionChains(browser).move_to_element_with_offset( img,x,y).click().perform() time.sleep(0.5) #圖片點選好以後,向表單內傳送賬戶密碼 browser.find_element_by_xpath('//*[@id="J-userName"]').send_keys('賬號') browser.find_element_by_xpath('//*[@id="J-password"]').send_keys('密碼') #進行點選登入按鈕 browser.find_element_by_xpath('//*[@id="J-login"]').click() time.sleep(2) #下面就是滑動模組了 #上面已經更改過selenium的滑動模組,所以這裡就可以直接定位到按鈕的位置,進行點選滑動 span=browser.find_element_by_xpath('//*[@id="nc_1_n1z"]') action=ActionChains(browser) #這裡是selenium的方法,按住點選不放 action.click_and_hold(span) #下面就是滑動了 action.drag_and_drop_by_offset(span,400,0).perform() #這裡加了個迴圈,就是滑動不行,一直重新整理繼續滑動,直到成功 #其實這裡也只是為了保險起見,因為上面改了滑動框,基本上都會成功 whileTrue: try: info=browser.find_element_by_xpath('//*[@id="J-slide-passcode"]/div/span').text print(info) ifinfo=='哎呀,出錯了,點選重新整理再來一次': #點選重新整理 browser.find_element_by_xpath('//*[@id="J-slide-passcode"]/div/span/a').click() time.sleep(0.2) #重新移動滑塊 span=browser.find_element_by_xpath('//*[@id="nc_1_n1z"]') action=ActionChains(browser) #點選長按指定的標籤 action.click_and_hold(span).perform() action.drag_and_drop_by_offset(span,400,0).perform() time.sleep(5) except: print('ok!') break #完成後,鬆開滑鼠 action.release() time.sleep(5) #退出 browser.quit()
最後想說的是
實現搶票的事,這個我還暫時沒想好怎麼去做
平時工作比較忙
所以以後實現這個功能吧
拜拜~