【基於Python的Selenium2自動化測試】04 - 模擬126郵箱的登入
首先開啟126郵箱的登入頁面如下:
所以我們要模擬的就是上圖中的郵箱賬號和密碼的填寫,以及登入按鈕的點選事件。
通過Chrome的開發者工具(F12),我們可以看到上述元素的前端程式碼如下:
【郵箱賬號或手機號】
<div class="u-input box" id="auto-id-1547015266203">
<label class="u-label f-dn" id="auto-id-1547015266172" style="display: block;">郵箱帳號或手機號</label>
<input data-placeholder="郵箱帳號或手機號" name="email" data-type="email" data-loginname="loginEmail" data-required="true" class="j-inputtext dlemail" type="text" autocomplete="off" tabindex="1" spellcheck="false" id="auto-id-1547015266158" placeholder="郵箱帳號或手機號" style="width: 188px;" />
<span class="pr-domain j-prdomain" style="right: -87px;">@126.com</span>
</div>
【密碼】
<div class="u-input box" id="auto-id-1547015266205">
<label class="u-label f-dn" id="auto-id-1547015266181" style="display: block;">密碼</label>
<input type="password" style="display:none;width:0;height:0;" />
<input data-placeholder="密碼" name="password" maxlength="50" data-required="true" class="j-inputtext dlpwd" type="password" autocomplete="new-password" data-max-length="50" tabindex="2" spellcheck="false" id="auto-id-1547015266161" placeholder="密碼" />
<input maxlength="50" data-placeholder="密碼" type="text" id="pwdtext" class="u-pwdtext" placeholder="密碼" />
</div>
【登入按鈕】
<div class="f-cb loginbox">
<a href="javascript:void(0);" id="dologin" data-action="dologin" class="u-loginbtn btncolor tabfocus btndisabled" tabindex="8">登 錄</a>
</div>
【程式碼】
# coding=utf-8
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get("http://www.126.com")
#執行郵箱登入操作
driver.find_element_by_name("email").clear()
driver.find_element_by_name("email").send_keys("emailName")
driver.find_element_by_name("password").clear()
driver.find_element_by_name("password").send_keys("passWord")
driver.find_element_by_id("dologin").click()
time.sleep(5)
driver.quit()
執行結果報如下錯誤:
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: [name="email"]
網上搜索尋找解決方法:
在做web應用的自動化測試時,定位元素是必不可少的,這個過程經常會碰到定位不到元素的情況(報selenium.common.exceptions.NoSuchElementException
),很常見的原因就是Frame/Iframe原因定位不到元素。
這個原因很常見,首先要理解下frame
的實質,frame
中實際上是嵌入了另一個頁面,而 webdriver 每次只能在一個頁面識別,因此需要先定位到相應的frame,對那個頁面裡的元素進行定位。
如果iframe有name或id的話,直接使用switch_to_frame("name值")
或switch_to_frame("id值")
,如果沒有可用 id
或者 name
時,就需要通過其他的方法先定位到 iframe,再切換進去。。
我們還是通過Chrome開發者工具檢視上述元素,發現在郵箱帳號登入下面果真有下面一行程式碼:
<iframe name="" frameborder="0" id="x-URS-iframe1547019659690.2905" scrolling="no" style="width: 100%; height: 100%; border: none; background: none;"
src="https://passport.126.com/webzj/v1.0.1/pub/index_dl2_new.html?
cd=https%3A%2F%2Fmimg.127.net%2Findex%2F126%2Fscripts%2F2017%2Fpc%2Fcss%2F&
cf=urs.3edc4a54.css&MGID=1547019659690.2905&wdaId=&pkid=QdQXWEQ&product=mail126">
</iframe>
也就是說這裡有頁面巢狀問題。
我們看到上面的頁面元素,發現上面的iframe
的name
屬性為空,雖然有id
屬性,但是這個id
是動態生成的,每次開啟後面的數字都是不一樣的,所以,這時候我們需要通過採用其他方法先定位到該iframe
,然後再切換進去。
【程式碼修改】
# coding=utf-8
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("http://www.126.com")
iframe = driver.find_element_by_xpath("//div[@id='loginDiv']/iframe")
driver.switch_to.frame(iframe)
#執行郵箱登入操作
driver.find_element_by_name("email").clear()
driver.find_element_by_name("email").send_keys("emailName")
driver.find_element_by_name("password").clear()
driver.find_element_by_name("password").send_keys("passWord")
driver.find_element_by_id("dologin").click()
time.sleep(30)
執行結果,還是報錯,如下:
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: //div[@id='loginDiv']/iframe
這時,遇到了新的問題,繼續尋找度娘,最後找到了原因:其實是程式在開啟網頁後,進行下一步操作時,frame還未載入進來導致的。所以在定位frame元素之前,加一個延時操作,程式就能夠順利繼續下去了。
【程式碼繼續修改】
# coding=utf-8
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("http://www.126.com")
time.sleep(1) # 加一個延時操作,才能定位到下面的iframe
iframe = driver.find_element_by_xpath("//div[@id='loginDiv']/iframe")
driver.switch_to.frame(iframe)
#執行郵箱登入操作
driver.find_element_by_name("email").clear()
driver.find_element_by_name("email").send_keys("emailName")
driver.find_element_by_name("password").clear()
driver.find_element_by_name("password").send_keys("passWord")
driver.find_element_by_id("dologin").click()
time.sleep(3)
執行程式碼後,發現沒有報錯,但是跟我們預想的結果不一樣,沒有直接登入到郵箱裡面,而是出現了一個【是否更換手機號】的登入提示框。如下:
這裡,我不需要更換手機號,直接點選【登入】就可以進入到郵箱裡面了。
但是我們看到這個提示框也是巢狀頁面,通過F12偵錯程式看到如下巢狀程式碼:
解決方法: 先從上一個iframe切回到主文件頁面,然後再從主文件頁面切入到這個新的提示框的iframe,最後再點選這個新的 iframe中的【登入】按鈕即可。
【程式碼繼續修改】
# coding=utf-8
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("http://www.126.com")
time.sleep(1) # 加一個延時操作,才能定位到下面的iframe
iframe1 = driver.find_element_by_xpath("//div[@id='loginDiv']/iframe")
driver.switch_to.frame(iframe1)
#執行郵箱登入操作
driver.find_element_by_name("email").clear()
driver.find_element_by_name("email").send_keys("emailName")
driver.find_element_by_name("password").clear()
driver.find_element_by_name("password").send_keys("passWord")
driver.find_element_by_id("dologin").click()
driver.switch_to.default_content() # 切回到主文件頁面
time.sleep(1) # 這裡不加延時,也定位不到下面iframe中的[登入]按鈕
iframe2 = driver.find_element_by_xpath("//div[@id='loginDiv']/iframe")
driver.switch_to.frame(iframe2)
driver.find_element_by_link_text("登入").click()
點選,執行,終於是我們想要看到的結果了,如下: