selenium實現登錄百度(自動識別簡單驗證碼)


需要做的工作

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-登陸失敗...')
View Code

②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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM