【python+selenium的web自動化】- 元素的常用操作詳解(一)

miki_peng發表於2021-03-12

如果想從頭學起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://lemon.ke.qq.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.accept()   # 是
# dismiss()     否
# text()	    獲取彈框裡的內容
# Send_keys()   往彈出框裡輸入文字

driver.quit()

相關文章