• 關閉

    Selenium 中的頁面元素以及常用的屬性和方法

    發表于:2024-2-21 09:04

    字體: | 上一篇 | 下一篇 | 我要投稿

     作者:Ice星空    來源:CSDN

      一、環境配置
      1. Python & Selenium
      本文是基于 Pytohn-3.7.4 以及 selenium-4.11.2 進行測試的,可以直接通過 pip 命令安裝 selenium:
      pip install selenium
      進入 python 交互界面,引入 selenium 包,檢查安裝結果:
      import selenium
      print(selenium.__version__)# 4.11.2
      2. Webdriver 瀏覽器驅動
      在準備好 Python 環境之后,還需要安裝瀏覽器程序,selenium 通過瀏覽器驅動的可執行文件對瀏覽器進行操作。
      Windows
      可以直接上對應瀏覽器的官方網站下載安裝瀏覽器即可。
      Linux
      在 Linux 則需要安裝對應瀏覽器的可執行程序以及驅動程序。
      瀏覽器可執行程序可以通過 yum 命令來安裝,例如谷歌瀏覽器:
      yum -y install google-chrome
      安裝完成之后,檢查安裝結果:
      google-chrome --version
      然后,還需要下載對應瀏覽器版本的驅動,在 Selenium 官方文檔的一篇文章 的下方,也提供了幾款比較流行的瀏覽器驅動的下載方式:
      需要注意,如果沒有瀏覽器程序和驅動版本沒有對應,啟動時將會直接報錯,提示驅動版本不匹配,此時只需要下載替換為對應版本的驅動即可。
      二、打開瀏覽器
      Windows 環境下可以直接通過 webdriver.Chrome() 創建瀏覽器驅動對象打開瀏覽器,在擁有圖形化界面的操作系統上運行時,你可以直接看到瀏覽器進程啟動,彈出瀏覽器窗口,并且后續對瀏覽器的一系列操作都可以實時在界面上看到:
      而 Linux 環境下如果直接打開瀏覽器:
      from selenium import webdriver
      driver = webdriver.Chrome()
      瀏覽器啟動將會直接報錯,拋出 selenium.common.exceptions.WebDriverException: Message: unkdown error: Chrome failed to start: exited abnormally 的異常,并且提示 google-chrome is no longer running,此時 ChromeDriver 認為瀏覽器崩潰了。
      在官方文檔中有提到,在沒有圖形化界面的操作系統中打開瀏覽器,必須指定 --headless 參數啟動:
      from selenium import webdriver
      from seleinum.webdriver.chrome.options import ChromeOptions
      # initialize options
      options = ChromeOptions()
      options.add_argument('--headless')
      # create chrome object
      driver = webdriver.Chrome(options=options)
      此時瀏覽器沒有報錯,可以正常啟動。
      另外,根據你的系統或者是 Selenium 的版本,Selenium 可能會要求你明確指定谷歌瀏覽器驅動的位置,否則會提示找不到對應的驅動:
      在初始化瀏覽器的時候,通過 service 參數設置驅動的位置即可:
      service = webdriver.ChromeService()
      在 Linux 或者 CentOS 等非圖形化界面的操作系統執行腳本的時候,很容易遇到各種各樣的問題,很多在 Windows 上面可以正常完成的流程,在 Linux 往往行為會不太一致,
      三、頁面請求
      Seleinum 中通過驅動對象的 get 方法來請求一個頁面:
      driver.get("https://www.baidu.com")
      此時,如果是 Windows 操作系統,你可以看到你的瀏覽器頁面跳轉到了百度的搜索首頁。而如果你是在 Linux 操作系統等無圖形化幾面的系統的話,可以嘗試通過查找頁面內的某個元素,或者打印頁面的標題來確定自己是否順利訪問到目標網址。
      而如果參數是一個下載鏈接,你也可以通過這個方法來下載文件,默認下載路徑是當前登錄用戶的 download 目錄:
      driver.get("your-picture-url")
      Selenium 的 webdriver 的驅動對象提供了一些屬性可以獲取當前頁面的一些信息,例如:
      # 當前頁面的標題
      print(driver.title)
      # 當前頁面的路由
      print(driver.current_url)
      四、元素定位、操作以及內容獲取
      1. 元素信息
      現在已經順利打開了一個頁面,接下來可以嘗試對頁面的元素進行操作,Selenium 提供 find_element 方法對頁面的元素進行定位:
      from selenium import webdriver
      from selenium.webdriver.common.by import By
      driver = webdriver.Chrome()
      driver.get("http://www.baidu.com")
      ele = driver.find_element(by=By.ID, value="kw")
      print(type(ele))
      其中,by 表示的是元素定位的依據,value 為檢索值,上方的代碼即表示在頁面中查找 id="kw" 的元素。
      除了 By.ID 之外,Selenium 還支持下面的檢索依據:
      ·By.CLASS_NAME,即元素的 class
      · By.TAG_NAME,即元素的標簽名稱,例如 div,a,p 等
      · By.LINK_TEXT,可以查找鏈接的文本,定位特定元素,往往用于鏈接的點擊,或者鏈接地址的獲取
      · By.CSS_SELECTOR,通過 CSS 篩選器定位元素,功能類似 JavaScript 的 document.querySelector 方法,可以通過例如 input[name=“password”] 這樣的方式定位元素,表示找到帶有 name="password" 的 input 標簽
      · By.NAME,通常是用于查找表單項元素,即找到帶有對應 name 屬性的 input,textarea,button 等頁面交互元素
      定位到元素之后,可以看到打印出來的變量類型如下:
      selenium.webdriver.remote.webelement.WebElement
      這是 selenium 定義的頁面元素對象,這個對象中已經為我們提供了一些常用的屬性可以獲取頁面元素的信息,例如:
      print(ele.text)# html 元素包含的文本,例如 <div> text </div> 中的 text
      print(ele.tag_name)# 元素標簽名稱,前文獲取到的是百度的輸入框,標簽名為 input
      print(ele.id)# 這個區別于元素的 'id' 屬性,是在 selenium 中元素對象的唯一標識
      print(ele.size)# 元素在頁面中最終計算得到的尺寸,這里返回的輸入框的尺寸為 {'height': 44, 'width': 550}
      WebElement 還提供了 get_attribute 的方法,可以獲取到元素所有的屬性,例如 name,id,class,src,href 等,還是以百度的搜索首頁 https://www.baidu.com/ 為例:
      print(ele.get_attribute("id"))# kw
      print(ele.get_attribute("class"))# soutu-btn
      還可以通過 value_of_css_property 獲取到元素所有的 CSS 屬性:
      print(ele.value_of_css_property("background-color"))# 獲取背景顏色
      print(ele.value_of_css_property("color"))# 獲取字體顏色
      print(ele.value_of_css_property("font-size"))# 獲取字體大小
      另外 WebElement 還提供了一些方法可以幫助我們判斷當前定位到的元素的狀態:
      print(ele.is_enabled())# 是否可用,即與 disabled 屬性相反
      # 結果同 print(not ele.get_attribute("disabled"))
      
      print(ele.is_selected())# 是否處于選中狀態
      print(ele.is_displayed())# 是否顯示
      通過上面的方法,我可以實現例如找到當前網頁的 DOM 中的圖片,并下載:
      # 如果有多個匹配項,find_element 默認返回第一個
      # find_elements 可以返回多個,可以利用這個方法下載頁面中所有圖片
      img_ele = driver.find_element(by=By.TAG_NAME, value="img")
      img_src = img_ele.get_attribute("src")
      driver.get(img_src)
      2. 元素操作
      find_element(s) 定位元素并操作
      通過 WebElement 封裝的方法可以對頁面元素進行操作,例如我們利用上面獲取到的輸入框元素,模擬搜索操作:
      from selenium.webdriver.common.keys import Keys
      ele = driver.find_element(by=By.ID, value="kw")
      # 模擬鍵盤輸入,并回車模擬搜索
      ele.send_keys("python selenium" + Keys.ENTER)
      也可以通過鏈式調用將元素定位和操作結合起來:
      # 模擬鍵盤輸入搜索內容
      driver.find_element(by=By.ID, value="kw").send_keys("python selenium")
      # 點擊百度首頁的搜索按鈕 “百度一下”,執行搜索
      driver.find_element(by=By.CSS_SELECTOR, value="input[id='su']").click()
      當然,如果你不滿足于這些功能,你也可以直接編寫 javaScript 去執行任何當前瀏覽器支持的 javaScript 語法編寫的腳本:
      result = driver.execute_script("return window.location.origin")
      print(result)# http://www.baidu.com
      ActionChains 操作鏈鏈式調用,實現連續操作
      使用 動作鏈(ActionChains) 的方式同樣可以實現頁面元素的操作,可以支持鏈式的操作方法調用:
      from selenium import webdriver
      from selenium.webdriver.common.by import By'
      from selenium.webdriver.common.keys import Keys
      driver = webdriver.Chrome()
      # locate element
      input_ele = driver.find_element(by=By.ID, value="kw")
      # chain of actions
      webdriver.ActionChains(driver).move_to_element(input_ele).send_keys("python selenium" + Keys.ENTER)
      selenium 目前支持的常用的操作環如下:
      ·move_to_element:聚焦到目標元素
      · click:點擊當前聚焦元素
      · send_keys:發送鍵盤輸入到當前聚焦元素
      · drag_and_drop:將當前元素拖拽到目標位置之后釋放
      · key_down:讓指定按鈕處于按下狀態,常用于模擬組合鍵操作
      · key_up:讓指定按鈕取消按下狀態
      3. Trouble shooting
      3.1 元素覆蓋問題
      如果發現點擊操作沒有正常生效,首先檢查 元素是否被其他元素覆蓋,這有可能會導致點擊無法穿透,例如 Linux 系統上,瀏覽器默認的尺寸可能與頁面要求的尺寸不符,頁面元素相互擁擠導致一些懸浮類型的元素或者一些固定位置尺寸的元素覆蓋在目標按鈕或者鏈接之上,最終導致點擊被攔截。
      你可以通過 get_window_size 的方法來查看當前瀏覽器的尺寸:
      print(driver.get_window_size()
      通過 set_window_size 方法設置合適的尺寸:
      # 常見的 16:9 的 2K 分辨率的瀏覽器尺寸
      driver.set_window_size(1920, 1080)
      可以通過 get_screenshot_as_file 截圖獲取當前頁面的情況:
      driver.get_screenshot_as_file("/tmp/check_window_size.png")
      可以通過將文件導出確認頁面是否正常,也可以在設置尺寸之前通過截圖先檢查是什么元素導致點擊失效。
      另外,如果元素沒有在當前頁面中,也可能導致點擊失效,同樣通過調整瀏覽器頁面,讓 Selenium 能夠定位到元素即可。
      3.2 iframe 問題
      如果元素在 iframe 中,那么將直接導致選擇器無法定位到目標元素,此時需要讓 Selenium 切換進入目標的 iframe 中,利用目標 iframe 的 id 實現:
      driver.switch_to.frame("target-frame-id")
      這時再次執行所需的定位或者動作,確認是否能夠順利定位執行。
      五、頁面導航 Navigate
      5.1 window 切換
      driver 提供了窗口對象以及 switch_to 來實現標簽頁切換:
      # 獲取當前瀏覽器所有的窗口
      window_handles = driver.window_handles
      # 獲取當前所在窗口
      current_window_handle = driver.current_window_handle
      # 切換到最后一個標簽頁
      driver.switch_to.window(window_handles[-1])
      打開新的標簽頁或者窗口:
      # 打開新的標簽
      driver.switch_to.new_window('tab')
      # 打開新的瀏覽器窗口
      driver.switch_to.new_window('window')
      關閉標簽頁:
      # 關閉當前所在標簽頁,即 current_window_handle
      driver.close()
      # 如果需要關閉其他標簽頁,需要切換至該標簽頁再調用 close 方法,例如關閉第一個標簽頁
      driver.switch_to.window(driver.window_handles[0])
      driver.close()
      需要注意,當我們手動關閉了當前的標簽頁,或者因為頁面的業務邏輯或者其他原因導致頁面自動關閉,此時的 current_window_handle 并不會因為自己所指向的頁面被關閉而默認切換到最近的標簽頁(即使你在 Windows 系統上面看到你的驅動所作用的瀏覽器上面的當前標簽頁已經關閉并且已經顯示了另外一個標簽頁了)。
      此時,任何對當前頁面的操作,例如獲取 current_window_handle,獲取當前標簽頁的標題 driver.title,甚至是關閉動作都會報錯,提示 Current window is already closed!
      這時,你需要先通過 switch_to.window 方法切換到一個新的已存在的頁面,此時再次獲取 current_window_handle 不會報錯,其他操作也恢復正常。
      5.2 iframe 切換
      還可以通過 switch_to 切換到頁面的 iframe 中,從而定位到 iframe 內的元素:
      # 如果 iframe 定義了名稱,可以根據目標名稱跳轉
      driver.switch_to.frame("target-frame-name")
      # 也可以通過類似 move_to_element 的方式,利用過濾器和 find_element 方法找到 iframe 元素跳轉
      target_iframe = driver.find_element(By.CSS_SELECTOR, "iframe[condition]")
      driver.switch_to.frame(target_iframe)
      # 如果 iframe 定義了 id 屬性,可以利用 id 找到 iframe 元素后跳轉
      driver.switch_to.frame(driver.find_element_by_id("iframe-id"))
      default_content 方法可以切換回頁面的默認內容主體,也就是我們訪問頁面時最外層的 <html>:
      # 從 iframe 中返回原文檔
      driver.switch_to.default_content()
      本文內容不用于商業目的,如涉及知識產權問題,請權利人聯系51Testing小編(021-64471599-8017),我們將立即處理
    《2023軟件測試行業現狀調查報告》獨家發布~

    關注51Testing

    聯系我們

    快捷面板 站點地圖 聯系我們 廣告服務 關于我們 站長統計 發展歷程

    法律顧問:上海蘭迪律師事務所 項棋律師
    版權所有 上海博為峰軟件技術股份有限公司 Copyright©51testing.com 2003-2024
    投訴及意見反饋:webmaster@51testing.com; 業務聯系:service@51testing.com 021-64471599-8017

    滬ICP備05003035號

    滬公網安備 31010102002173號

    久久97久久97精品免视_欧洲国产伦久久久久久_91麻豆精品国产自产在线观_伊人久久大香线蕉综合av