需要做的工作
0、工程結構
1、代碼:
①baidu_login.py

1 import re 2 import os 3 import sys 4 import time 5 import random 6 from selenium import webdriver 7 from PIL import Image, ImageEnhance 8 import pytesseract 9 from func import base642str, str2base64 10 11 12 def input_account(account='請傳入賬號參數', xpath_rule="//input[@id='TANGRAM__PSP_3__userName']"): 13 '''模擬輸入賬號 14 :param account: 賬號 15 :param xpath_rule: 賬號輸入框的xpath定位規則 16 :return: 17 ''' 18 input_box1 = driver.find_element_by_xpath(xpath_rule) 19 input_box1.send_keys(account) 20 time.sleep(0.5) 21 22 23 def input_pwd(pwd, xpath_rule="//input[@id='TANGRAM__PSP_3__password']"): 24 '''模擬輸入密碼 25 :param account: base64后的密碼 26 :param xpath_rule: 密碼輸入框的xpath定位規則 27 :return: 28 ''' 29 input_box2 = driver.find_element_by_xpath(xpath_rule) 30 input_box2.clear() # 清空密碼 31 input_box2.send_keys(base642str(pwd)) 32 time.sleep(0.5) 33 34 35 def input_verify_code(verify_code, xpath_rule="TANGRAM__PSP_3__verifyCode"): 36 '''模擬輸入驗證碼 37 :param account: base64后的密碼 38 :param xpath_rule: 密碼輸入框的xpath定位規則 39 :return: 40 ''' 41 driver.find_element_by_id(xpath_rule).send_keys(verify_code.strip()) 42 time.sleep(0.5) 43 44 45 def identify_verify_code(rootpath, pic_name="screenImg.png"): 46 '''tesseract識別百度驗證碼 47 :param rootpath: 驗證碼圖片保存的文件夾路徑 48 :param pic_name: 驗證碼圖片保存的文件名 49 :return: 識別后的驗證碼文本 50 ''' 51 # 截圖或驗證碼圖片保存地址 52 screenImg = os.path.join(rootpath, pic_name) 53 # 瀏覽器頁面截屏 54 time.sleep(3) 55 driver.get_screenshot_as_file(screenImg) 56 # 定位驗證碼位置及大小 57 location = driver.find_element_by_id('TANGRAM__PSP_3__verifyCodeImg').location 58 size = driver.find_element_by_id('TANGRAM__PSP_3__verifyCodeImg').size 59 left = location['x'] 60 top = location['y'] 61 right = location['x'] + size['width'] 62 bottom = location['y'] + size['height'] 63 # 從文件讀取截圖,截取驗證碼位置再次保存 64 img = Image.open(screenImg).crop((left, top, right, bottom)) 65 img = img.convert('L') # 轉換模式:L | RGB 66 img = ImageEnhance.Contrast(img) # 增強對比度 67 img = img.enhance(2.0) # 增加飽和度 68 img.save(screenImg) 69 print("圖片驗證碼以保存:%s" % screenImg) 70 # 再次讀取識別驗證碼 71 print("開始讀取識別圖片驗證碼:%s" % screenImg) 72 img = Image.open(screenImg) 73 verifycode = pytesseract.image_to_string(img) 74 print("識別結果:%s" % verifycode) 75 return verifycode 76 77 78 def click_a_link(xpath_rule="//p[@id='TANGRAM__PSP_3__footerULoginBtn']"): 79 '''點擊一個鏈接 80 :param xpath_rule: 被點擊鏈接的xpath定位規則 81 :return: 82 ''' 83 input_box0 = driver.find_element_by_xpath(xpath_rule) 84 input_box0.click() 85 86 87 def click_a_id_link(id_rule="TANGRAM__PSP_3__verifyCodeChange"): 88 '''點擊一個鏈接 89 :param id_rule: 被點擊鏈接的id定位規則 90 :return: 91 ''' 92 input_box0 = driver.find_element_by_id(id_rule) 93 input_box0.click() 94 95 96 def is_need_verify_code(): 97 '''判斷是否需要驗證碼 98 :return: 需要驗證碼返回True,否則False 99 ''' 100 imgsrc = driver.find_element_by_id("TANGRAM__PSP_3__verifyCodeImg").get_attribute('src') 101 if re.match(r'https://passport.baidu.com/cgi-bin/genimage.*', imgsrc): 102 return True 103 else: 104 return False 105 106 107 def get_id_node_text(id_rule="TANGRAM__PSP_3__error"): 108 '''獲取id節點提示信息 109 :param id_rule:id節點的id匹配規則(id屬性的值) 110 :return:該id節點中的文本信息 111 ''' 112 one_node = driver.find_element_by_id(id_rule) 113 text_info = one_node.text 114 return text_info 115 116 117 def is_login_success(): 118 '''判斷登錄是否成功 119 :return: 登錄成功返回True,否則False 120 ''' 121 current_title = driver.title.strip() 122 if current_title.startswith("登錄"): 123 return False 124 else: 125 return True 126 127 128 def deal_much_pop_up_window(): 129 '''處理手機驗證碼認證反復彈窗 130 :return: 131 ''' 132 i = 0 133 while True: # 處理手機驗證碼認證反復彈窗 134 try: 135 one3_click = driver.find_element_by_id("TANGRAM__%s__header_a" % (22 + i)) # 22+i在應對彈窗的關閉按鈕id名稱發生變化。 136 except Exception as e: 137 print("無需手機驗證碼") 138 break 139 else: 140 print("第 %s 次彈出安全驗證,要求獲取手機驗證碼" % (i + 1)) 141 time.sleep(0.5) 142 print("1s后自動選擇無需手機驗證碼") 143 time.sleep(1) 144 one3_click.click() 145 print("1s后自動點擊登陸") 146 time.sleep(1) 147 click_a_link(xpath_rule="//input[@id='TANGRAM__PSP_3__submit']") # 點擊登錄,提交表單 148 time.sleep(2) 149 # 判斷是否成功登陸 150 current_title = driver.title.strip() 151 if current_title.startswith("登錄"): 152 print('333-登陸失敗...') 153 time.sleep(0.5) 154 print('333-2秒后自動重試...') 155 i = i + 1 156 time.sleep(2) 157 continue 158 else: 159 print("打印標題") 160 print(driver.title) 161 print('333-登錄成功...') 162 sys.exit() # 程序終止 163 164 165 def deal_a_pop_up_window(xpath_rule="//input[@id='TANGRAM__PSP_27__rebindGuideCancel']"): 166 '''處理一次彈窗 167 :param xpath_rule:處理彈窗的按鈕/鏈接的xpath匹配規則 168 :return: 169 ''' 170 # 判斷是否需要手機號綁定確認 171 try: 172 # 綁定手機號確認 173 one_click = driver.find_element_by_xpath(xpath_rule) 174 except Exception as e: 175 print("無需綁定手機號確認") 176 else: 177 print("彈出了綁定手機號確認,1s后自動選擇不需要") 178 time.sleep(1) 179 one_click.click() 180 181 182 if __name__ == '__main__': 183 # 將mm隱匿化 184 # print(str2base64("123456")) 185 # str1_base64="MTIzNDU2" 186 # print(base642str(str1_base64)) 187 # sys.exit() 188 189 # 賬號和密碼准備 190 account = random.randint(0, 1000000) # 隨機數字作為賬號 191 pwd = "MTIzNDU2" 192 print("account: %s" % account) 193 # 最大登錄次數 194 max_login = 16 195 # 當前目錄設置為根路徑 196 ROOT_PATH = os.getcwd() 197 print('000-正在啟用selenium...') 198 # 調用環境變量指定的PhantomJS瀏覽器創建瀏覽器對象 199 chromedriver_exe_path = os.path.join(ROOT_PATH, "chromedriver.exe") 200 driver = webdriver.Chrome(chromedriver_exe_path) 201 print('000-啟用OK') 202 203 # 請求登錄頁面 204 url = 'https://passport.baidu.com/v2/?login' 205 print('111-selenium正在請求頁面:%s' % url) 206 driver.get(url) # get方法請求頁面,獲取響應 207 print('111-請求OK') 208 209 print("打印標題") 210 print(driver.title) 211 212 # 點擊賬號和密碼登錄 213 click_a_link() 214 215 print('222-selenium正在填寫表單...') 216 time.sleep(1) 217 # 第一次嘗試登錄 218 219 # 模擬填寫賬號 220 input_account(account) 221 222 # 模擬填寫密碼 223 input_pwd(pwd) 224 225 # 判斷是否需要驗證碼 226 is_need = is_need_verify_code() 227 if is_need: # 需要驗證碼 228 print("需要驗證碼") 229 # 自動識別和模擬填寫驗證碼 230 code = identify_verify_code(rootpath=ROOT_PATH, pic_name="screenImg.png") # 自動識別驗證碼 231 input_verify_code(code) # 模擬填寫驗證碼 232 else: # 不需要驗證碼 233 print("不需要驗證碼") 234 print('222-填寫表單OK') 235 time.sleep(1) 236 237 print('333-selenium提交表單...') 238 click_a_link(xpath_rule="//input[@id='TANGRAM__PSP_3__submit']") # 點擊登錄,提交表單 239 print("第 %s 次嘗試登錄" % 1) 240 time.sleep(3) 241 242 # 處理反復彈窗(手機驗證碼):點擊關閉按鈕 243 deal_much_pop_up_window() 244 # 處理一次彈窗(綁定手機號確認):點擊不需要修改 245 deal_a_pop_up_window() 246 247 for login_i in range(max_login - 1): 248 # 判斷是否登錄成 249 is_logined = is_login_success() 250 if is_logined: 251 print("登錄成功") 252 break 253 else: 254 print("第 %s 次登錄失敗,正在嘗試重新登錄..." % (login_i + 1)) 255 # 第二次嘗試登錄 256 print("=>第 %s 次嘗試登錄" % (login_i + 2)) 257 error_info = get_id_node_text() 258 if ("帳號或密碼錯誤" in error_info) or ("用戶名或密碼有誤"): # 第二次嘗試登錄2.1 259 print("正在嘗試重新輸入密碼...") 260 # 模擬填寫密碼 261 input_pwd(pwd) 262 # 判斷是否需要驗證碼 263 is_need = is_need_verify_code() 264 if is_need: 265 print("需要驗證碼") 266 # 點擊更新驗證碼 267 click_a_id_link() 268 # 自動識別和模擬填寫驗證碼 269 code = identify_verify_code(rootpath=ROOT_PATH, pic_name="screenImg.png") # 自動識別驗證碼 270 input_verify_code(code) # 模擬填寫驗證碼 271 print("提示:驗證碼錯誤,js會使得提交無效") 272 else: 273 print("不需要驗證碼") 274 275 elif ("驗證碼" in error_info): # 第二次嘗試登錄2.2 276 print("正在嘗試重新輸入了驗證碼和密碼...") 277 time.sleep(1) 278 # 模擬填寫密碼 279 input_pwd(pwd) 280 # 點擊更新驗證碼 281 click_a_id_link() 282 # 自動識別和模擬填寫驗證碼 283 code = identify_verify_code(rootpath=ROOT_PATH, pic_name="screenImg.png") # 自動識別驗證碼 284 input_verify_code(code) # 模擬填寫驗證碼 285 print("提示:驗證碼錯誤,js會使得提交無效") 286 time.sleep(2) 287 288 else: 289 print("其他未知異常:登錄失敗") 290 sys.exit() # 程序終止 291 292 print('222-填寫表單OK') 293 time.sleep(1) 294 295 print('333-selenium提交表單...') 296 click_a_link(xpath_rule="//input[@id='TANGRAM__PSP_3__submit']") # 點擊登錄,提交表單 297 time.sleep(3) 298 299 # 打印標題 300 print("打印標題") 301 print(driver.title) 302 time.sleep(1) 303 304 # 判斷是否成功登陸 305 is_logined = is_login_success() 306 if is_logined: 307 print('333-登錄成功...') 308 else: 309 print('333-登陸失敗...')
②func.py
import base64 import time def timestamp2datems(timestamp): ''' 時間戳轉為日期字串,精確到ms。單位s :param timestamp:時間戳 :return:日期字串 ''' local_time = time.localtime(timestamp) # data_head = time.strftime("%Y-%m-%d %H:%M:%S", local_time) data_head = time.strftime("%Y-%m-%d_%H-%M-%S", local_time) data_secs = (timestamp - int(timestamp)) * 1000 dt_ms = "%s.%03d" % (data_head, data_secs) # print(dt_ms) return dt_ms def bit2humanView(bit_val): ''' 文件大小bit轉為人類易讀大小bit、KB、MB :param bit_val:字節數值 :return:人類易讀大小和單位 ''' is2kb = int(bit_val / 1042) # 轉換為kb取整 is2mb = int(bit_val / 1024 / 1024) # 轉為mb取整 is2gb = int(bit_val / 1024 / 1024 / 1024) # 轉為gb取整 if is2gb is not 0: gb_val = bit_val / 1024 / 1024 / 1024 return "%.2f GB" % gb_val if is2mb is not 0: mb_val = bit_val / 1024 / 1024 return "%.2f MB" % mb_val if is2kb is not 0: kb_val = bit_val / 1024 return "%.2f KB" % kb_val return "%s bit" % bit_val def str2base64(pwd_decode_str): ''' 明文str轉為base64密文 :param pwd_decode_str: 明文str :return: base64密文 ''' base64_encrypt = base64.b64encode(pwd_decode_str.encode('utf-8')) pwd_encode_str = str(base64_encrypt, 'utf-8') return pwd_encode_str def base642str(pwd_encode_str): ''' base64密文轉為明文str :param pwd_encode_str: base64密文 :return: 明文str ''' base64_decrypt = base64.b64decode(pwd_encode_str.encode('utf-8')) pwd_decode_str = str(base64_decrypt, 'utf-8') return pwd_decode_str
③依賴包:requirements.txt
Pillow==6.0.0 pytesseract==0.2.6 selenium==3.141.0
2、selenium的相關支持:
①google瀏覽器;
②相應版本的瀏覽器驅動chromedriver.exe
http://npm.taobao.org/mirrors/chromedriver/
3、PIL安裝:pip install pillow
4、圖像識別工具:
①windows安裝tesseract.exe
②python安裝pytesseract