最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

從入門到精通介紹Python中Selenium安裝使用的完整指南

 更新時間:2025年12月17日 08:45:54   作者:去掉浮華與虛華  
Selenium?是一個功能強大的自動化測試工具,廣泛用于對?web?應用程序進行自動化測試,它支持多種編程語言(如?Python、Java、C#?等),下面小編就和大家詳細介紹一下它的詳細安裝使用教程吧

環(huán)境準備與基礎入門

1. 安裝 Selenium 與瀏覽器驅動

安裝 Selenium

# 使用pip安裝最新版本
pip install selenium

# 安裝特定版本
pip install selenium==4.10.0

# 在虛擬環(huán)境中安裝(推薦)
python -m venv selenium_env
source selenium_env/bin/activate  # Linux/Mac
selenium_env\Scripts\activate.bat  # Windows
pip install selenium

安裝瀏覽器驅動

從Selenium 4.0開始,提供了自動管理驅動的功能,但了解手動安裝方法仍然很重要:

Chrome瀏覽器:

  • 訪問 ChromeDriver 下載頁面
  • 下載與本地Chrome版本匹配的驅動程序
  • 將驅動添加到系統(tǒng)PATH中或在代碼中指定路徑

Firefox瀏覽器:

  • 訪問 GeckoDriver 下載頁面
  • 下載適用于你操作系統(tǒng)的版本
  • 將驅動添加到系統(tǒng)PATH中或在代碼中指定路徑

Edge瀏覽器:

  • 訪問 Microsoft Edge Driver 下載頁面
  • 下載與本地Edge版本匹配的驅動程序

Safari瀏覽器:

  • Safari驅動已內(nèi)置于macOS中
  • 需要在Safari瀏覽器中啟用開發(fā)者模式

2. Selenium 4.x 新特性

Selenium 4.x引入了許多重要的改進和新功能:

  • 相對定位:允許基于其他元素的位置來查找元素
  • Service對象:用于更好地管理驅動程序服務
  • WebDriver Manager:自動管理驅動程序的下載和設置
  • CDP(Chrome DevTools Protocol)支持:允許訪問瀏覽器特定的功能

3. WebDriver初始化方法

使用Selenium Manager(推薦,Selenium 4.x)

from selenium import webdriver
from selenium.webdriver.chrome.service import Service

# 自動管理驅動
driver = webdriver.Chrome()

傳統(tǒng)方法(指定驅動路徑)

from selenium import webdriver
from selenium.webdriver.chrome.service import Service

# 指定驅動路徑
service = Service(executable_path='/path/to/chromedriver')
driver = webdriver.Chrome(service=service)

配置瀏覽器選項

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

# 創(chuàng)建Chrome選項對象
chrome_options = Options()
chrome_options.add_argument("--headless")  # 無頭模式
chrome_options.add_argument("--window-size=1920,1080")  # 設置窗口大小
chrome_options.add_argument("--disable-gpu")  # 禁用GPU加速
chrome_options.add_argument("--disable-extensions")  # 禁用擴展
chrome_options.add_argument("--proxy-server='direct://'")  # 代理設置
chrome_options.add_argument("--proxy-bypass-list=*")  # 繞過代理
chrome_options.add_argument("--start-maximized")  # 啟動時最大化窗口
chrome_options.add_experimental_option("prefs", {
    "download.default_directory": "/path/to/download/directory",  # 設置下載目錄
    "download.prompt_for_download": False,  # 禁用下載提示
    "download.directory_upgrade": True,
    "safebrowsing.enabled": True
})

# 初始化WebDriver
driver = webdriver.Chrome(options=chrome_options)

4. 基礎瀏覽器操作

from selenium import webdriver

# 初始化WebDriver
driver = webdriver.Chrome()

# 窗口操作
driver.maximize_window()  # 最大化窗口
driver.set_window_size(1920, 1080)  # 設置窗口大小
driver.set_window_position(0, 0)  # 設置窗口位置

# 導航操作
driver.get('https://www.example.com')  # 打開URL
driver.back()  # 后退
driver.forward()  # 前進
driver.refresh()  # 刷新頁面

# 頁面信息
title = driver.title  # 獲取頁面標題
url = driver.current_url  # 獲取當前URL
page_source = driver.page_source  # 獲取頁面源代碼

# Cookie操作
driver.add_cookie({"name": "key", "value": "value"})  # 添加Cookie
cookies = driver.get_cookies()  # 獲取所有Cookies
driver.delete_cookie("key")  # 刪除特定Cookie
driver.delete_all_cookies()  # 刪除所有Cookies

# 關閉操作
driver.close()  # 關閉當前標簽頁
driver.quit()  # 關閉瀏覽器,釋放資源

5. 常見瀏覽器配置

無頭模式(Headless)

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_argument("--headless")
driver = webdriver.Chrome(options=chrome_options)

使用代理

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_argument('--proxy-server=http://proxyserver:port')
driver = webdriver.Chrome(options=chrome_options)

禁用圖片加載(提高性能)

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
prefs = {"profile.managed_default_content_settings.images": 2}
chrome_options.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(options=chrome_options)

元素定位與交互操作

1. 元素定位基礎

Selenium提供了多種定位元素的方法,每種都有其適用場景:

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://www.example.com")

# 1. 通過ID定位(最推薦,高效且唯一)
element = driver.find_element(By.ID, "login-button")

# 2. 通過Name屬性定位
element = driver.find_element(By.NAME, "username")

# 3. 通過Class Name定位(不唯一時返回第一個匹配元素)
element = driver.find_element(By.CLASS_NAME, "login-form")

# 4. 通過Tag Name定位
element = driver.find_element(By.TAG_NAME, "button")

# 5. 通過Link Text定位(完全匹配)
element = driver.find_element(By.LINK_TEXT, "Forgot Password?")

# 6. 通過Partial Link Text定位(部分匹配)
element = driver.find_element(By.PARTIAL_LINK_TEXT, "Forgot")

# 7. 通過CSS選擇器定位(強大且靈活)
element = driver.find_element(By.CSS_SELECTOR, "#login-form .submit-button")

# 8. 通過XPath定位(最強大但可能較慢)
element = driver.find_element(By.XPATH, "http://div[@id='login-form']//button")

2. 高級定位策略

XPath進階用法

# 絕對路徑(從根節(jié)點開始)
element = driver.find_element(By.XPATH, "/html/body/div/form/input")

# 相對路徑(從任意節(jié)點開始)
element = driver.find_element(By.XPATH, "http://input[@name='username']")

# 使用contains()函數(shù)
element = driver.find_element(By.XPATH, "http://button[contains(@class, 'login')]")

# 使用text()函數(shù)
element = driver.find_element(By.XPATH, "http://a[text()='Forgot Password?']")
element = driver.find_element(By.XPATH, "http://a[contains(text(), 'Forgot')]")

# 使用AND和OR操作符
element = driver.find_element(By.XPATH, "http://input[@type='text' and @name='username']")
element = driver.find_element(By.XPATH, "http://button[@type='submit' or @type='button']")

# 通過父子關系定位
element = driver.find_element(By.XPATH, "http://form[@id='login-form']/input")
parent = driver.find_element(By.XPATH, "http://input[@id='username']/..")

# 通過兄弟關系定位
element = driver.find_element(By.XPATH, "http://input[@id='username']/following-sibling::input")
element = driver.find_element(By.XPATH, "http://input[@id='password']/preceding-sibling::input")

# 按索引定位
element = driver.find_element(By.XPATH, "(//input[@type='text'])[2]")

# 使用軸(axes)
element = driver.find_element(By.XPATH, "http://input[@id='username']/ancestor::form")
element = driver.find_element(By.XPATH, "http://form/descendant::input")

CSS選擇器進階用法

# 基本選擇器
element = driver.find_element(By.CSS_SELECTOR, "#login-button")  # ID選擇器
element = driver.find_element(By.CSS_SELECTOR, ".login-form")    # Class選擇器
element = driver.find_element(By.CSS_SELECTOR, "input")          # 標簽選擇器

# 屬性選擇器
element = driver.find_element(By.CSS_SELECTOR, "input[name='username']")
element = driver.find_element(By.CSS_SELECTOR, "input[name^='user']")  # 以user開頭
element = driver.find_element(By.CSS_SELECTOR, "input[name$='name']")  # 以name結尾
element = driver.find_element(By.CSS_SELECTOR, "input[name*='erna']")  # 包含erna

# 組合選擇器
element = driver.find_element(By.CSS_SELECTOR, "form input[type='text']")
element = driver.find_element(By.CSS_SELECTOR, "form > input")  # 直接子元素
element = driver.find_element(By.CSS_SELECTOR, "label + input")  # 緊鄰兄弟元素
element = driver.find_element(By.CSS_SELECTOR, "label ~ input")  # 通用兄弟元素

# 偽類選擇器
element = driver.find_element(By.CSS_SELECTOR, "input:first-child")
element = driver.find_element(By.CSS_SELECTOR, "input:last-child")
element = driver.find_element(By.CSS_SELECTOR, "input:nth-child(2)")

相對定位(Selenium 4.x新特性)

from selenium.webdriver.support.relative_locator import locate_with

# 獲取參考元素
username_field = driver.find_element(By.ID, "username")

# 使用相對定位
password_field = driver.find_element(locate_with(By.TAG_NAME, "input").below(username_field))
login_button = driver.find_element(locate_with(By.TAG_NAME, "button").below(password_field))
remember_me = driver.find_element(locate_with(By.TAG_NAME, "input").to_right_of(password_field))
forgot_password = driver.find_element(locate_with(By.TAG_NAME, "a").above(login_button))

3. 查找多個元素

# 查找所有符合條件的元素
elements = driver.find_elements(By.CSS_SELECTOR, ".product-item")

# 遍歷元素列表
for element in elements:
    name = element.find_element(By.CLASS_NAME, "product-name").text
    price = element.find_element(By.CLASS_NAME, "product-price").text
    print(f"產(chǎn)品名稱: {name}, 價格: {price}")

4. 元素交互操作

# 輸入操作
element.send_keys("test@example.com")  # 輸入文本
element.send_keys(Keys.CONTROL, 'a')   # 鍵盤組合鍵(全選)
element.send_keys(Keys.BACK_SPACE)     # 退格鍵

# 點擊操作
element.click()                        # 點擊元素
element.submit()                       # 提交表單(適用于表單元素內(nèi))

# 清除操作
element.clear()                        # 清除文本輸入框

# 獲取元素屬性和狀態(tài)
value = element.get_attribute("value")  # 獲取屬性值
text = element.text                     # 獲取元素文本內(nèi)容
tag = element.tag_name                  # 獲取標簽名
size = element.size                     # 獲取元素大小
location = element.location             # 獲取元素位置
is_enabled = element.is_enabled()       # 元素是否啟用
is_selected = element.is_selected()     # 元素是否選中(復選框、單選按鈕等)
is_displayed = element.is_displayed()   # 元素是否可見

# 特殊元素操作
# 下拉菜單
from selenium.webdriver.support.select import Select
select = Select(driver.find_element(By.ID, "dropdown"))
select.select_by_visible_text("Option 1")  # 通過文本選擇
select.select_by_value("option1")         # 通過值選擇
select.select_by_index(1)                 # 通過索引選擇
options = select.options                  # 獲取所有選項
first_option = select.first_selected_option  # 獲取當前選中選項
select.deselect_all()                      # 取消所有選擇(多選下拉框)

# 復選框和單選按鈕
checkbox = driver.find_element(By.ID, "checkbox")
ifnot checkbox.is_selected():
    checkbox.click()

5. 元素查找最佳實踐

性能優(yōu)化順序:ID > Name > CSS > XPath

避免使用

  • 絕對XPath路徑(容易失效)
  • 基于視覺位置的選擇器
  • 多級嵌套CSS選擇器

推薦使用

  • 有意義的ID和名稱屬性
  • 數(shù)據(jù)測試屬性(如data-testid)
  • 短而明確的CSS選擇器

建議添加

  • 頁面加載和元素的等待機制
  • 查找元素的超時和重試機制
  • 詳細的錯誤處理機制

等待機制與異常處理

1. 等待策略

在Web自動化中,頁面加載和元素渲染需要時間,等待機制至關重要。

隱式等待(Implicit Wait)

# 設置隱式等待時間(全局設置)
driver.implicitly_wait(10)  # 等待最多10秒直到元素出現(xiàn)

隱式等待會在查找元素時自動等待一段時間直到元素出現(xiàn),如果在指定時間內(nèi)未找到元素,則拋出異常。

顯式等待(Explicit Wait)

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 等待元素可見
element = WebDriverWait(driver, 10).until(
    EC.visibility_of_element_located((By.ID, "element_id"))
)

# 等待元素可點擊
element = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.ID, "button_id"))
)

