python+selenium實(shí)現(xiàn)12306模擬登錄的步驟
簡(jiǎn)介:
這里是利用了selenium+圖片識(shí)別驗(yàn)證,來(lái)實(shí)現(xiàn)12306的模擬登錄,中間也參考了好幾個(gè)項(xiàng)目,實(shí)現(xiàn)了這個(gè)小demo,中間也遇到了很多的坑,主要難點(diǎn)在于圖片識(shí)別和滑動(dòng)驗(yàn)證這兩個(gè)方面,圖片識(shí)別是利用超級(jí)鷹的服務(wù)進(jìn)行驗(yàn)證識(shí)別的,其次一個(gè)難點(diǎn)就是在賬戶密碼和圖片識(shí)別都過(guò)了以后的滑動(dòng)驗(yàn)證,因?yàn)?2306網(wǎng)站做了反爬,利用selenium滑動(dòng)時(shí),會(huì)報(bào)錯(cuò),提示你一直刷新,這里也是更改了滑動(dòng)框。
技術(shù)棧:
python、selenium、圖片驗(yàn)證、滑動(dòng)驗(yàn)證
思路:
12306網(wǎng)站的并發(fā)真的牛。
在模擬登錄的時(shí)候,第一個(gè)難點(diǎn)就是圖片驗(yàn)證,這里不會(huì)底層的算法,只能通過(guò)圖片識(shí)別平臺(tái)的api接口服務(wù)進(jìn)行解密,返回驗(yàn)證坐標(biāo)以后,通過(guò)selenium的點(diǎn)擊動(dòng)能,進(jìn)行點(diǎn)擊,在這里提前說(shuō)明一下,網(wǎng)上有很多項(xiàng)目在實(shí)例化瀏覽器時(shí),需要調(diào)整桌面分辨率,然后最大化窗口,這樣截屏才不會(huì)出現(xiàn)截不全的情況,我這邊是比較省事的,直接用xpath定位到驗(yàn)證碼的png文件。直接寫入到本地,然后傳到圖片識(shí)別平臺(tái)進(jìn)行識(shí)別。
里面涉及了一些selenium的方法,我基本上都是現(xiàn)查現(xiàn)用,比如按住鼠標(biāo)不放、按左鍵什么的。
具體的代碼和注解貼在下面,
from?selenium?import?webdriver from?hashlib?import?md5 import?requests import?time from?selenium.webdriver?import?ActionChains ? #??這個(gè)類是超級(jí)鷹平臺(tái)寫的調(diào)用服務(wù)的接口代碼,也是比較容易看懂的 class?Chaojiying_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;?MSIE?8.0;?Windows?NT?5.1;?Trident/4.0)', ????????} ? ????def?PostPic(self,?im,?codetype): ????????""" ????????im:?圖片字節(jié) ????????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) ????????return?r.json() ? ????def?ReportError(self,?im_id): ????????""" ????????im_id:報(bào)錯(cuò)題目的圖片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) ????????return?r.json() ? #???這里進(jìn)入模擬登錄的主程序 ? #?實(shí)例化瀏覽器,并且最大化。然后請(qǐng)求12306主網(wǎng)站,我這里是從首頁(yè)請(qǐng)求的,大家可以直接從登陸頁(yè)面請(qǐng)求 browser?=?webdriver.Chrome() browser.maximize_window() browser.get('http://12306.cn/') time.sleep(5) #?因?yàn)槭菑氖醉?yè)請(qǐng)求的,所以下面有兩個(gè)點(diǎn)擊的動(dòng)作,都是為了點(diǎn)進(jìn)登陸頁(yè)面 browser.find_element_by_xpath('//*[@id="J-header-login"]/a[1]').click() time.sleep(0.3) #?這里比較重要了,這里就是利用這個(gè)代碼,來(lái)更改selenium中的滑動(dòng)功能,讓網(wǎng)站不報(bào)錯(cuò) script?=?'Object.defineProperty(navigator,"webdriver",{get:()=>undefined,});' browser.execute_script(script) time.sleep(1) #?這里進(jìn)入帳號(hào)登錄 browser.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click() time.sleep(0.3) #??這里直接定位驗(yàn)證碼的png文件,然后保存 img?=?browser.find_element_by_xpath('//*[@id="J-loginImg"]') img.screenshot('cde.png') #?調(diào)用超級(jí)鷹的參數(shù) chaojiying?=?Chaojiying_Client('用戶名',?'密碼',?'ID')#??這個(gè)在超級(jí)鷹的實(shí)例代碼中有解釋 im?=?open('../12306/cde.png',?'rb').read() #?注意,這里返回的是一個(gè)字典格式,所以直接取要用的key,來(lái)返回坐標(biāo) result?=?chaojiying.PostPic(im,?9004)['pic_str'] print(result) #?這里就是處理超級(jí)鷹返回坐標(biāo)的方法了 all_list?=?[] #?通過(guò)判斷超級(jí)鷹返回坐標(biāo)的格式進(jìn)行坐標(biāo)處理, #?返回的坐標(biāo)有兩種形式,一種是以|隔開的,一種是用,隔開的,對(duì)應(yīng)下面兩種處理方式 #?處理好的坐標(biāo)存入list if?'|'?in?result: ????list?=?result.split('|') ????for?i?in?range(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) ? #?處理好的坐標(biāo)進(jìn)行循環(huán),并帶入selenium進(jìn)行點(diǎn)擊點(diǎn)擊 for?l?in?all_list: ????x?=?l[0] ????y?=?l[1] ????ActionChains(browser).move_to_element_with_offset( ????????img,?x,?y).click().perform() ????time.sleep(0.5) #?圖片點(diǎn)擊好以后,向表單內(nèi)發(fā)送賬戶密碼 browser.find_element_by_xpath('//*[@id="J-userName"]').send_keys('賬號(hào)') browser.find_element_by_xpath('//*[@id="J-password"]').send_keys('密碼') #?進(jìn)行點(diǎn)擊登錄按鈕 browser.find_element_by_xpath('//*[@id="J-login"]').click() time.sleep(2) #?下面就是滑動(dòng)模塊了 #?上面已經(jīng)更改過(guò)selenium的滑動(dòng)模塊,所以這里就可以直接定位到按鈕的位置,進(jìn)行點(diǎn)擊滑動(dòng) span?=?browser.find_element_by_xpath('//*[@id="nc_1_n1z"]') action?=?ActionChains(browser) #?這里是selenium的方法,按住點(diǎn)擊不放 action.click_and_hold(span) #?下面就是滑動(dòng)了 action.drag_and_drop_by_offset(span,400,0).perform() #?這里加了個(gè)循環(huán),就是滑動(dòng)不行,一直刷新繼續(xù)滑動(dòng),直到成功 #?其實(shí)這里也只是為了保險(xiǎn)起見,因?yàn)樯厦娓牧嘶瑒?dòng)框,基本上都會(huì)成功 while?True: ????try: ????????info=browser.find_element_by_xpath('//*[@id="J-slide-passcode"]/div/span').text ????????print(info) ????????if?info=='哎呀,出錯(cuò)了,點(diǎn)擊刷新再來(lái)一次': ????????????#點(diǎn)擊刷新 ????????????browser.find_element_by_xpath('//*[@id="J-slide-passcode"]/div/span/a').click() ????????????time.sleep(0.2) ????????????#重新移動(dòng)滑塊 ????????????span?=?browser.find_element_by_xpath('//*[@id="nc_1_n1z"]') ????????????action?=?ActionChains(browser) ????????????#?點(diǎn)擊長(zhǎng)按指定的標(biāo)簽 ????????????action.click_and_hold(span).perform() ????????????action.drag_and_drop_by_offset(span,?400,?0).perform() ????????????time.sleep(5) ????except: ????????print('ok!') ????????break #?完成后,松開鼠標(biāo) action.release() ? time.sleep(5) #?退出 browser.quit()
最后想說(shuō)的是
實(shí)現(xiàn)搶票的事,這個(gè)我還暫時(shí)沒想好怎么去做
平時(shí)工作比較忙
所以以后實(shí)現(xiàn)這個(gè)功能吧
拜拜~
以上就是python+selenium實(shí)現(xiàn)12306模擬登錄的步驟的詳細(xì)內(nèi)容,更多關(guān)于python 12306模擬登錄的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python3.5面向?qū)ο缶幊虉D文與實(shí)例詳解
這篇文章主要介紹了Python3.5面向?qū)ο缶幊?結(jié)合圖文與實(shí)例形式詳細(xì)分析了Python面向?qū)ο缶幊滔嚓P(guān)的概念、類定義、實(shí)例化、實(shí)例變量、類變量、析構(gòu)函數(shù)等相關(guān)原理及使用技巧,需要的朋友可以參考下2019-04-04Python 實(shí)現(xiàn)定積分與二重定積分的操作
這篇文章主要介紹了Python 實(shí)現(xiàn)定積分與二重定積分的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-05-05Python3 shutil(高級(jí)文件操作模塊)實(shí)例用法總結(jié)
在本篇文章里小編給大家整理的是一篇關(guān)于Python3 shutil實(shí)例用法內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。2020-02-02Python實(shí)現(xiàn)讀取Excel文件并復(fù)制指定的數(shù)據(jù)行
這篇文章主要介紹了如何基于Python語(yǔ)言,讀取Excel表格文件數(shù)據(jù),并基于其中某一列數(shù)據(jù)的值,將這一數(shù)據(jù)處于指定范圍的那一行加以復(fù)制,感興趣的可以了解一下2023-07-07python 子類調(diào)用父類的構(gòu)造函數(shù)實(shí)例
這篇文章主要介紹了python 子類調(diào)用父類的構(gòu)造函數(shù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03Python如何存儲(chǔ)和讀取ASCII碼形式的byte數(shù)據(jù)
這篇文章主要介紹了Python如何存儲(chǔ)和讀取ASCII碼形式的byte數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05Python實(shí)現(xiàn)mysql數(shù)據(jù)庫(kù)中的SQL文件生成和導(dǎo)入
這篇文章主要介紹了Python實(shí)現(xiàn)mysql數(shù)據(jù)庫(kù)中的SQL文件生成和導(dǎo)入,首先通過(guò)將mysql數(shù)據(jù)導(dǎo)出到SQL文件中展開詳細(xì)內(nèi)容需要的小伙伴可以參考一下2022-06-06