我們在登錄界面,輸入用戶名和密碼之后,點擊提交按鈕, 瀏覽器會向服務器發送一個post請求, 該請求的表單數據中就包含我們輸入的用戶名密碼等信息, 有一些做了加密的網站還可能包含一些類似 _token,的數據信息,對於這樣的網站我們只需要構造表單數據, 然后向服務器發送post請求就可以實現模擬登陸了, 但是有一些做了驗證碼的網站, 我們就不能靠這種方法登陸了, 我們要借助selenium, 打碼平台, 來幫助我們識別驗證碼,進行模擬登陸, 如12306網站的登錄
登錄的難點在於驗證碼的識別:
識別驗證碼的步驟:
-
- 用selenium訪問登錄界面,待頁面加載完成后, 截取整張頁面
- 用selenium查找標簽的方法, 找到驗證碼圖片標簽, 這個標簽有兩個屬性, location(圖片左上角坐標), size(圖片長和寬), 構造一個rangle()
- 用PIL的Image.open() 打開圖片, 調用crop(rangle)方法, 將驗證碼圖片從整張圖片上截取下來,
- 將驗證碼圖片發送給超級鷹處理,返回的就是需要點擊的坐標,(相對坐標,相對於驗證碼圖片左上角的坐標), 將返回結果修改成數組結構
- 用selenium的動作鏈, 實現點擊操作
- 用selenium 輸入用戶名和密碼, 點擊登錄
import time from PIL import Image from selenium import webdriver from chaojiying import Chaojiying_Client from selenium.webdriver import ActionChains def getCode(imgpath, imgType): chaojiying = Chaojiying_Client('xxxxxxxx', 'xxx', 'xxxxxxx') im = open(imgpath, 'rb').read() return chaojiying.PostPic(im, imgType)['pic_str'] bro = webdriver.Chrome() url = 'https://kyfw.12306.cn/otn/login/init' bro.get(url) time.sleep(5) #截取驗證碼圖片 #截取整張頁面的圖片 bro.save_screenshot('main.png') #確定截取的范圍 #找到驗證碼圖片 img_ele = bro.find_element_by_xpath('//img[@class="touclick-image"]') #location表示的是驗證碼圖片的左上角的坐標 location = img_ele.location #{'x': 256, 'y': 274} # print('location:', location) #size返回的是圖片的長和寬 size = img_ele.size #{'height': 190, 'width': 293} # print('size:',size) #rangle就是制定好的截取范圍 rangle = (int(location['x']), int(location['y']), int(location['x'])+int(size['width']), int(location['y'])+int(size['height'])) print(rangle) #根據制定好的范圍進行截圖 i = Image.open('main.png') #code_img_name 驗證碼圖片的名稱 code_img_name = 'code.png' frame = i.crop(rangle) frame.save(code_img_name) #記錄: code.png就是驗證碼圖片, main.png就是當前登錄頁面對應的圖片 result = getCode('code.png', 9004) #返回的單組坐標數據 119,140 #返回的多組坐標數據 119,140|177,139|248,84 # 我們想要的數據結構式數組類型 [[119,140], [177,139]] all_points = [] for i in result.split('|'): all_points.append(i.split(',')) print('all_points', all_points) #基於selenium根據all_points進行定點的點擊操作 for point in all_points: x = point[0] y = point[1] ActionChains(bro).move_to_element_with_offset(img_ele,int(x),int(y)).click().perform() time.sleep(0.5) bro.find_element_by_id('username').send_keys('123456787') time.sleep(2) bro.find_element_by_id('password').send_keys('asdf1234') time.sleep(2) bro.find_element_by_id('loginSub').click() time.sleep(10) bro.quit()