# 等待頁面標題包含特定文本
WebDriverWait(driver, 10).until(
    EC.title_contains("Home Page")
)

# 等待元素消失
WebDriverWait(driver, 10).until(
    EC.invisibility_of_element_located((By.CLASS_NAME, "loading"))
)

# 等待警告框出現(xiàn)
WebDriverWait(driver, 10).until(
    EC.alert_is_present()
)

# 等待元素的文本內(nèi)容滿足條件
WebDriverWait(driver, 10).until(
    EC.text_to_be_present_in_element((By.ID, "status"), "Success")
)

# 等待元素的屬性值滿足條件
WebDriverWait(driver, 10).until(
    EC.text_to_be_present_in_element_attribute((By.ID, "input"), "value", "text")
)

自定義等待條件

from selenium.webdriver.support.ui import WebDriverWait

# 自定義等待條件
def element_has_class(element, class_name):
    return class_name in element.get_attribute("class").split()

# 使用自定義等待條件
element = driver.find_element(By.ID, "myElement")
WebDriverWait(driver, 10).until(lambda driver: element_has_class(element, "active"))

流暢等待(FluentWait)

from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException

# 創(chuàng)建FluentWait實例
wait = WebDriverWait(
    driver,
    timeout=30,
    poll_frequency=2,  # 每2秒檢查一次
    ignored_exceptions=[NoSuchElementException, StaleElementReferenceException]
)

