前面咱們的預定腳本已經自動將姓名填入了網頁,如今來處理剩下的部分html
前面提到過自動輸入姓名信息,其實證件號碼、手機號碼、2020年賀歲幣(第一批)這三條信息也是能夠自動輸入的。python
輸入的方式實際上是同樣的,下面是代碼:git
ele_identNo = driver.find_element_by_xpath('//*[@id="identNo"]') ele_identNo.send_keys(paras['identNo']) ele_mobile = driver.find_element_by_xpath('//*[@id="mobile"]') ele_mobile.send_keys(paras['mobile']) ele_cardvalue0 = driver.find_element_by_xpath('//*[@id="cardvalue0"]') ele_cardvalue0.send_keys(paras['cardvalue0']) 複製代碼
前文有提到過,網頁上驗證碼的源是一條連接而不是一張固定的圖片:github
基於這種狀況,咱們不能經過連接直接讀取當前的驗證碼。退而求其次,咱們採起的方式是對當前驗證碼截圖。不過這樣作有一個缺點,就是每次運行時須要存儲一個臨時的驗證碼圖片。考慮到腳本的使用環境不會有太多的驗證碼被緩存,並且每次緩存時保持臨時圖片的文件名不變則一直只會有一張圖片,因此這個策略是能夠被接受的。緩存
那怎樣對當前驗證碼截圖呢?markdown
selenium
已經爲咱們想到了這一點:網絡
# 先找到驗證碼對應的網頁元素 ele_piccaptcha = driver.find_element_by_xpath('//*[@id="piccaptcha"]') # 而後直接調用這個元素的screenshot方法,參數是保存的路徑便可實現截圖 ele_piccaptcha.screenshot('./temp_capchar.jpg') 複製代碼
咱們將驗證碼圖片保存爲了當前目錄下的temp_capchar.jpg
文件。但有時因爲元素選擇的不許確或者其餘的緣由會致使圖片偏大,因此在識別驗證碼以前須要對它進行「瘦身」(前文代碼中有體現):dom
# 先讀取圖片 image = cv2.imread(capchar, 0) # 將圖片上下左右各切割一個像素 image = image[1:-1, 1:-1] 複製代碼
上述代碼是默認封裝在recognize_capchar
方法中的,要識別驗證碼,咱們只須要將驗證碼圖片的路徑以及咱們訓練好的模型傳遞給這個方法便可。 須要注意的是,因爲初始化神經網絡的耗時相對其餘代碼來講會長不少,因此最好的作法是在程序一開始就初始化一個模型對象,後面只要須要自動識別驗證碼,都用這個對象來作。整個過程只須要初始化模型一次,能大大的提升效率,畢竟這是搶錢的時候。ide
# 用已經提早初始化好的模型和標籤對象來對temp_capchar.jpg進行自動識別 capchar = recognize_capchar('./temp_capchar.jpg', model, lb) # 將識別結果輸入到對應的框中 ele_capchar = driver.find_element_by_xpath('//*[@id="piccode"]') ele_capchar.send_keys(capchar) 複製代碼
前面都是靜態的網頁元素,像這種須要選擇的元素應該怎麼處理呢?oop
其實也仍是一步步的來,首先獲取到這個下拉框對象:
ele_orglevel = driver.find_element_by_xpath('//*[@id="orglevel1"]') 複製代碼
而後能夠經過這個下拉框對象的text
屬性已經預先配置好的location
信息獲取到下拉列表的下標:
for org_index, org in enumerate(ele_orglevel.text.split('\n')): if loca in org: ele_org = driver.find_element_by_xpath(xpath + '/option[{}]'.format(str(org_index + 1))) ele_org.click() break 複製代碼
這樣一級一級的作下來就能夠選中預先配置的選項了。我把這些重複的動做作到一個for
循環中,而後將下拉框的選擇作成了一個獨立的方法,這樣代碼是否是看起來精簡了許多:
def choose_bank(driver, location, top_xpath): locations = location.split(',') for index, loca in enumerate(locations): level = str(index + 1) xpath = top_xpath.replace('1', level) ele_orglevel = driver.find_element_by_xpath(xpath) for org_index, org in enumerate(ele_orglevel.text.split('\n')): if loca in org: ele_org = driver.find_element_by_xpath(xpath + '/option[{}]'.format(str(org_index + 1))) ele_org.click() break xpath = top_xpath.replace('1', str(len(locations) + 1)) try: ele_bottom = driver.find_element_by_xpath(xpath) except: return else: org_index = random.choice(list(range(len(ele_bottom.text.split('\n'))))[1:]) ele_org = driver.find_element_by_xpath(xpath + '/option[{}]'.format(str(org_index + 1))) ele_org.click() 複製代碼
而後這樣調用就能夠了:
choose_bank(driver, paras['location'], '//*[@id="orglevel1"]') 複製代碼
因爲手機驗證碼不是程序能直接拿到的東西,因此這個腳本也無能爲力,這也是這個腳本只能叫作半自動腳本的緣由。
但這裏仍是能簡單講講業務流程的。
要獲取手機驗證碼,咱們首先得點擊「獲取驗證碼」按鈕:
btn_sms = driver.find_element_by_xpath('//*[@id="sendValidate"]') btn_sms.click() 複製代碼
而後,咱們須要輸入手機驗證碼,而後程序會自動的輸入到網頁中:
phoneCaptchaNo = input('請輸入手機驗證碼, 按回車鍵確認(若是還未收到短信,請等到短信以後再輸入):\n') ele_phoneCaptchaNo = driver.find_element_by_xpath('//*[@id="phoneCaptchaNo"]') ele_phoneCaptchaNo.send_keys(phoneCaptchaNo) 複製代碼
至此,整個表單的信息所有填寫完成,如今就差提交了:
ele_infosubmit = driver.find_element_by_xpath('//*[@id="infosubmit"]') ele_infosubmit.click() 複製代碼
到這裏,整個預定過程就結束了。
咱們的「Python盤記念幣系列」也基本結束。
本系列的全部源代碼都會放在下面的github倉庫裏面,有須要能夠參考,有問題歡迎指正,謝謝!
https://github.com/TitusWongCN/AutoTokenAppointment
複製代碼
後面會有一篇文章對「Python盤記念幣系列」作一個總結,同時開始下一個系列,敬請期待!