如果想從頭學起selenium,可以去看看這個系列的文章哦!
https://www.cnblogs.com/miki-peng/category/1942527.html
本篇主要內容:1.元素的基本操作;2.等待操作;3.iframe切換;4.alert彈出框
下篇主要內容:1.鼠標操作;2.鍵盤操作;3.下拉框操作;4.js處理 傳送門
元素基本操作
常用操作
關鍵代碼🔻:
- 點擊:
ele.click()
- 輸入內容:
ele.send_keys("內容")
- 清空內容:
ele.clear()
- 獲取文本內容:
ele.text
- 獲取屬性值:
ele.get_attribute("屬性名稱")
- 獲取元素的寬高:
ele.size
,size和location一樣都是實例屬性,返回都是字典格式 - 獲取元素的坐標:
ele.location
,元素坐標值是通過元素的最左上角相對瀏覽器內容區域的左上角來定位的
# 定位元素
input_ele = driver.find_element_by_id("kw")
su_ele = driver.find_element_by_id("su")
# 獲取元素的文本內容
input_ele.text
# 獲取元素的某個屬性
input_ele.get_attribute("屬性名稱")
# 輸入內容
input_ele.send_keys("selenium")
# 點擊操作
su_ele.click()
# 清空內容
input_ele.clear()
# 獲取元素的寬高
print("【百度一下】按鈕的寬高:{}".format(su_ele.size))
# 獲取元素的x、y坐標值
print("【百度一下】按鈕的坐標:{}".format(su_ele.location))
表單提交
關鍵代碼🔻:
- 表單提交:
ele.submit()
,用於表單的提交;也可以定位到具體提交按鈕做一個點擊的動作
input_ele = driver.find_element_by_id("kw")
input_ele.submit() # 也可以實現回車
檢查元素
關鍵代碼🔻:
- 是否可見:
ele.is_displayed()
,返回True可見,反之不可見 - 是否可點擊:
ele.is_enabled()
,返回True可點擊,反之不可點擊 - 是否被選中:
ele.is_selected()
,返回True被選中,反之未選中
ele = driver.find_element_by_id("xxxx")
print(ele.is_displayed())
print(ele.is_enabled())
print(ele.is_selected())
等待操作
在web自動化中,不得不提的元素等待操作,我們在做功能測試中也會經常遇到頁面元素未完全加載的情況,需要等到元素出現后再進行操作。現在是代碼代替人工去做這件事,那自然也需要先等到元素加載完成才進行操作。
當我們打開瀏覽器,進入一個網頁driver.get(網址)
,除了get()會自主強制等待網頁加載完再進入下一個操作,其他元素操作都不會自己等待頁面加載完成,因此在get()之后只要我們做的動作會讓頁面產生變化就要做一個等待動作,以防元素未加載完成導致元素找不到報錯,因為代碼運行的速度是非常快的。
有三種等待方式,一種強制等待,兩種智能等待:隱性和顯性。
強制等待
time.sleep(秒)
:表示讓程序強制死等x秒,無論發生什么,都會在x秒之后再執行后續的代碼
import time
time.sleep(2) # 強制等待10s
隱性等待
implicitly_wait(秒)
:設置最長等待時間,在這個時間內只要有個時間點加載完成,則執行下一步代碼,如果在這個時間內仍未完成,就會拋出一個異常,在這整個driver的會話周期內,設置一次即可,全局都可用。
缺點🔶:程序會一直等待整個頁面加載完成,也就是一般情況下你看到瀏覽器標簽欄那個小圈不再轉,才會執行下一步,但有時候頁面想要的元素早就加載完成了,但是因為個別js、圖片之類的東西特別慢,仍得等到頁面全部完成才能執行下一步,就會增加不必要的加載時間。
from selenium import webdriver
# 實例化chrome類
# 啟動了Chromedriver,並與Chromedriver開啟了會話
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("https://www.baidu.com")
顯性等待
關鍵代碼:WebDriverWait(driver, 等待時長, 輪循周期).until/until_not(判斷條件)
。
使用WebDriverWait類和expected_conditions模塊,它會明確等到某個條件滿足后,再去執行下一步操作。它的等待機制是程序會每隔xx秒去尋找一遍,如果條件成立則執行下一步,否則以輪循的方式繼續去尋找,直到超過設置的最長時間,然后拋出一個TimeoutException
異常。
WebDriverWait類:顯性等待類
expected_conditions模塊,提供了一系列期望發生的條件,如下:
- 🍊
title_is(title)
:判斷當前頁面的title是否等於預期, - 🍊
title_contains(title)
:判斷當前頁面的title是否包含預期字符串 - 🍊
presence_of_element_located(locator)
:判斷某個元素是否存在dom樹 - 🍊
visiblilty_of_element_located(locator)
:判斷某個元素是否可見 - 🍊
visiblilty_of(element)
:跟上面的方法一樣,判斷某個元素是否可見,只是前者要傳locator(定位器),后者直接傳定位到的element就好了 - 🍊
element_to_be_clickable(locator)
:判斷某個元素是否可點擊 - 🍊
frame_to_be_available_and_switch_to_it(frame下標/name屬性/webelement對象)
:判斷該frame是否可以swtich進去,可以則返回True並swtich進去,否則返回False。 - 🍊
alert_is_present()
:判斷頁面上是否存在alert
以上是列舉的部分條件類,還有更多的方法有興趣可以自行擴展。下面是其中一個方法示例:
import time
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By # By模塊封裝了8大定位方法名
driver = webdriver.Chrome()
# driver.implicitly_wait(10) # 智能等待10秒
driver.get("http://www.baidu.com")
driver.find_element_by_xpath('//div[@id="u1"]//a[@name="tj_login"]').click()
# 定位表達式
loc = (By.ID, "TANGRAM__PSP_10__footerULoginBtn") # 實際是11,這里改成10找不到會彈出報錯
# 等待元素可見:等待時間10秒,輪循周期默認0.5秒一次
WebDriverWait(driver, 10).until(EC.visibility_of_element_located(loc))
# 操作滿足條件之后的元素
driver.find_element(*loc).click()
time.sleep(2)
driver.quit()
運行結果:
C:\software\python\python.exe D:/learn/test.py
Traceback (most recent call last):
File "D:/learn/test.py", line 25, in <module>
WebDriverWait(driver, 10).until(EC.visibility_of_element_located(loc))
File "C:\software\python\lib\site-packages\selenium\webdriver\support\wait.py", line 80, in until
raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message:
Process finished with exit code 1
知識點🔻:
上面提到的定位器其實就是一個元組(定位方式, 定位表達式)
,By模塊里封裝了8大定位方法名,跟我們之前的定位方式是一樣的。
不過要注意的是,在使用find_element()
定位元素時,不是傳入一個元組,定位方式和表達式是直接作為參數傳入的,因此上面的例子中會用到*解包。而find_element_by_id(屬性值)
之類的定位,底層代碼用的其實就是find_element()
,后者只要傳對應定位方式的值,前者則需要傳定位方式、定位表達式。
iframe切換
iframe:iframe就是一個網頁里面嵌套了另外一個框架/頁面,即一個html頁面中,還內嵌了另一個html頁面,這個內嵌的html頁面放在<iframe></iframe>
標簽對中。iframe也是html中的某一個元素,里面放的是html頁面。
切換到iframe
如果我們要操作的元素,在內嵌的iframe頁面中,那么必須要從當前頁面切換到iframe中,然后再去iframe中的頁面去操作元素。切換到iframe,主要有以下兩種方式:
- 🍅 方式一:
swtich_to.iframe()
參數:iframe的index(下標)/ iframe的name屬性 / iframe的webelement對象
# 切換到iframe 下標/name屬性/webelement對象
driver.switch_to.iframe("login_frame_qq")
driver.switch_to.iframe(0)
driver.switch_to.iframe(dirver.find_element_by_tag_name('iframe'))
- 🍅 方式二:
EC.frame_to_be_available_and_switch_to_it()
(強烈推薦 ,等待和切換一次到位)
參數:iframe的index(下標)/ iframe的name屬性 / iframe的webelement對象,等待條件:此方法會判斷iframe是否可用,並且會自動切換到iframe中
wait = WebDriverWait(driver, 10) # 設置顯性等待時間
# 設置等待條件,此方法會判斷iframe是否可用,並且會自動切換到iframe中
wait.until(EC.frame_to_be_available_and_switch_to_it('login_frame_qq'))
driver.find_element_by_id('switcher_plogin').click()
切換到上層iframe
關鍵代碼:driver.iframe_to.parent_frame()
如果iframe中又內嵌了一個iframe,那就只能在主html中一層一層地切進去。如果想返回上一層時也是一層一層地返回去。一般很少會返回去。
切換到主html
關鍵代碼:driver.swtich_to.default_content()
切換到iframe之后,本身在主html就變成了在切換后的內嵌html,這時可以操作內嵌html的元素了,如果想重新操作主html的元素,就要先從iframe中回到主html。
這里要注意,不管你是在第幾層的iframe中,想切回到主html中,都只需執行一次。例子:
import time
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
# 主html、內嵌html
# 確定要操作的元素是否在iframe內?
# 啟動Chromedriver,並與Chromedriver開啟會話
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("http://xxxx.com/")
driver.find_element_by_id('js_login').click()
wait = WebDriverWait(driver, 10) # 設置顯性等待時間
qq_l = (By.XPATH, '//div[@class="content-btns"]//a')
wait.until(EC.visibility_of_element_located(qq_l)) # 設置顯性等待條件
driver.find_element(*qq_l).click()
# 設置等待條件,此方法會判斷iframe是否可用,並且會自動切換到iframe中
wait.until(EC.frame_to_be_available_and_switch_to_it('login_frame_qq'))
driver.find_element_by_id('switcher_plogin').click()
driver.find_element_by_id('u').send_keys('test')
driver.find_element_by_id('p').send_keys('test')
driver.find_element_by_id('login_button').click()
time.sleep(2)
driver.quit() # 關閉瀏覽器,kill掉chromedriver進程
alert彈出框操作
網頁上的彈出框分兩種,一種是頁面彈出框 ,這是一個html頁面元素,可見時是能定位到並進行操作的;另一種則是alert彈出框,這是是js里的alert彈框,而selenium只能定位到html元素,那么像這種alert彈出框如何處理呢?既然是js那么我們就用js來處理。
頁面彈出框
它是一個html頁面元素,只是需要由用戶在頁面的操作中觸發彈出,因此處理這種類型的彈出框,一般分為兩步:
- 🍊 第一步:執行觸發操作之后,等待彈出框出現
- 🍊 第二步:定位彈出框中的元素並操作
如百度登錄的彈出框:
import time
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By # By模塊封裝了8大定位方法名
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
driver.find_element_by_xpath('//div[@id="u1"]//a[@name="tj_login"]').click()
# 用戶名登陸定位表達式
loc = (By.ID, "TANGRAM__PSP_11__footerULoginBtn")
# 等待時間10秒,輪循周期默認0.5秒一次
WebDriverWait(driver, 10).until(EC.visibility_of_element_located(loc))
# 操作滿足條件之后的元素
driver.find_element(*loc).click()
time.sleep(2)
driver.quit()
alert彈出框
alert彈出框的處理方式:
- 🍰 第一步:使用
swtich_to.alert
切換到彈出框,建議先使用顯性等待EC.alert_is_present()
判斷彈出框是否可見,或者強制等待0.5s:time.sleep(0.5)
- 🍰 第二步:使用Alert類提供的一系列操作方法對彈窗進行操作:
accept()
是dismiss()
否Send_keys()
往彈出框里輸入文本text()
獲取彈框里的內容
import time
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 啟動Chromedriver,並與Chromedriver開啟會話
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://www.w3school.com.cn/tiy/t.asp?f=js_alert")
wait = WebDriverWait(driver, 10)
wait.until(EC.frame_to_be_available_and_switch_to_it('iframeResult'))
# 觸發alert彈框
driver.find_element_by_xpath('//button[text()="試一試"]').click()
wait.until(EC.alert_is_present())
time.sleep(3) # 這里是為了看下效果
alert = driver.switch_to.alert # Alert類的實例化,切換到alert
alert.accept() # 是
# dismiss() 否
# text() 獲取彈框里的內容
# Send_keys() 往彈出框里輸入文本
driver.quit()