# 使用FluentWait
element = wait.until(EC.element_to_be_clickable((By.ID, "myElement")))

2. 異常處理

Selenium操作可能會觸發(fā)各種異常,合理的異常處理可以提高腳本的健壯性。

常見異常類型

from selenium.common.exceptions import (
    NoSuchElementException,  # 元素未找到
    TimeoutException,        # 等待超時
    ElementNotVisibleException,  # 元素不可見
    ElementNotInteractableException,  # 元素不可交互
    StaleElementReferenceException,  # 元素已過時(DOM已更新)
    WebDriverException,      # WebDriver通用異常
    InvalidSelectorException,  # 無效的選擇器
    UnexpectedAlertPresentException,  # 意外的警告框
    NoAlertPresentException,  # 沒有警告框
    SessionNotCreatedException,  # 會話創(chuàng)建失敗
    ElementClickInterceptedException  # 元素點擊被攔截
)

基本異常處理

try:
    element = driver.find_element(By.ID, "non_existent_element")
    element.click()
except NoSuchElementException:
    print("元素未找到")
except ElementNotInteractableException:
    print("元素不可交互")
except Exception as e:
    print(f"發(fā)生其他異常: {e}")

重試機制

def retry_click(driver, by, value, max_attempts=3, wait_time=1):
    """
    嘗試多次點擊元素
    """
    from time import sleep
    
    for attempt in range(max_attempts):
        try:
            element = driver.find_element(by, value)
            element.click()
            returnTrue
        except (NoSuchElementException, ElementNotInteractableException, 
                ElementClickInterceptedException, StaleElementReferenceException) as e:
            if attempt == max_attempts - 1:
                print(f"無法點擊元素,錯誤: {e}")
                returnFalse
            sleep(wait_time)
    returnFalse

處理StaleElementReferenceException

def get_fresh_element(driver, by, value):
    """
    獲取一個新鮮的元素引用,避免StaleElementReferenceException
    """
    try:
        return driver.find_element(by, value)
    except StaleElementReferenceException:
        # 重新查找元素
        return driver.find_element(by, value)

使用裝飾器處理異常

import functools
from time import sleep

def retry(max_attempts=3, wait_time=1):
    """
    函數(shù)重試裝飾器
    """
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except (NoSuchElementException, ElementNotInteractableException, 
                        StaleElementReferenceException) as e:
                    if attempt == max_attempts - 1:
                        raise e
                    sleep(wait_time)
        return wrapper
    return decorator

# 使用裝飾器
@retry(max_attempts=5, wait_time=2)
def click_element(driver, by, value):
    driver.find_element(by, value).click()

3. 等待策略最佳實踐

  • 避免使用time.sleep()不靈活且低效
  • 優(yōu)先使用顯式等待:更精確,可控性更強
  • 結合使用隱式等待和顯式等待:隱式等待作為全局保護,顯式等待針對特定場景
  • 設置合理的超時時間:不要過長或過短
  • 捕獲并處理超時異常:提供適當?shù)幕謴蜋C制或用戶友好的錯誤信息
  • 為不同網(wǎng)絡環(huán)境調(diào)整等待策略:可配置的超時參數(shù)

面向對象封裝與框架設計

1. 頁面對象模型(Page Object Model, POM)

頁面對象模型是一種設計模式,將頁面的元素和操作封裝在類中,使測試代碼更加清晰和可維護。

基本POM結構

class BasePage:
    """
    所有頁面的基類
    """
    def __init__(self, driver):
        self.driver = driver
    
    def find_element(self, locator):
        return self.driver.find_element(*locator)
    
    def find_elements(self, locator):
        return self.driver.find_elements(*locator)
    
    def click(self, locator):
        self.find_element(locator).click()
    
    def input_text(self, locator, text):
        element = self.find_element(locator)
        element.clear()
        element.send_keys(text)
    
    def get_text(self, locator):
        return self.find_element(locator).text
    
    def is_element_present(self, locator):
        try:
            self.find_element(locator)
            returnTrue
        except NoSuchElementException:
            returnFalse
    
    def wait_for_element(self, locator, timeout=10):
        try:
            WebDriverWait(self.driver, timeout).until(
                EC.presence_of_element_located(locator)
            )
            returnTrue
        except TimeoutException:
            returnFalse


