使用Selenium自動化操作瀏覽器!

Selenium可以自動化操作瀏覽器,例如:選擇元素,輸入,點擊等,可以用于軟件自動化測試,爬蟲等工作,也可以做你想做的任何事情。

本文環境:?Python3.12,Windows10,Selenium?4.15.2,Chrome?119.0.6045.160?

原理

WebDriver是一套標準API協議,由Selenium提出,W3C將其作為推薦標準,用于描述對UI界面的操作指令,使得客戶端使用同樣的函數就能操作不同的瀏覽器。自動化框架Appium也是基于WebDriver協議傳輸指令。

圖片

Selenium各種編程語言的lib庫(客戶端)使用WebDriver協議,向Driver程序傳輸控制指令,各種瀏覽器都有自己對應的Driver程序,Driver程序實際上就是把WebDriver 指令翻譯成實際的瀏覽器控制命令。

安裝

一、安裝Chrome

方法1.安裝標準版Chrome(如果系統中已安裝可跳過)

官網下載安裝標準版(https://www.google.com/chrome/),Selenium會自動在PATH路徑尋找系統安裝的瀏覽器,并自動下載對應的Driver程序。

方法2.安裝測試專用版

去chromiun官網(https://chromedriver.chromium.org/downloads)?下載各平臺對應的測試專用版本Chrome和對應驅動,解壓后放到項目路徑。此種方式需要初始化驅動時配置瀏覽器和驅動的路徑,后文會有介紹。

二、安裝Python

去官網下載安裝即可?https://www.python.org/downloads/windows/

可以自定義安裝位置和特性。

圖片

注:安裝給所有人,默認安裝到系統路徑(C:\Program Files\)下,有些庫文件會分散安裝到系統其他路徑。

安裝給當前用戶,默認安裝到路徑(C:\Users\username\AppData\Local\Programs\)下。所有文件都會安裝到一個文件夾下,把這個目錄復制到別處,只需自己配好PATH路徑就能繼續使用。

注:由于Python3.12的基礎庫有些變動,如果你使用Pycharm請升級其到最新版,否則可能管理不了虛擬環境。

三、安裝selenium庫

pip install selenium

示例:訪問百度

import timefrom selenium import webdriverfrom selenium.webdriver.common.by import By
driver = webdriver.Chrome()driver.get("https://www.baidu.com/")print(driver.title)
input = driver.find_element(by=By.ID, value="kw")input.send_keys('abc')
submit = driver.find_element(by=By.XPATH, value='//*[@id="su"]')submit.click()
time.sleep(300)

第一次運行可能要等一段挺長的時間,之后會自動打開頁面輸入內容,點擊搜索:

圖片

初始化driver

以下初始化參數請按需選擇

from?selenium?import?webdriver
options?=?webdriver.ChromeOptions()
options.page_load_strategy?=?'normal'??#?網頁加載模式:等待所有資源都被下載options.binary_location = r".\chrome-win64\chrome.exe"  # 指定被操作的瀏覽器程序路徑
#?headless模式需要的三個配置,不需要可以注釋掉options.add_argument("--headless")  # 無界面模式options.add_argument("--disable-gpu")  # headless模式下,windows系統可能需要options.add_argument('--window-size=1920,1080')  # 缺少此配置,headless模式可能點擊不到元素
options.add_argument("--start-maximized")??#?啟動時最大化窗口options.add_argument(f"--force-device-scale-factor={1}")  # 縮放后的高分屏截屏模糊,需要恢復options.add_argument("--test-type=gpu")??#?關掉提示:“Chrome測試版?僅適用于自動測試”
options.add_experimental_option("detach",?True)??#?driver退出,但保留瀏覽器(注意不要執行driver.quit())
switches =?['enable-automation', ?#?關掉提示:“Chrome正受到自動測試軟件的控制”????????????'enable-logging',??#?關閉瀏覽器日志????????????]????????????options.add_experimental_option('excludeSwitches', switches)
prefs = {"credentials_enable_service": False,  # 禁止保存密碼彈窗?????????"profile.password_manager_enabled":?False,??#?禁止保存密碼彈窗         }options.add_experimental_option("prefs", prefs)
service = webdriver.ChromeService(service_args=["--verbose", "--log-path=.\\qc1.log"], # chromedriver的日志                                 executable_path=r".\chromedriver-win64\chromedriver.exe" # chromedriver程序路徑                                 )driver = webdriver.Chrome(options=options, service=service)
driver.implicitly_wait(50)??#?查找元素標簽時,等待時長

注:瀏覽器啟動后,可以在地址欄訪問:chrome://version/ 查看啟動參數,需要屏蔽的默認參數可以放到excludeSwitches中。

注:如果想用detach True參數,在Pycharm中不要直接Run,要在Terminal標簽,或系統cmd命令行運行。或者excludeSwitches中包含'enable-logging'確保瀏覽器不輸出日志。

注:關于指定所用的瀏覽器和web驅動

在4.10.0版本后,selenium包含了一個Selenium Manager工具,會自動探測系統上安裝的瀏覽器位置,自動下載對應的web驅動程序,這種情況下也可以刪除上文中這兩個配置:上文的百度示例就是沒有這兩個配置,第一次運行自動下載驅動消耗了一段時間。

# 指定瀏覽器options.binary_location = r".\chrome-win64\chrome.exe"# 指定web驅動service?=?webdriver.ChromeService(executable_path=r".\chromedriver-win64\chromedriver.exe")
現在我也找了很多測試的朋友,做了一個分享技術的交流群,共享了很多我們收集的技術文檔和視頻教程。
如果你不想再體驗自學時找不到資源,沒人解答問題,堅持幾天便放棄的感受
可以加入我們一起交流。而且還有很多在自動化,性能,安全,測試開發等等方面有一定建樹的技術大牛
分享他們的經驗,還會分享很多直播講座和技術沙龍
可以免費學習!劃重點!開源的!!!
qq群號:691998057【暗號:csdn999】

打開網頁

打開網頁,selenium只有get方法,其他方法只能操作瀏覽器,由瀏覽器或js腳本發送。???????

driver.get('https://www.w3schools.com/js/default.asp')# driver.refresh() 刷新頁面,如果鏈接未變,重復get無用,可以刷新。

網頁操作簡單來說就分兩步:1. 定位元素 2.執行操作。???????

from selenium.webdriver.common.by import Byaccept_button = driver.find_element(by=By.XPATH,????????????????????value='//*[@id="accept-choices"]')accept_button.click()

元素定位

主要通過find_element()函數進行,有兩個參數,by參數選擇定位方式;value參數輸入定位方式對應的值。

其他定位方式:

By.XPATH:使用XPATH定位:?'//*[@id="accept-choices"]'。

By.TAG_NAME:使用tag名定位:? 即h1,div,a等。

By.ID: 使用ID屬性:<div id="content"></div>

By.NAME: 使用name屬性:<div name="content"></div>

By.CSS_SELECTOR:? css選擇器:"#book"

By.CLASS_NAME:類名:<div class="content"></div>

By.LINK_TEXT:通過鏈接文字:<a href="continue.html">Continue</a>

By.PARTIAL_LINK_TEXT:部分鏈接文字:上例中只寫Cont
?

定位元素不只針對窗口,也可以從已經定位的元素開始,driver.find_element() 返回的是一個?WebElement,它也有find_element()方法???????

table?=?driver.find_element(by=By.ID,?value="table")t_body = table.find_element(by=By.TAG_NAME, value="tbody")t_tr?=?t_body.find_elements(by=By.TAG_NAME,?value='tr')

元素操作???????

# 按鈕鏈接等button.click()#?文本框username_box.send_keys(username)#?select元素from selenium.webdriver.support.ui import Selectselect_elm?=?driver.find_element(by=By.TAG_NAME,?value='select')selecter?=?Select(select_elm)selecter.select_by_value("2023-12")

切換iframe和窗口

有時候你會發現,怎么也定位不到元素,這也許是因為他們處于不同的iframe或窗口,必須先切換過去才能操作。

切換iframe???????

<iframe id="buttonframe" name="myframe"  src="https://seleniumhq.github.io">   <button>Click here</button></iframe>------------------------------------#?Store?iframe?web?elementiframe = driver.find_element(By.CSS_SELECTOR, "#modal > iframe")
#?switch?to?selected?iframedriver.switch_to.frame(iframe)# Switch frame by iddriver.switch_to.frame('buttonframe')
#?Now?click?on?buttondriver.find_element(By.TAG_NAME, 'button').click()
# switch back to default contentdriver.switch_to.default_content()

切換窗口???????

driver.current_window_handle # 當前窗口句柄driver.window_handles # 所有的窗口列表,可以從中取出handle
#?Opens?a?new?tab?and?switches?to?new?tabdriver.switch_to.new_window('tab')#?Opens?a?new?window?and?switches?to?new?windowdriver.switch_to.new_window('window')driver.switch_to.window(handle)?#?切換到一個窗口,driver.close() # 關閉窗口

等待(Wait)

點擊了按鈕或執行了某個操作后,瀏覽器需要一定的時間加載資源或進行計算,js也會改變DOM內容。

因此,很多時候我們需要等待一定的條件才能繼續操作。

手工等待

最簡單的等待可以添加time.sleep()硬性等待,短時間的等待(一兩秒)是可以使用的,對于等待時長不固定,有較大概率等待時間較長的情況一般不要使用,但在遇到問題時可以臨時用這種方法定位問題。

隱式等待

在初始化好driver后,使用如下語句配置

driver.implicitly_wait(20)

如果沒有配置默認值為0,即如果元素沒有就位會立刻返回錯誤;如果配置了則等待對用時長后元素還沒有就位才返回錯誤;如果元素就位會立即返回,不會浪費時間。

顯式等待(最重要)

顯式等待,是等待某個或某些條件的成立,條件是否成立由一個函數判斷,這個函數作為參數傳寄給Wait機制的until()或until_not()函數:???????

from selenium.webdriver.support.ui import WebDriverWait
wait = WebDriverWait(driver, timeout=20)element = wait.until(lambda?d?:?revealed.is_displayed())wait.until_not(lambda d : revealed.is_displayed())
# 還可以配置其探測間隔,忽略的異常等errors = [NoSuchElementException, ElementNotInteractableException]wait = WebDriverWait(driver, timeout=2, poll_frequency=.2, ignored_exceptions=errors)wait.until(lambda d : revealed.send_keys("Displayed") or True)

until()函數直到回調函數返回"真"值,否則拋出超時異常;until_not()函數相反,直到回調函數返回"假"值就返回否則拋出異常,另外如果遇到被忽略的異常,會返回True。

回調函數接收一個參數,即初始化wait時的driver。???????

def condition_fun(driver):????if?time.time()?>?2524579200:?#?2050-01-01后滿足條件????????return?Trueresp?=?wait.until(condition_fun)

系統預定義條件

系統預置了一些expected conditions函數,他們通過閉包的方式,生成一個符合until()函數需要的單參數函數:???????

from selenium.webdriver.support import expected_conditions as ECf_condition?=?EC.element_to_be_clickable(submit_button)wait.until(f_condition)?#?f_condition是一個函數

EC.element_to_be_clickable()函數會幫我們生成需要的回調函數。這個函數等待指定的元素可點擊。

函數的參數指定要等待的元素,有兩種類型,一種是之前見過的使用find_element找到的元素,另一種是使用一個元組,傳入定位方式和定位值,被稱為locator:

例:???????

# 傳入元素submit_button =?driver.find_element(by=By.XPATH,?value='//*[@id="submit"]')submit_button?=?wait.until(EC.element_to_be_clickable(submit_button))if?submit_button?:    submit_button.click()
#?傳入locatorsubmit_button?=?wait.until(EC.element_to_be_clickable(                     (By.XPATH,?'//*[@id="submit"]')                  ))if submit_button :????submit_button.click()

預定義的條件很多,詳情見官方文檔,這里簡單介紹幾個:???????

EC.alert_is_present() # 當前正彈出告警框,并返回告警框EC.element_attribute_to_include()?#?元素包含某個屬性EC.element_to_be_clickable() # 元素可被點擊EC.visibility_of()?#?元素可見EC.staleness_of()?#?元素消失EC.text_to_be_present_in_element() # 元素種出現某個字符EC.title_contains(title)?#?頁面標題包含某字符串
#?還有些條件的組合函數EC.all_of()?#?所有條件都滿足EC.any_of()?#?任何一個條件滿足EC.none_of()?#?所有條件都不滿足

文檔:https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html

補充:等待AJAX請求結束,并獲取其內容

由于前后端分離技術,越來越多的頁面并不是后端渲染完再返回顯示,而是先返回一個框架,通過AJAX請求異步獲取數據,再用js渲染到頁面。Selenium對js的這些請求沒有處理。

網絡波動會對下載產生很大影響,時不時會有一個很長的等待(概率低但不是沒有),如果使用sleep()手動等待,就需要等待很長時間,才能保證每一次請求都能完成。

所以如果能準確地等待一個數據請求結束,將會節省很多時間。???????

# 首先記得在初始化時打開performance日志options.set_capability(            "goog:loggingPrefs", {"performance": "ALL"}        )

這樣就可以通過日志獲得鏈接即將發送請求,響應以及響應結束三種狀態。???????

def ec_request_finish(url, timestamp):    """    等待ajax發起的GET或POST請求結束    :param url: 請求前綴,    :param timestamp: 請求開始前記錄的時間,可幫助排除頁面自動發起的請求,或減少處理的日志數量    :return: request_id, 可以通過它獲取文件內容    """    request_id = ''
    def check_fish(driver):        for log in driver.get_log('performance'):            if timestamp * 1000 > log['timestamp'] or 'message' not in log:                continue
            log_entry = json.loads(log['message'])
            try:                method = log_entry['message']['method']                params = log_entry['message']['params']                if not request_id and method in ['Network.requestWillBeSent', 'Network.responseReceived']:                    if method == 'Network.requestWillBeSent' and \                            params['request']['method'] in ['POST', 'GET'] and \                            url in params['request']['url']:                        request_id = params['requestId']                    if method == 'Network.responseReceived' and \                            params['response']['method'] in ['POST', 'GET'] and \                            url in params['response']['url']:                        request_id = params['requestId']
                if request_id and method in ['Network.loadingFinished'] and \                        request_id == params['requestId']:                    return request_id            except Exception as e:                pass    return check_fish
#?等待請求結束request_id = wait.until(ec_request_finish('https://www.abc.com/x/y/z',0))# 獲取返回的內容,此處以返回json格式字符串為例result = self.driver.execute_cdp_cmd("Network.getResponseBody", {"requestId": request_id})data?=?json.loads(result['body'])

瀏覽器操作

# 導航driver.back()driver.forward()driver.refresh()
# 獲取信息driver.title # 標題driver.current_url # 當前鏈接driver.capabilities # 查看driver的一些配置
# Cookiesdriver.add_cookie({"name": "foo", "value": "bar"})driver.get_cookie("foo")driver.get_cookies() #獲取所有域名的cookiesdriver.delete_cookie("foo")driver.delete_all_cookies()
#?執行js腳本,有些信息可以通過js獲取,當然也可以做其他事情driver.execute_script('return arguments[0].innerText', header)
size = driver.get_window_size() # 獲取窗口尺寸driver.set_window_size(1024, 768) # 設置窗口尺寸driver.get_window_position() # 獲取窗口位置driver.set_window_position(0, 0) # 設置窗口位置driver.maximize_window() # 最大化driver.minimize_window() # 最小化driver.fullscreen_window()?#?全屏顯示,相當于F11

截屏???????

# 對窗口截屏driver.get_screenshot_as_file('./image.png')?#?截屏當前窗口,gng格式driver.save_screenshot('./image.png')?#?對get_screenshot_as_file()的封裝driver.get_screenshot_as_png() # 對窗口截屏,返回二進制png數據driver.get_screenshot_as_base64() # 對窗口截屏,返回base64數據
# 對目標元素截屏element?=?driver.find_element(...)element.screenshot('./image.png')?element.screenshot_as_base64?#?注意不是函數,是property屬性element.screenshot_as_png # 注意不是函數,是property屬性

補充:截長屏的方法

一般的截屏工具截長屏是通過滾輪操作滾動條,然后不斷拼接完成的。Selenium應該也可以這樣操作,不斷的滾動、切圖、拼接。

這里分享一個更簡單些的操作:設置窗口大小,使滾動條消失內容全部顯示。但要注意,這種方式一般需要在headless模式下才能正常工作。

截屏瀏覽器:???????

original_size?=?driver.get_window_size()height?=?driver.execute_script('return?document.documentElement.scrollHeight')width?=?driver.execute_script('return?document.documentElement.scrollWidth')
driver.set_window_size(width,?height)??#?the?trick,?and?must?in?headless?modescreenshot = form.screenshot_as_base64form.screenshot('image.png')driver.set_window_size(original_size['width'], original_size['height'])

截取帶滾動條的元素:???????

content?=?driver.find_element(by=By.XPATH,?value='//div[@id="app-content"]')
original_size?=?driver.get_window_size()height = content.size['height']width = content.size['width']
driver.set_window_size(width, height+100)  # the trick, and must in headless mode# screenshot?=?content.screenshot_as_base64content.screenshot('image.png')driver.set_window_size(original_size['width'], original_size['height'])

下載文件

有些網頁有文檔或數據導出功能,點擊按鈕會下載文件,可以使用的相關參數有:

prefs = {?????????"download.default_directory":?'D:\\',??#?下載文件的保存地址,一定要是絕對地址?????????"download.prompt_for_download":?False,?????????"download.directory_upgrade":?True,??????????"profile.default_content_settings.popups":?0,         }options.add_experimental_option("prefs",?prefs)

default_directory一定要注意寫絕對地址,其他參數是屏蔽彈窗什么的,遇到了可以試試。

有時候想直接指定文件名,暫時看是不可以的,可以下載回來后再給文件改名。

警告框操作

警告框是通過js的?alert()、 confirm()、 prompt()函數彈出的???????

#?使用wait等待警告框出現,并保存它alert?=?wait.until(EC.alert_is_present())#?或者直接獲取警告框alert = driver.switch_to.alert
#?警告框的文字內容text?=?alert.text#?按確定按鈕alert.accept()# 按取消按鈕alert.dismiss()#?向prompt()輸入內容,作為其返回值alert.send_keys("Selenium")

設備操作

能模擬鍵盤,鼠標,滾輪等操作。主要通過ActionChains,ActionBuilder 操作。

通用的一些操作???????

.pause(3)  # 暫停3秒.perform() # 執行action chain

鍵盤操作???????

from selenium.webdriver import Keys, ActionChains
#?直接輸入到當前活躍元素,支持鏈式調用ActionChains(driver)\        .key_down(Keys.SHIFT)\        .send_keys("abc")\        .key_up(Keys.SHIFT)\????????.send_keys("def")\        .perform()
#?發送到特定元素(會自動點擊傳入的元素)???text_input = driver.find_element(By.ID, "textInput")ActionChains(driver)\        .send_keys_to_element(text_input, "abc")\        .perform()?
# 剪切復制粘貼cmd_ctrl?=?Keys.COMMAND?if?sys.platform?==?'darwin'?else?Keys.CONTROLActionChains(driver)\        .send_keys("Selenium!")\        .send_keys(Keys.ARROW_LEFT)\        .key_down(Keys.SHIFT)\        .send_keys(Keys.ARROW_UP)\        .key_up(Keys.SHIFT)\        .key_down(cmd_ctrl)\        .send_keys("xvv")\        .key_up(cmd_ctrl)\        .perform()

鼠標操作???????

from selenium.webdriver import Keys, ActionChains
button= driver.find_element(By.ID, "button")ActionChains(driver)\????????.move_to_element(button)?\????????.click() \        .perform()
#?移動鼠標.move_to_element(to_element).move_by_offset(xoffset, yoffset).move_to_element_with_offset(to_element, xoffset, yoffset)
# 點擊相關.click()?#?單擊.double_click() # 雙擊.context_click() # 右擊  .click_and_hold()?#?單擊不釋放.release() # 釋放按鈕
#?拖動.drag_and_drop(source,?target)?#?一個元素拖動到另一個元素的位置.drag_and_drop_by_offset(source,?xoffset, yoffset)??#?一個元素按像素拖動
#?滾輪滾動條,如果沒效果嘗試用一個新的ActionChains.scroll_by_amount(delta_x,?delta_y).scroll_to_element(element).scroll_from_origin(origin, delta_x, delta_y)

補充:顯示鼠標指針

鼠標指針是操作系統管理的,我們可以移動瀏覽器的指針焦點位置,但是操做系統不會讓鼠標跟著動。所以我們要想直觀些看到指針(debug用,正常時候不要用),需要自己畫一個:???????

????def?enable_cursor(driver):        enable_cursor = """        (function() {          var seleniumFollowerImg = document.createElement("img");          seleniumFollowerImg.setAttribute('src', 'data:image/png;base64,'            + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAQAAACGG/bgAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAA'            + 'HsYAAB7GAZEt8iwAAAAHdElNRQfgAwgMIwdxU/i7AAABZklEQVQ4y43TsU4UURSH8W+XmYwkS2I0'            + '9CRKpKGhsvIJjG9giQmliHFZlkUIGnEF7KTiCagpsYHWhoTQaiUUxLixYZb5KAAZZhbunu7O/PKf'            + 'e+fcA+/pqwb4DuximEqXhT4iI8dMpBWEsWsuGYdpZFttiLSSgTvhZ1W/SvfO1CvYdV1kPghV68a3'            + '0zzUWZH5pBqEui7dnqlFmLoq0gxC1XfGZdoLal2kea8ahLoqKXNAJQBT2yJzwUTVt0bS6ANqy1ga'            + 'VCEq/oVTtjji4hQVhhnlYBH4WIJV9vlkXLm+10R8oJb79Jl1j9UdazJRGpkrmNkSF9SOz2T71s7M'            + 'SIfD2lmmfjGSRz3hK8l4w1P+bah/HJLN0sys2JSMZQB+jKo6KSc8vLlLn5ikzF4268Wg2+pPOWW6'            + 'ONcpr3PrXy9VfS473M/D7H+TLmrqsXtOGctvxvMv2oVNP+Av0uHbzbxyJaywyUjx8TlnPY2YxqkD'            + 'dAAAAABJRU5ErkJggg==');          seleniumFollowerImg.setAttribute('id', 'selenium_mouse_follower');          seleniumFollowerImg.setAttribute('style', 'position: absolute; z-index: 99999999999; pointer-events: none; left:0; top:0');          document.body.appendChild(seleniumFollowerImg);
          document.onmousemove = function (e) {            document.getElementById("selenium_mouse_follower").style.left = e.pageX + 'px';            document.getElementById("selenium_mouse_follower").style.top = e.pageY + 'px';          };        })();
        // enableCursor();????????"""????????driver.execute_script(enable_cursor)

鼠標除了常用的按鍵還有一些特殊的,比如“中鍵”。這些按鍵需要用更底層的action機制:ActionBuilder???????

from?selenium.webdriver.common.actions.action_builder?import?ActionBuilderfrom?selenium.webdriver.common.actions.mouse_button?import?MouseButton???????
# 按鼠標按鍵action = ActionBuilder(driver)action.pointer_action.pointer_down(MouseButton.MIDDLE)action.pointer_action.pointer_up(MouseButton.MIDDLE)action.perform()

注:ActionChains?底層也是使用ActionBuilder創建的action對象:???????

class ActionChains:??? def?__init__(self,?driver:?WebDriver,?duration:?int?=?250,?devices:?list[AnyDevice]?|?None?=?None)?->?None:????????...        self.w3c_actions = ActionBuilder(driver, mouse=mouse, keyboard=keyboard, wheel=wheel, duration=duration)
????def?click(self,?on_element:?WebElement?|?None?=?None)?->?ActionChains:????????if?on_element:            self.move_to_element(on_element)
        self.w3c_actions.pointer_action.click()        self.w3c_actions.key_action.pause()        self.w3c_actions.key_action.pause()
        return self

因此,學習ActionBuilder可以通過學習ActionChains源碼進行。

指點設備

觸控屏,觸摸板,指點筆之類的???????

pointer_area = driver.find_element(By.ID, "pointerArea")pen_input = PointerInput(POINTER_PEN, "default pen")# 關鍵是替換默認的mouseaction = ActionBuilder(driver, mouse=pen_input)action.pointer_action\    .move_to(pointer_area)\    .pointer_down()\????.move_by(2,?2,?tilt_x=-72,?tilt_y=9,?twist=86)\????.pointer_up(0)action.perform()

顏色支持

Selenium有個操作顏色的類,幫助判定顏色,配置顏色???????

from selenium.webdriver.support.color import Color
#?創建顏色BLACK = Color.from_string('black')CHOCOLATE = Color.from_string('chocolate')HOTPINK = Color.from_string('hotpink')TRANSPARENT = Color.from_string('transparent')HEX_COLOUR = Color.from_string('#2F7ED8')RGB_COLOUR = Color.from_string('rgb(255, 255, 255)')RGB_COLOUR = Color.from_string('rgb(40%, 20%, 40%)')RGBA_COLOUR = Color.from_string('rgba(255, 255, 255, 0.5)')RGBA_COLOUR = Color.from_string('rgba(40%, 20%, 40%, 0.5)')HSL_COLOUR = Color.from_string('hsl(100, 0%, 50%)')HSLA_COLOUR = Color.from_string('hsla(100, 0%, 50%, 0.5)')
#?從頁面元素獲取顏色login_button = driver.find_element(By.ID,'login')login_button_colour?=?Color.from_string(login_button.value_of_css_property('color'))login_button_background_colour = Color.from_string(login_button.value_of_css_property('background-color'))
#?從顏色生成hex,rgb,rgba顏色login_button_background_colour.hex # '#ff69b4'login_button_background_colour.rgba?#?'rgba(255,?105,?180,?1)'login_button_background_colour.rgb # 'rgb(255, 105, 180)'
#?判斷元素的顏色assert login_button_background_colour == HOTPINK

總結:

本文描述了Selenium自動化操控瀏覽器的原理,環境安裝,及其支持的各種操作,并補充了一些很有用的擴展功能,希望能幫助讀者對Selenium有個整體的認識,更多操作請參考官方資料。

下面是配套資料,對于做【軟件測試】的朋友來說應該是最全面最完整的備戰倉庫,這個倉庫也陪伴我走過了最艱難的路程,希望也能幫助到你!

最后: 可以在公眾號:自動化測試老司機?! 免費領取一份216頁軟件測試工程師面試寶典文檔資料。以及相對應的視頻學習教程免費分享!,其中包括了有基礎知識、Linux必備、Shell、互聯網程序原理、Mysql數據庫、抓包工具專題、接口測試工具、測試進階-Python編程、Web自動化測試、APP自動化測試、接口自動化測試、測試高級持續集成、測試架構開發測試框架、性能測試、安全測試等。

如果我的博客對你有幫助、如果你喜歡我的博客內容,請 “點贊” “評論” “收藏” 一鍵三連哦!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/10176.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/10176.shtml
英文地址,請注明出處:http://en.pswp.cn/web/10176.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python實現星號打印出金字塔

#編程實現下列圖形的打印 a input() for i in range(int(a)//21): num * * ((i1)*2-1) print(num.center(int(a), )) 編譯后通過。輸入20后得到下面的星號金字塔

拓撲排序——數據結構

拓撲排序是對有向無環圖&#xff08;DAG&#xff09;的頂點進行線性排序的方法。關鍵在于每個頂點代表了一個任務&#xff0c;而每條有向邊代表了任務間的先后依賴關系。這個排序保證了每個任務只在它依賴的任務完成后才開始。 拓撲排序的本質是這樣的&#xff1a;你有一堆任務…

c#教程——索引器

前言&#xff1a; 索引器&#xff08;Indexer&#xff09;可以像操作數組一樣來訪問對象的元素。它允許你使用索引來訪問對象中的元素&#xff0c;就像使用數組索引一樣。在C#中&#xff0c;索引器的定義方式類似于屬性&#xff0c;但具有類似數組的訪問方式。 索引器&#x…

Cloudera的簡介及安裝部署

簡介 Cloudera是一家位于美國的軟件公司&#xff0c;成立于2008年&#xff0c;專注于為企業客戶提供基于Apache Hadoop的軟件、支持、服務以及培訓。Cloudera的開源Apache Hadoop發行版&#xff0c;即Cloudera Distribution including Apache Hadoop&#xff08;CDH&am…

【計算機網絡原理】初識網絡原理和一些名詞解釋??

?????? write in front ??????? ?????????大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之處請多多諒解&#xff0c;讓我們一起共同進步????? . ?? ?xiaoxie?????????—CSDN博客 本文由xiaoxie????????? 原創 CSDN 如…

未來辦公新方式--智能體與程序完美配合

Agent AI智能體的未來 工作中&#xff0c;有時候我們就像是在不停地踩著縫紉機&#xff0c;重復地做著那些單調乏味的任務&#xff0c;不僅耗時費力&#xff0c;還特別容易出錯。可是&#xff0c;咱們現在可是生活在數字化時代啊&#xff01;這時候&#xff0c;Python編程語言…

docker私有倉庫registry

簡介 Docker私有倉庫的Registry是一個服務&#xff0c;主要用于存儲、管理和分發Docker鏡像。具體來說&#xff0c;Registry的功能包括&#xff1a; 存儲鏡像&#xff1a;Registry提供一個集中的地方來存儲Docker鏡像&#xff0c;包括鏡像的層次結構和元數據。 版本控制&…

嵌入式人工智能是一個怎樣的概念呢?

嵌入式人工智能將會是未來幾年人工智能發展的主要方向之一&#xff0c;并且會伴隨著一系列的職位和角色的出現。雖然目前還沒有嵌入式人工智能的確切定義&#xff0c;但隨著人工智能的不斷發展&#xff0c;它勢必會延伸到邊緣、終端和嵌入式市場。 嵌入式人工智能具有速度快、功…

攻略:大學生三下鄉投稿媒體網站和快速方法

作為當代大學生,不僅需要學習和掌握知識,更需要將所學知識運用到實踐中,參與各種社會實踐活動。其中,“三下鄉”活動就是一個非常有意義的社會實踐活動。三下鄉社會實踐活動新聞稿投稿網站有哪些?有哪些方式可以快速投稿呢&#xff1f;今天小編給大家一次講個明白。 三下鄉新…

高效文件管理:一鍵提取文件名關鍵字,快速創建對應文件夾

在數字化時代&#xff0c;文件管理成為我們日常工作中不可或缺的一部分。隨著文件數量的不斷增加&#xff0c;如何高效、有序地管理這些文件成為了許多人的挑戰。傳統的文件管理方法&#xff0c;如手動創建文件夾和分類文件&#xff0c;不僅耗時耗力&#xff0c;而且容易出錯。…

KAN網絡

目錄 背景知識 什么是神經網絡&#xff1f; 神經網絡發展史 MP神經元模型 感知機模型 KAN 引言 MLP架構vsKAN架構 從數學定理方面來看&#xff1a; 從算法層面上看&#xff1a; 從實際應用過程看&#xff1a; KAN的架構細節 KAN的準確性 KAN的可解釋性 監督學習…

https://是怎么實現的?

默認的網站建設好后都是http訪問模式&#xff0c;這種模式對于純內容類型的網站來說&#xff0c;沒有什么問題&#xff0c;但如果受到中間網絡劫持會讓網站輕易的跳轉釣魚網站&#xff0c;為避免這種情況下發生&#xff0c;所以傳統的網站改為https協議&#xff0c;這種協議自己…

MyBatis——在WEB中使用MyBatis(MVC架構模式)

一、在 Web 應用中使用 MyBatis 項目目錄結構 pojo package org.qiu.bank.pojo;/*** 賬戶類&#xff0c;封裝賬戶數據* author 秋玄* version 1.0* package org.qiu.bank.pojo* date 2022-09-27-20:31* since 1.0*/ public class Account {private Long id;private String …

Logit Standardization in Knowledge Distillation 知識蒸餾中的logit標準化

摘要 知識蒸餾涉及使用基于共享溫度的softmax函數將軟標簽從教師轉移到學生。然而&#xff0c;教師和學生之間共享溫度的假設意味著他們的logits在logit范圍和方差方面必須精確匹配。這種副作用限制了學生的表現&#xff0c;考慮到他們之間的能力差異&#xff0c;以及教師天生…

TypeScript學習筆記:入門指南

介紹 TypeScript 是一個由微軟開發的開源編程語言&#xff0c;它是 JavaScript 的超集&#xff0c;添加了靜態類型和面向對象的特性&#xff0c;使得 JavaScript 更加適合大型項目的開發。本文將介紹 TypeScript 的基本概念、特點以及其在實際項目中的作用。 特點 靜態類型系…

農業生產中,土壤墑情的監測方法有哪些?

農業是人類的生命之源&#xff0c;而土壤墑情則是農業生產的基礎。我們應該倍加珍惜土地資源&#xff0c;合理利用水資源&#xff0c;努力創造出更加宜人的生長環境。讓每一滴水都能為農作物帶來生機&#xff0c;讓每一寸土地都能孕育豐收。這樣才能實現農業可持續發展的目標&a…

存內計算加速大模型——REM-CiM的RGB-事件融合多模態類比計算內存(CiM)技術

本文為大模型&存內計算融合專題的首篇文章&#xff0c;我們將以這篇名為《REM-CiM: Attentional RGB-Event Fusion Multi-modal Analog CiM for Area/Energy-efficient Edge Object Detection during both Day and Night》為例[1]&#xff0c;探討其在文中提到的多模態大模…

python dict賦值時有逗號自動變成元組

webpack 查找n.m時用的加載器是頁面上調用的&#xff0c;因為賦值了s等于加載器 s(‘8536’) s.m[‘8536’] headers[Cookie] f_m_h5_tk{cookie_list[0]}; _m_h5_tk_enc{cookie_list[1]}{accept: */*, accept-language: zh-CN,zh;q0.9, cache-control: no-cache, pragma: no-…

護眼臺燈和普通臺燈差別很大嗎?專業護眼燈品牌有哪些?

隨著科技的不斷演進&#xff0c;臺燈的設計也日益脫胎換骨&#xff0c;從曾經的笨重造型轉變為如今輕盈雅致的外觀。它們的功能同樣經歷了多樣化的革新&#xff0c;變得更加人性化和便捷。作為學習、閱讀和辦公環境中不可或缺的照明工具&#xff0c;臺燈所提供的光線舒適度至關…

小紅書java社招一二三面面經

面試前&#xff0c;先找面經哥&#xff0c;點擊此處查看更多面經 面試公司&#xff1a;小紅書 面試職位&#xff1a;后端開發工程師 整體評價&#xff1a;已拿offer &#x1f4dd;面試題&#xff1a; 【一面】 講一下MySQL優化 1、索引優化的細節 2、前綴索引原理 3、MySQ…