class LoginPage(BasePage):
    """
    登錄頁面對象
    """
    # 頁面元素定位
    _username_field = (By.ID, "username")
    _password_field = (By.ID, "password")
    _login_button = (By.ID, "login_button")
    _error_message = (By.CLASS_NAME, "error-message")
    
    def __init__(self, driver):
        super().__init__(driver)
        self.driver.get("https://example.com/login")
    
    def enter_username(self, username):
        self.input_text(self._username_field, username)
        return self
    
    def enter_password(self, password):
        self.input_text(self._password_field, password)
        return self
    
    def click_login(self):
        self.click(self._login_button)
        # 根據(jù)登錄結果返回不同的頁面對象
        if"dashboard"in self.driver.current_url:
            return DashboardPage(self.driver)
        return self
    
    def login(self, username, password):
        self.enter_username(username)
        self.enter_password(password)
        return self.click_login()
    
    def get_error_message(self):
        if self.is_element_present(self._error_message):
            return self.get_text(self._error_message)
        return""


class DashboardPage(BasePage):
    """
    儀表盤頁面對象
    """
    _welcome_message = (By.ID, "welcome")
    _logout_button = (By.ID, "logout")
    
    def is_loaded(self):
        return self.wait_for_element(self._welcome_message)
    
    def get_welcome_message(self):
        return self.get_text(self._welcome_message)
    
    def logout(self):
        self.click(self._logout_button)
        return LoginPage(self.driver)

使用POM進行測試

def test_login_success():
    driver = webdriver.Chrome()
    try:
        login_page = LoginPage(driver)
        dashboard_page = login_page.login("valid_user", "valid_password")
        
        assert dashboard_page.is_loaded()
        assert"Welcome"in dashboard_page.get_welcome_message()
    finally:
        driver.quit()

def test_login_failure():
    driver = webdriver.Chrome()
    try:
        login_page = LoginPage(driver)
        result_page = login_page.login("invalid_user", "invalid_password")
        
        assert isinstance(result_page, LoginPage)
        assert"Invalid credentials"in result_page.get_error_message()
    finally:
        driver.quit()

2. 測試框架集成

與unittest集成

import unittest
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

class TestLogin(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
        self.driver.maximize_window()
        self.login_page = LoginPage(self.driver)
    
    def tearDown(self):
        self.driver.quit()
    
    def test_valid_login(self):
        dashboard_page = self.login_page.login("valid_user", "valid_password")
        self.assertTrue(dashboard_page.is_loaded())
        self.assertIn("Welcome", dashboard_page.get_welcome_message())
    
    def test_invalid_login(self):
        result_page = self.login_page.login("invalid_user", "invalid_password")
        self.assertIsInstance(result_page, LoginPage)
        self.assertIn("Invalid credentials", result_page.get_error_message())

if __name__ == "__main__":
    unittest.main()

與pytest集成

import pytest
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

@pytest.fixture
def driver():
    # 設置
    driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
    driver.maximize_window()
    yield driver
    # 清理
    driver.quit()

@pytest.fixture
def login_page(driver):
    return LoginPage(driver)

def test_valid_login(login_page):
    dashboard_page = login_page.login("valid_user", "valid_password")
    assert dashboard_page.is_loaded()
    assert"Welcome"in dashboard_page.get_welcome_message()

def test_invalid_login(login_page):
    result_page = login_page.login("invalid_user", "invalid_password")
    assert isinstance(result_page, LoginPage)
    assert"Invalid credentials"in result_page.get_error_message()

與Behave(BDD)集成

# features/login.feature
Feature: User Login
  As a user
  I want to be able to login to the application
  So that I can access my account

  Scenario: Successful login with valid credentials
    Given the user is on the login page
    When the user enters "valid_user"as username
    And the user enters "valid_password"as password
    And the user clicks the login button
    Then the user should be redirected to the dashboard
    And the dashboard should display a welcome message

  Scenario: Failed login with invalid credentials
    Given the user is on the login page
    When the user enters "invalid_user"as username
    And the user enters "invalid_password"as password
    And the user clicks the login button
    Then the user should remain on the login page
    And an error message should be displayed
# steps/login_steps.py
from behave import given, when, then
from pages.login_page import LoginPage
from pages.dashboard_page import DashboardPage

@given('the user is on the login page')
def step_impl(context):
    context.login_page = LoginPage(context.driver)

@when('the user enters "{username}" as username')
def step_impl(context, username):
    context.login_page.enter_username(username)

@when('the user enters "{password}" as password')
def step_impl(context, password):
    context.login_page.enter_password(password)

@when('the user clicks the login button')
def step_impl(context):
    context.result_page = context.login_page.click_login()

@then('the user should be redirected to the dashboard')
def step_impl(context):
    assert isinstance(context.result_page, DashboardPage)

@then('the dashboard should display a welcome message')
def step_impl(context):
    assert"Welcome"in context.result_page.get_welcome_message()

@then('the user should remain on the login page')
def step_impl(context):
    assert isinstance(context.result_page, LoginPage)

@then('an error message should be displayed')
def step_impl(context):
    assert"Invalid credentials"in context.result_page.get_error_message()

3. 高級框架設計模式

工廠模式

class PageFactory:
    """
    頁面對象工廠類
    """
    @staticmethod
    def get_page(page_name, driver):
        pages = {
            "login": LoginPage,
            "dashboard": DashboardPage,
            "profile": ProfilePage,
            "settings": SettingsPage
        }
        
        if page_name.lower() notin pages:
            raise ValueError(f"不支持的頁面: {page_name}")
        
        return pages[page_name.lower()](driver)

單例模式(驅動管理器)

class WebDriverManager:
    """
    WebDriver管理器(單例模式)
    """
    _instance = None
    
    def __new__(cls):
        if cls._instance isNone:
            cls._instance = super(WebDriverManager, cls).__new__(cls)
            cls._instance.driver = None
        return cls._instance
    
    def get_driver(self, browser="chrome"):
        if self.driver isNone:
            if browser.lower() == "chrome":
                self.driver = webdriver.Chrome()
            elif browser.lower() == "firefox":
                self.driver = webdriver.Firefox()
            else:
                raise ValueError(f"不支持的瀏覽器: {browser}")
            
            self.driver.maximize_window()
            self.driver.implicitly_wait(10)
        
        return self.driver
    
    def quit(self):
        if self.driver:
            self.driver.quit()
            self.driver = None

策略模式(等待策略)

from abc import ABC, abstractmethod

class WaitStrategy(ABC):
    """
    等待策略基類
    """
    @abstractmethod
    def wait_for(self, driver, locator):
        pass

class VisibilityStrategy(WaitStrategy):
    """
    等待元素可見策略
    """
    def wait_for(self, driver, locator, timeout=10):
        return WebDriverWait(driver, timeout).until(
            EC.visibility_of_element_located(locator)
        )

class ClickableStrategy(WaitStrategy):
    """
    等待元素可點擊策略
    """
    def wait_for(self, driver, locator, timeout=10):
        return WebDriverWait(driver, timeout).until(
            EC.element_to_be_clickable(locator)
        )

class PresenceStrategy(WaitStrategy):
    """
    等待元素存在策略
    """
    def wait_for(self, driver, locator, timeout=10):
        return WebDriverWait(driver, timeout).until(
            EC.presence_of_element_located(locator)
        )

# 使用策略模式的高級頁面基類
class AdvancedBasePage:
    def __init__(self, driver):
        self.driver = driver
        self.wait_strategies = {
            "visible": VisibilityStrategy(),
            "clickable": ClickableStrategy(),
            "present": PresenceStrategy()
        }
    
    def find_element(self, locator, strategy="present"):
        return self.wait_strategies[strategy].wait_for(self.driver, locator)

4. 配置與日志管理

配置管理

import json
import os

class ConfigManager:
    """
    配置管理器
    """
    _instance = None
    
    def __new__(cls):
        if cls._instance isNone:
            cls._instance = super(ConfigManager, cls).__new__(cls)
            cls._instance.config = {}
            cls._instance.load_config()
        return cls._instance
    
    def load_config(self, config_file="config.json"):
        if os.path.exists(config_file):
            with open(config_file, "r") as f:
                self.config = json.load(f)
        else:
            # 默認配置
            self.config = {
                "browser": "chrome",
                "implicit_wait": 10,
                "explicit_wait": 20,
                "base_url": "https://example.com",
                "headless": False,
                "screenshots_dir": "screenshots",
                "logs_dir": "logs"
            }
    
    def get(self, key, default=None):
        return self.config.get(key, default)

日志管理

import logging
import os
from datetime import datetime

class LogManager:
    """
    日志管理器
    """
    _instance = None
    
    def __new__(cls):
        if cls._instance isNone:
            cls._instance = super(LogManager, cls).__new__(cls)
            cls._instance.setup_logger()
        return cls._instance
    
    def setup_logger(self):
        config = ConfigManager().get("logs", {})
        logs_dir = config.get("dir", "logs")
        log_level = config.get("level", "INFO")
        
        ifnot os.path.exists(logs_dir):
            os.makedirs(logs_dir)
        
        log_file = os.path.join(logs_dir, f"test_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log")
        
        # 設置日志級別映射
        level_map = {
            "DEBUG": logging.DEBUG,
            "INFO": logging.INFO,
            "WARNING": logging.WARNING,
            "ERROR": logging.ERROR,
            "CRITICAL": logging.CRITICAL
        }
        
        # 設置根日志記錄器
        self.logger = logging.getLogger("selenium_framework")
        self.logger.setLevel(level_map.get(log_level.upper(), logging.INFO))
        
        # 文件處理器
        file_handler = logging.FileHandler(log_file)
        file_handler.setLevel(level_map.get(log_level.upper(), logging.INFO))
        
        # 控制臺處理器
        console_handler = logging.StreamHandler()
        console_handler.setLevel(level_map.get(log_level.upper(), logging.INFO))
        
        # 日志格式
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        file_handler.setFormatter(formatter)
        console_handler.setFormatter(formatter)
        
        # 添加處理器
        self.logger.addHandler(file_handler)
        self.logger.addHandler(console_handler)
    
    def get_logger(self):
        return self.logger

進階技巧與最佳實踐

1. 高級交互操作

ActionChains高級操作

from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys

# 基本鼠標操作
def perform_hover(driver, element):
    """執(zhí)行懸停操作"""
    ActionChains(driver).move_to_element(element).perform()

def perform_right_click(driver, element):
    """執(zhí)行右鍵點擊操作"""
    ActionChains(driver).context_click(element).perform()

def perform_double_click(driver, element):
    """執(zhí)行雙擊操作"""
    ActionChains(driver).double_click(element).perform()

def perform_drag_and_drop(driver, source_element, target_element):
    """執(zhí)行拖放操作"""
    ActionChains(driver).drag_and_drop(source_element, target_element).perform()

def perform_drag_and_drop_by_offset(driver, element, x_offset, y_offset):
    """執(zhí)行偏移拖放操作"""
    ActionChains(driver).drag_and_drop_by_offset(element, x_offset, y_offset).perform()

# 組合鍵盤操作
def perform_ctrl_click(driver, element):
    """執(zhí)行Ctrl+點擊操作(多選)"""
    ActionChains(driver).key_down(Keys.CONTROL).click(element).key_up(Keys.CONTROL).perform()

def perform_shift_click(driver, element):
    """執(zhí)行Shift+點擊操作(范圍選擇)"""
    ActionChains(driver).key_down(Keys.SHIFT).click(element).key_up(Keys.SHIFT).perform()

def perform_select_all(driver):
    """執(zhí)行全選操作(Ctrl+A)"""
    ActionChains(driver).key_down(Keys.CONTROL).send_keys('a').key_up(Keys.CONTROL).perform()

def perform_copy(driver):
    """執(zhí)行復制操作(Ctrl+C)"""
    ActionChains(driver).key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()

def perform_paste(driver):
    """執(zhí)行粘貼操作(Ctrl+V)"""
    ActionChains(driver).key_down(Keys.CONTROL).send_keys('v').key_up(Keys.CONTROL).perform()

# 鏈式組合操作
def perform_complex_action(driver, element1, element2):
    """執(zhí)行復雜組合操作"""
    ActionChains(driver)\
        .move_to_element(element1)\
        .pause(1)  # 暫停1秒
        .click()\
        .move_to_element(element2)\
        .click()\
        .perform()

處理JavaScript事件

def trigger_js_event(driver, element, event_name):
    """觸發(fā)JavaScript事件"""
    js_code = f"arguments[0].dispatchEvent(new Event('{event_name}'));"
    driver.execute_script(js_code, element)

def focus_element(driver, element):
    """使元素獲取焦點"""
    driver.execute_script("arguments[0].focus();", element)

def blur_element(driver, element):
    """使元素失去焦點"""
    driver.execute_script("arguments[0].blur();", element)

def scroll_to_element(driver, element):
    """滾動到元素位置"""
    driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", element)

def scroll_to_top(driver):
    """滾動到頁面頂部"""
    driver.execute_script("window.scrollTo(0, 0);")

def scroll_to_bottom(driver):
    """滾動到頁面底部"""
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

2. 窗口與標簽頁管理

def switch_to_window_by_title(driver, title):
    """切換到指定標題的窗口"""
    current_window = driver.current_window_handle
    for window in driver.window_handles:
        driver.switch_to.window(window)
        if title in driver.title:
            returnTrue
    # 如果沒有找到匹配標題的窗口,切回原窗口
    driver.switch_to.window(current_window)
    returnFalse

def switch_to_window_by_url(driver, url_part):
    """切換到URL包含指定部分的窗口"""
    current_window = driver.current_window_handle
    for window in driver.window_handles:
        driver.switch_to.window(window)
        if url_part in driver.current_url:
            returnTrue
    # 如果沒有找到匹配URL的窗口,切回原窗口
    driver.switch_to.window(current_window)
    returnFalse

def close_all_windows_except_current(driver):
    """關閉除當前窗口外的所有窗口"""
    current_window = driver.current_window_handle
    for window in driver.window_handles:
        if window != current_window:
            driver.switch_to.window(window)
            driver.close()
    driver.switch_to.window(current_window)

def open_new_tab(driver, url=None):
    """打開新標簽頁"""
    driver.execute_script("window.open();")
    driver.switch_to.window(driver.window_handles[-1])
    if url:
        driver.get(url)

def handle_popup_window(driver, action="accept"):
    """處理彈出窗口"""
    try:
        if action.lower() == "accept":
            driver.switch_to.alert.accept()
        elif action.lower() == "dismiss":
            driver.switch_to.alert.dismiss()
        elif action.lower() == "text":
            return driver.switch_to.alert.text
        else:
            raise ValueError(f"不支持的操作: {action}")
        returnTrue
    except:
        returnFalse

3. iframe處理

def switch_to_frame_by_index(driver, index):
    """通過索引切換到iframe"""
    try:
        driver.switch_to.frame(index)
        returnTrue
    except:
        returnFalse

def switch_to_frame_by_name_or_id(driver, name_or_id):
    """通過名稱或ID切換到iframe"""
    try:
        driver.switch_to.frame(name_or_id)
        returnTrue
    except:
        returnFalse

def switch_to_frame_by_element(driver, element):
    """通過元素切換到iframe"""
    try:
        driver.switch_to.frame(element)
        returnTrue
    except:
        returnFalse

def switch_to_parent_frame(driver):
    """切換到父iframe"""
    try:
        driver.switch_to.parent_frame()
        returnTrue
    except:
        returnFalse

def switch_to_default_content(driver):
    """切換到主文檔"""
    try:
        driver.switch_to.default_content()
        returnTrue
    except:
        returnFalse

def get_iframe_count(driver):
    """獲取頁面中iframe的數(shù)量"""
    return len(driver.find_elements(By.TAG_NAME, "iframe"))

def execute_in_iframe(driver, iframe_locator, action_func):
    """在iframe中執(zhí)行操作"""
    driver.switch_to.frame(driver.find_element(*iframe_locator))
    try:
        result = action_func(driver)
        return result
    finally:
        driver.switch_to.default_content()

4. 文件上傳與下載

文件上傳

def upload_file(driver, file_input_locator, file_path):
    """
    上傳文件(適用于<input type="file">元素)
    """
    try:
        file_input = driver.find_element(*file_input_locator)
        file_input.send_keys(file_path)
        returnTrue
    except Exception as e:
        print(f"文件上傳失敗: {e}")
        returnFalse

def upload_file_without_input(driver, upload_button_locator, file_path):
    """
    上傳文件(適用于沒有可見<input type="file">的情況)
    使用JS創(chuàng)建一個隱藏的文件輸入元素
    """
    try:
        # 創(chuàng)建一個隱藏的文件輸入元素
        js_script = """
        const input = document.createElement('input');
        input.type = 'file';
        input.style.display = 'none';
        input.id = 'hidden-file-input';
        document.body.appendChild(input);
        return input;
        """
        file_input = driver.execute_script(js_script)
        
        # 設置文件路徑
        file_input.send_keys(file_path)
        
        # 觸發(fā)上傳按鈕的點擊事件
        upload_button = driver.find_element(*upload_button_locator)
        driver.execute_script("arguments[0].click();", upload_button)
        
        # 移除隱藏的文件輸入元素
        driver.execute_script("document.getElementById('hidden-file-input').remove();")
        
        returnTrue
    except Exception as e:
        print(f"文件上傳失敗: {e}")
        returnFalse

文件下載

import os
import time
from pathlib import Path

def setup_chrome_download_path(download_dir):
    """
    設置Chrome瀏覽器的下載路徑
    """
    options = webdriver.ChromeOptions()
    prefs = {
        "download.default_directory": download_dir,
        "download.prompt_for_download": False,
        "download.directory_upgrade": True,
        "safebrowsing.enabled": True
    }
    options.add_experimental_option("prefs", prefs)
    return options

def wait_for_download_to_complete(download_dir, timeout=60, check_interval=1):
    """
    等待下載完成
    """
    start_time = time.time()
    while time.time() - start_time < timeout:
        # 檢查是否有部分下載的文件(.crdownload, .part等)
        downloading_files = list(Path(download_dir).glob("*.crdownload")) + list(Path(download_dir).glob("*.part"))
        ifnot downloading_files:
            # 找出最近下載的文件
            downloaded_files = list(Path(download_dir).glob("*"))
            if downloaded_files:
                downloaded_files.sort(key=lambda x: x.stat().st_mtime, reverse=True)
                return str(downloaded_files[0])
        time.sleep(check_interval)
    raise TimeoutError("文件下載超時")

def download_file(driver, download_button_locator, download_dir, timeout=60):
    """
    下載文件
    """
    try:
        # 確保下載目錄存在
        os.makedirs(download_dir, exist_ok=True)
        
        # 點擊下載按鈕
        download_button = driver.find_element(*download_button_locator)
        download_button.click()
        
        # 等待下載完成
        downloaded_file = wait_for_download_to_complete(download_dir, timeout)
        return downloaded_file
    except Exception as e:
        print(f"文件下載失敗: {e}")
        returnNone

5. 截圖與日志

import os
import time
from datetime import datetime

def take_screenshot(driver, directory="screenshots", filename=None):
    """
    截取屏幕截圖
    """
    try:
        # 確保目錄存在
        os.makedirs(directory, exist_ok=True)
        
        # 如果未指定文件名,使用時間戳生成
        ifnot filename:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"screenshot_{timestamp}.png"
        
        # 拼接完整路徑
        file_path = os.path.join(directory, filename)
        
        # 截圖
        driver.save_screenshot(file_path)
        return file_path
    except Exception as e:
        print(f"截圖失敗: {e}")
        returnNone

def take_element_screenshot(driver, element, directory="screenshots", filename=None):
    """
    截取元素截圖
    """
    try:
        # 確保目錄存在
        os.makedirs(directory, exist_ok=True)
        
        # 如果未指定文件名,使用時間戳生成
        ifnot filename:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"element_screenshot_{timestamp}.png"
        
        # 拼接完整路徑
        file_path = os.path.join(directory, filename)
        
        # 截取元素截圖
        element.screenshot(file_path)
        return file_path
    except Exception as e:
        print(f"元素截圖失敗: {e}")
        returnNone

def screenshot_on_failure(func):
    """
    失敗時自動截圖的裝飾器
    """
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            # 假設第一個參數(shù)是self,第二個參數(shù)是driver
            driver = args[1] if len(args) > 1elseNone
            if driver:
                timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
                filename = f"failure_{func.__name__}_{timestamp}.png"
                take_screenshot(driver, filename=filename)
            raise e
    return wrapper

6. 高級斷言與驗證

def verify_element_text(driver, locator, expected_text, contains=False):
    """
    驗證元素文本
    """
    try:
        element = driver.find_element(*locator)
        actual_text = element.text
        if contains:
            assert expected_text in actual_text, f"期望文本包含'{expected_text}',實際文本為'{actual_text}'"
        else:
            assert actual_text == expected_text, f"期望文本為'{expected_text}',實際文本為'{actual_text}'"
        returnTrue
    except AssertionError as e:
        print(f"驗證失敗: {e}")
        returnFalse

def verify_element_attribute(driver, locator, attribute, expected_value, contains=False):
    """
    驗證元素屬性
    """
    try:
        element = driver.find_element(*locator)
        actual_value = element.get_attribute(attribute)
        if contains:
            assert expected_value in actual_value, f"期望屬性'{attribute}'包含'{expected_value}',實際值為'{actual_value}'"
        else:
            assert actual_value == expected_value, f"期望屬性'{attribute}'為'{expected_value}',實際值為'{actual_value}'"
        returnTrue
    except AssertionError as e:
        print(f"驗證失敗: {e}")
        returnFalse

def verify_element_visible(driver, locator, timeout=10):
    """
    驗證元素可見
    """
    try:
        WebDriverWait(driver, timeout).until(EC.visibility_of_element_located(locator))
        returnTrue
    except TimeoutException:
        print(f"元素在{timeout}秒內(nèi)未可見: {locator}")
        returnFalse

def verify_element_not_visible(driver, locator, timeout=10):
    """
    驗證元素不可見
    """
    try:
        WebDriverWait(driver, timeout).until(EC.invisibility_of_element_located(locator))
        returnTrue
    except TimeoutException:
        print(f"元素在{timeout}秒內(nèi)仍然可見: {locator}")
        returnFalse

def verify_url(driver, expected_url, contains=False, timeout=10):
    """
    驗證URL
    """
    try:
        if contains:
            WebDriverWait(driver, timeout).until(lambda d: expected_url in d.current_url)
        else:
            WebDriverWait(driver, timeout).until(lambda d: d.current_url == expected_url)
        returnTrue
    except TimeoutException:
        print(f"URL驗證失敗,期望URL{'' if contains else '為'}{expected_url},實際URL為{driver.current_url}")
        returnFalse

def verify_title(driver, expected_title, contains=False, timeout=10):
    """
    驗證頁面標題
    """
    try:
        if contains:
            WebDriverWait(driver, timeout).until(lambda d: expected_title in d.title)
        else:
            WebDriverWait(driver, timeout).until(lambda d: d.title == expected_title)
        returnTrue
    except TimeoutException:
        print(f"標題驗證失敗,期望標題{'' if contains else '為'}{expected_title},實際標題為{driver.title}")
        returnFalse

性能優(yōu)化與調(diào)試技巧

1. 性能測試與優(yōu)化

測量頁面加載時間

def measure_page_load_time(driver, url):
    """
    測量頁面加載時間
    """
    start_time = time.time()
    driver.get(url)
    
    # 等待頁面完全加載
    WebDriverWait(driver, 60).until(
        lambda d: d.execute_script("return document.readyState") == "complete"
    )
    
    end_time = time.time()
    load_time = end_time - start_time
    
    return load_time

使用Performance API獲取詳細性能數(shù)據(jù)

def get_performance_metrics(driver):
    """
    獲取瀏覽器性能指標
    """
    # 使用Navigation Timing API
    navigation_timing = driver.execute_script("""
        var performance = window.performance;
        var timingObj = performance.timing;
        var loadTime = timingObj.loadEventEnd - timingObj.navigationStart;
        var dnsTime = timingObj.domainLookupEnd - timingObj.domainLookupStart;
        var tcpTime = timingObj.connectEnd - timingObj.connectStart;
        var serverTime = timingObj.responseEnd - timingObj.requestStart;
        var domTime = timingObj.domComplete - timingObj.domLoading;
        
        return {
            'loadTime': loadTime,
            'dnsTime': dnsTime,
            'tcpTime': tcpTime,
            'serverTime': serverTime,
            'domTime': domTime,
            'firstPaint': timingObj.responseStart - timingObj.navigationStart,
            'ttfb': timingObj.responseStart - timingObj.requestStart
        };
    """)
    
    return navigation_timing

def get_resource_timing(driver):
    """
    獲取資源加載時間
    """
    resources = driver.execute_script("""
        var resources = window.performance.getEntriesByType('resource');
        return resources.map(function(resource) {
            return {
                'name': resource.name,
                'startTime': resource.startTime,
                'duration': resource.duration,
                'initiatorType': resource.initiatorType,
                'size': resource.transferSize
            };
        });
    """)
    
    return resources

優(yōu)化執(zhí)行速度

def optimize_chrome_for_performance():
    """
    優(yōu)化Chrome瀏覽器以提高性能
    """
    options = webdriver.ChromeOptions()
    
    # 禁用不必要的瀏覽器功能
    options.add_argument("--disable-extensions")
    options.add_argument("--disable-gpu")
    options.add_argument("--disable-dev-shm-usage")
    options.add_argument("--disable-browser-side-navigation")
    options.add_argument("--disable-infobars")
    options.add_argument("--disable-notifications")
    options.add_argument("--disable-popup-blocking")
    
    # 減少內(nèi)存使用
    options.add_argument("--disable-features=site-per-process")
    options.add_argument("--process-per-site")
    
    # 禁用圖片加載以提高速度
    prefs = {
        "profile.managed_default_content_settings.images": 2,
        "profile.default_content_setting_values.notifications": 2,
        "profile.default_content_setting_values.geolocation": 2
    }
    options.add_experimental_option("prefs", prefs)
    
    # 使用無頭模式
    options.add_argument("--headless")
    
    return options

2. 高級調(diào)試技巧

獲取瀏覽器控制臺日志

def get_browser_logs(driver):
    """
    獲取瀏覽器控制臺日志
    """
    logs = driver.get_log('browser')
    return logs

def print_browser_logs(driver):
    """
    打印瀏覽器控制臺日志
    """
    logs = driver.get_log('browser')
    for log in logs:
        print(f"[{log['level']}] {log['message']}")

以上就是從入門到精通介紹Python中Selenium安裝使用的完整指南的詳細內(nèi)容,更多關于Python Selenium的資料請關注腳本之家其它相關文章!

相關文章

  • python實現(xiàn)學生管理系統(tǒng)

    python實現(xiàn)學生管理系統(tǒng)

    這篇文章主要為大家詳細介紹了python實現(xiàn)學生管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 一文帶你搞懂Python上下文管理器

    一文帶你搞懂Python上下文管理器

    這篇文章主要為大家介紹了Python上下文管理器,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • Python高級排序sort()函數(shù)使用技巧實例探索

    Python高級排序sort()函數(shù)使用技巧實例探索

    本文詳細介紹sort()函數(shù)的使用,包括基本排序、自定義排序、逆序排序等多種情況,并提供大量示例代碼,以幫助你充分理解和掌握這一函數(shù)的用法,探索更多sort()排序函數(shù)的作用
    2024-01-01
  • Python計算時間間隔(精確到微妙)的代碼實例

    Python計算時間間隔(精確到微妙)的代碼實例

    今天小編就為大家分享一篇關于Python計算時間間隔(精確到微妙)的代碼實例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • python geemap的安裝步驟及環(huán)境配置

    python geemap的安裝步驟及環(huán)境配置

    geemap是基于GEE由吳秋生老師二次開發(fā)的一個包,geemap主要使用python來進行實現(xiàn)相關功能,這篇文章主要介紹了geemap的詳細安裝步驟及環(huán)境配置,需要的朋友可以參考下
    2022-08-08
  • Opencv實現(xiàn)二維直方圖的計算及繪制

    Opencv實現(xiàn)二維直方圖的計算及繪制

    這篇博客將介紹如何使用Opencv進行二維直方圖的計算及繪制,維直方圖可以讓我們對不同的像素密度有更好的了解,感興趣的可以了解一下
    2021-07-07
  • 基于Python實現(xiàn)火車票搶票軟件

    基于Python實現(xiàn)火車票搶票軟件

    每年的節(jié)假日一到,大家頭疼的總時同一個問題:你買到回家的票了嗎?尤其是大型的節(jié)日:國慶、春節(jié)等。本文將利用Python編寫一個火車票搶票軟件,感興趣的可以了解一下
    2022-07-07
  • 使用python實現(xiàn)學生信息管理系統(tǒng)

    使用python實現(xiàn)學生信息管理系統(tǒng)

    這篇文章主要為大家詳細介紹了使用python實現(xiàn)學生信息管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-02-02
  • Python解析庫pyquery 的使用詳解

    Python解析庫pyquery 的使用詳解

    要是你接觸過Web開發(fā),平時習慣用CSS選擇器,或者對jQuery有一定了解,那我得給你介紹一個更稱手的解析庫,它就是pyquery,本文給大家介紹Python解析庫pyquery 的使用詳解,感興趣的朋友一起看看吧
    2025-04-04
  • Python 中如何實現(xiàn)參數(shù)化測試的方法示例

    Python 中如何實現(xiàn)參數(shù)化測試的方法示例

    這篇文章主要介紹了Python 中如何實現(xiàn)參數(shù)化測試的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-12-12

最新評論

巴马| 隆尧县| 通渭县| 盐边县| 石狮市| 美姑县| 喜德县| 广南县| 类乌齐县| 闵行区| 汨罗市| 曲松县| 离岛区| 石林| 十堰市| 鹤山市| 曲靖市| 博野县| 铁力市| 仁怀市| 洞头县| 林芝县| 金溪县| 和静县| 沙坪坝区| 六安市| 鄂托克前旗| 福贡县| 武陟县| 耿马| 布拖县| 太原市| 宁都县| 盐山县| 逊克县| 东莞市| 台前县| 云南省| 日喀则市| 蒙山县| 阿巴嘎旗|