Selenium使用超全指南

🍅?點擊文末小卡片?,免費獲取軟件測試全套資料,資料在手,漲薪更快

概述

selenium是網頁應用中最流行的自動化測試工具,可以用來做自動化測試或者瀏覽器爬蟲等。官網地址為:相對于另外一款web自動化測試工具QTP來說有如下優點:

  • 免費開源輕量級,不同語言只需要一個體積很小的依賴包
  • 支持多種系統,包括Windows,Mac,Linux
  • 支持多種瀏覽器,包括Chrome,FireFox,IE,safari,opera等
  • 支持多語言,包括Java,C,python,c#等主流語言
  • 支持分布式測試用例執行

python+selenium環境安裝

首先需要安裝python(推薦3.7+)環境,然后直接用pip install selenium安裝依賴包即可。

另外還需要下載瀏覽器相應的webdriver驅動程序,注意下載的驅動版本一定要匹配瀏覽器版本。

  • Firefox瀏覽器驅動:
  • Chrome瀏覽器驅動:
  • IE瀏覽器驅動:
  • Edge瀏覽器驅動:
  • Opera瀏覽器驅動:

下載以后可以把驅動程序加到環境變量,這樣使用時就不用手動指定驅動程序路徑。

使用selenium啟動瀏覽器

可以在python中使用下面的代碼啟動一個Chrome瀏覽器,然后控制這個瀏覽器的行為或者讀取數據。

from selenium import webdriver# 啟動Chrome瀏覽器,要求chromedriver驅動程序已經配置到環境變量
# 將驅動程序和當前腳本放在同一個文件夾也可以
driver = webdriver.Chrome()# 手動指定驅動程序路徑
driver = webdriver.Chrome(r'D:/uusama/tools/chromedriver.exe')driver = webdriver.Ie()        # Internet Explorer瀏覽器
driver = webdriver.Edge()      # Edge瀏覽器
driver = webdriver.Opera()     # Opera瀏覽器
driver = webdriver.PhantomJS()   # PhantomJSdriver.get('http://uusama.com')  # 打開指定路徑的頁面

啟動的時候還可以設置啟動參數,比如下面的代碼實現啟動時添加代理,并且忽略https證書校驗。

from selenium import webdriver# 創建chrome啟動選項對象
options = webdriver.ChromeOptions()options.add_argument("--proxy-server=127.0.0.1:16666")  # 設置代理
options.add_argument("---ignore-certificate-errors")  # 設置忽略https證書校驗
options.add_experimental_option("excludeSwitches", ["enable-logging"])  # 啟用日志# 設置瀏覽器下載文件時保存的默認路徑
prefs = {"download.default_directory": get_download_dir()}
options.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(options=options)

啟動的時候還可以設置啟動參數,比如下面的代碼實現啟動時添加代理,并且忽略https證書校驗。

from selenium import webdriver# 創建chrome啟動選項對象
options = webdriver.ChromeOptions()options.add_argument("--proxy-server=127.0.0.1:16666")  # 設置代理
options.add_argument("---ignore-certificate-errors")  # 設置忽略https證書校驗
options.add_experimental_option("excludeSwitches", ["enable-logging"])  # 啟用日志# 設置瀏覽器下載文件時保存的默認路徑
prefs = {"download.default_directory": get_download_dir()}
options.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(options=options)

一些非常有用的啟動選項,下面使用的options = webdriver.ChromeOptions():

  • options.add_argument("--proxy-server=127.0.0.1:16666"): 設置代理,可以結合mitmproxy進行抓包等
  • option.add_experimental_option('excludeSwitches', ['enable-automation']): 設置繞過selenium檢測
  • options.add_argument("---ignore-certificate-errors"): 設置忽略https證書校驗
  • options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2}): 設置不請求圖片模式加快頁面加載速度
  • chrome_options.add_argument('--headless'): 設置無頭瀏覽器

selenium頁面加載等待和檢測

使用selenium打開頁面以后,還不能立刻操作,需要等到待處理頁面元素加載完成,這時就需要檢測和等待頁面元素加載。

使用time.sleep()等待

最簡單的方法就是打開頁面以后,使用time.sleep()強制等待一定時間,該方法只能設置一個固定時間等待,如果頁面提前加載完成,則會空等阻塞。

from time import sleep
from selenium import webdriverdriver = webdriver.Chrome()
driver.get('http://uusama.con')
time.sleep(10)
print('load finish')

使用implicitly_wait設置最長等待時間

另外還可以使用implicitly_wait設置最長等待時間,如果在給定時間內頁面加載完成或者已經超時,才會執行下一步。該方法會等到所有資源全部加載完成,也就是瀏覽器標簽欄的loading圖表不再轉才會執行下一步。有可能頁面元素已經加載完成,但是js或者圖片等資源還未加載完成,此時還需要等待。

另需注意使用implicitly_wait只需設置一次,且對整個driver生命周期都起作用,凡是遇到頁面正在加載都會阻塞。

示例如下:

from selenium import webdriverdriver = webdriver.Chrome()
driver.implicitly_wait(30)   # 設置最長等30秒
driver.get('http://uusama.com')
print(driver.current_url)driver.get('http://baidu.com')
print(driver.current_url)

使用WebDriverWait設置等待條件

使用WebDriverWait(selenium.webdriver.support.wait.WebDriverWait)能夠更加精確靈活地設置等待時間,WebDriverWait可在設定時間內每隔一段時間檢測是否滿足某個條件,如果滿足條件則進行下一步操作,如果超過設置時間還不滿足,則拋出TimeoutException異常,其方法聲明如下:

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)

其中各參數含義如下:

  • driver:瀏覽器驅動
  • timeout:最長超時時間,默認以秒為單位
  • poll_frequency:檢測的間隔(步長)時間,默認為0.5秒
  • ignored_exceptions:忽略的異常,即使在調用until()或until_not()的過程中拋出給定異常也不中斷

WebDriverWait()一般配合until()或until_not()方法使用,表示等待阻塞直到返回值為True或者False,需要注意這兩個方法的參數都需是可調用對象,即方法名稱,可以使用expected_conditions模塊中的方法或者自己封裝的方法。?

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditionsdriver = webdriver.Chrome()
driver.get("http://baidu.com")# 判斷id為`input`的元素是否被加到了dom樹里,并不代表該元素一定可見,如果定位到就返回WebElement
element = WebDriverWait(driver, 5, 0.5).until(expected_conditions.presence_of_element_located((By.ID, "s_btn_wr")))# implicitly_wait和WebDriverWait都設置時,取二者中最大的等待時間
driver.implicitly_wait(5)# 判斷某個元素是否被添加到了dom里并且可見,可見代表元素可顯示且寬和高都大于0
WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.ID, 'su')))# 判斷元素是否可見,如果可見就返回這個元素
WebDriverWait(driver,10).until(EC.visibility_of(driver.find_element(by=By.ID, value='kw')))

下面列出expected_conditions常用的一些方法:

  • title_is: 判斷當前頁面title是否精確等于預期
  • title_contains: 判斷當前頁面title是否包含預期字符串
  • presence_of_element_located: 判斷某個元素是否被加到了dom樹里,并不代表該元素一定可見
  • visibility_of_element_located: 判斷某個元素是否可見(元素非隱藏,并且元素的寬和高都不等于0)
  • visibility_of: 跟上面的方法做一樣的事情,只是上面的方法要傳入locator,這個方法直接傳定位到的element就好了
  • presence_of_all_elements_located: 判斷是否至少有1個元素存在于dom樹中。舉個例子,如果頁面上有n個元素的class都是'column-md-3',那么只要有1個元素存在,這個方法就返回True
  • text_to_be_present_in_element: 判斷某個元素中的text是否包含了預期的字符串
  • text_to_be_present_in_element_value: 判斷某個元素中的value屬性是否包含了預期的字符串
  • frame_to_be_available_and_switch_to_it: 判斷該frame是否可以switch進去,如果可以的話,返回True并且switch進去,否則返回False
  • invisibility_of_element_located: 判斷某個元素中是否不存在于dom樹或不可見
  • element_to_be_clickable: 判斷某個元素中是否可見并且是enable的,這樣的話才叫clickable
  • staleness_of: 等某個元素從dom樹中移除,注意,這個方法也是返回True或False
  • element_to_be_selected: 判斷某個元素是否被選中了,一般用在下拉列表
  • element_selection_state_to_be: 判斷某個元素的選中狀態是否符合預期
  • element_located_selection_state_to_be: 跟上面的方法作用一樣,只是上面的方法傳入定位到的element,而這個方法傳入locator

檢測document是否加載完成

另外還可以使用driver.execute_script('return document.readyState;') == 'complete'來檢測document是否加載完成。

注意document加載完成,是不包括那種異步加載ajax請求動態渲染dom的,這種需要使用WebDriverWait檢測某個元素是否渲染完成。

selenium元素定位和讀取

查找元素

selenium提供了一系列api方便獲取chrome中的元素,這些API都返回WebElement對象或其列表,如:

  • find_element_by_id(id): 查找匹配id的第一個元素
  • find_element_by_class_name(): 查找匹配class的第一個元素
  • find_elements_by_xpath(): 查找匹配xpath的所有元素
  • find_elements_by_css_selector(): 查找匹配css選擇器的所有元素

其實可以看WebDriver類里面的實現源碼,其核心實現都是調用兩個基本函數:

  • find_element(self, by=By.ID, value=None): 查找匹配策略的第一個元素
  • find_elements(self, by=By.ID, value=None): 查找匹配策略的所有元素

其中by參數可以是ID, CSS_SELECTOR, CLASS_NAME, XPATH等。下面舉幾個簡單的例子:

  • 通過xpath查詢包含文本登錄的第一個元素: find_element_by_xpath("//*[contains(text(),'登錄')]")
  • 查詢包含類名refresh的所有元素: find_elements_by_class_name('refresh')
  • 查詢table表格的第二行: find_element_by_css_selector('table tbody > tr:nth(2)')

dom元素交互

上面介紹的元素查找結果WebElement對象,常用的api有:

  • ?element.text: 返回元素的文本內容(包括所有后代節點的內容),注意如果元素display=none則返回為空字符串
  • element.screenshot_as_png: 元素的截圖
  • element.send_keys("input"): 元素輸入框輸入input字符串
  • element.get_attribute('data-v'): 獲取data-v名稱屬性值,除了自定義節點屬性,還可以獲取如textContent等屬性
  • element.is_displayed(): 判斷元素是否用戶可見
  • element.clear(): 清除元素文本
  • element.click(): 點擊元素,如果元素不可點擊會拋出ElementNotInteractableException異常
  • element.submit(): 模擬表單提交

查找元素失敗處理

如果找不到指定元素,則會拋出NoSuchElementException異常,而且需要注意,display=none的元素是可以獲取到的,凡是在dom節點中的元素都可以獲取到。

而且實際使用的時候要注意一些js代碼動態創建的元素,可能需要輪詢獲取或者監控。

一個檢查是否存在指定元素的方法如下:

def check_element_exists(xpath):try:driver.find_element_by_xpath(xpath)except NoSuchElementException:return Falsereturn True

selenium交互控制

ActionChains動作鏈

webdriver通過ActionChains對象來模擬用戶操作,該對象表示一個動作鏈路隊列,所有操作會依次進入隊列但不會立即執行,直到調用perform()方法時才會執行。其常用方法如下:

  • click(on_element=None): 單擊鼠標左鍵
  • click_and_hold(on_element=None): 點擊鼠標左鍵,不松開
  • context_click(on_element=None): 點擊鼠標右鍵
  • double_click(on_element=None): 雙擊鼠標左鍵
  • send_keys(*keys_to_send): 發送某個鍵到當前焦點的元素
  • send_keys_to_element(element, *keys_to_send): 發送某個鍵到指定元素
  • key_down(value, element=None): 按下某個鍵盤上的鍵
  • key_up(value, element=None): 松開某個鍵
  • drag_and_drop(source, target): 拖拽到某個元素然后松開
  • drag_and_drop_by_offset(source, xoffset, yoffset): 拖拽到某個坐標然后松開
  • move_by_offset(xoffset, yoffset): 鼠標從當前位置移動到某個坐標
  • move_to_element(to_element): 鼠標移動到某個元素
  • move_to_element_with_offset(to_element, xoffset, yoffset): 移動到距某個元素(左上角坐標)多少距離的位置
  • perform(): 執行鏈中的所有動作
  • release(on_element=None): 在某個元素位置松開鼠標左鍵

模擬鼠標事件

下面代碼模擬鼠標移動,點擊,拖拽等操作,注意操作時需要等待一定時間,否則頁面還來不及渲染。

from time import sleep
from selenium import webdriver
# 引入 ActionChains 類
from selenium.webdriver.common.action_chains import ActionChainsdriver = webdriver.Chrome()
driver.get("https://www.baidu.cn")
action_chains = ActionChains(driver)target = driver.find_element_by_link_text("搜索")
# 移動鼠標到指定元素然后點擊
action_chains.move_to_element(target).click(target).perform()
time.sleep(2)# 也可以直接調用元素的點擊方法
target.click()
time.sleep(2)# 鼠標移動到(10, 50)坐標處
action_chains.move_by_offset(10, 50).perform()
time.sleep(2)# 鼠標移動到距離元素target(10, 50)處
action_chains.move_to_element_with_offset(target, 10, 50).perform()
time.sleep(2)# 鼠標拖拽,將一個元素拖動到另一個元素
dragger = driver.find_element_by_id('dragger')
action.drag_and_drop(dragger, target).perform()
time.sleep(2)# 也可以使用點擊 -> 移動來實現拖拽
action.click_and_hold(dragger).release(target).perform()
time.sleep(2)
action.click_and_hold(dragger).move_to_element(target).release().perform()

模擬鍵盤輸入事件

通過send_keys模擬鍵盤事件,常用有:

  • send_keys(Keys.BACK_SPACE): 刪除鍵(BackSpace)
  • send_keys(Keys.SPACE): 空格鍵(Space)
  • send_keys(Keys.TAB): 制表鍵(Tab)
  • send_keys(Keys.ESCAPE): 回退鍵(Esc)
  • send_keys(Keys.ENTER): 回車鍵(Enter)
  • send_keys(Keys.F1): 鍵盤 F1
  • send_keys(Keys.CONTROL,'a'): 全選(Ctrl+A)
  • send_keys(Keys.CONTROL,'c'): 復制(Ctrl+C)
  • send_keys(Keys.CONTROL,'x'): 剪切(Ctrl+X)
  • send_keys(Keys.CONTROL,'v'): 粘貼(Ctrl+V)

示例:定位到輸入框,然后輸入內容

# 輸入框輸入內容
driver.find_element_by_id("kw").send_keys("uusamaa")# 模擬回車刪除多輸入的一個字符a
driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE)

警告框處理

用于處理調用alert彈出的警告框。

  • driver.switch_to_alert(): 切換到警告框
  • text:返回alert/confirm/prompt中的文字信息,比如js調用alert('failed')則會獲取failed字符串
  • accept():接受現有警告框
  • dismiss():關閉現有警告框
  • send_keys(keysToSend):將文本發送至警告框

selenium瀏覽器控制

基本常用api

下面列出一些非常實用的瀏覽器控制api:

  • driver.current_url: 獲取當前活動窗口的url
  • driver.switch_to_window("windowName"): 移動到指定的標簽窗口
  • driver.switch_to_frame("frameName"): 移動到指定名稱的iframe
  • driver.switch_to_default_content(): 移動到默認文本內容區
  • driver.maximize_window(): 將瀏覽器最大化顯示
  • driver.set_window_size(480, 800): 設置瀏覽器寬480、高800顯示
  • driver.forword(), driver.back(): 瀏覽器前進和后退
  • driver.refresh(): 刷新頁面
  • driver.close(): 關閉當前標簽頁
  • driver.quiit(): 關閉整個瀏覽器
  • driver.save_screenshot('screen.png'): 保存頁面截圖
  • driver.maximize_window(): 將瀏覽器最大化顯示
  • browser.execute_script('return document.readyState;'): 執行js腳本

selenium讀取和加載cookie

使用get_cookies和add_cookie可以實現將cookie緩存到本地,然后啟動時加載,這樣可以保留登錄態。實現如下

import os
import json
from selenium import webdriverdriver = webdriver.Chrome()
driver.get("https://www.baidu.cn")# 讀取所有cookie并保存到文件
cookies = driver.get_cookies()
cookie_save_path = 'cookie.json'
with open(cookie_save_path, 'w', encoding='utf-8') as file_handle:json.dump(cookies, file_handle, ensure_ascii=False, indent=4)# 從文件讀取cookie并加載到瀏覽器
with open(cookie_save_path, 'r', encoding='utf-8') as file_handle:cookies = json.load(file_handle)for cookie in cookies:driver.add_cookie(cookie)

selenium打開新的標簽頁窗口

使用driver.get(url)會默認在第一個標簽窗口打開指定連接,點擊頁面中的_blank的鏈接時也會打開一個新的標簽窗口。

還可以用下面的方式手動打開一個指定頁面的標簽窗口,需要注意打開新窗口或者關閉以后,還需要手動調用switch_to.window切換當前活動的標簽窗口,否則會拋出NoSuchWindowException異常。

from selenium import webdriverdriver = webdriver.Chrome()
driver.get("https://www.baidu.cn")new_tab_url = 'http://uusama.com'
driver.execute_script(f'window.open("{new_tab_url}", "_blank");')
time.sleep(1)# 注意:必須調用switch_to.window手動切換window,否則會找不到tab view
# 聚焦到新打開的tab頁面,然后關閉
driver.switch_to.window(driver.window_handles[1])
time.sleep(2)
driver.close()   # 關閉當前窗口# 手動回到原來的tab頁面
driver.switch_to.window(driver.window_handles[0])
time.sleep(1)

除了使用execute_script外,還可以使用模擬打開新tab頁按鍵的方式新建一個標簽頁窗口:

  • driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 't')
  • ActionChains(driver).key_down(Keys.CONTROL).send_keys('t').key_up(Keys.CONTROL).perform()

selenium一些問題記錄

獲取隱藏元素的文本內容

?如果一個元素是隱藏的,即display=none,雖然可以通過find_element查找到該元素,但是用element.text屬性是獲取不到該元素文本內容的,其值是空字符串,這時可以用下面的方式獲取:

element = driver.find_element_by_id('uusama')
driver.execute_script("return arguments[0].textContent", element)
driver.execute_script("return arguments[0].innerHTML", element)# 相應的也可以把隱藏的元素設置為非隱藏
driver.execute_script("arguments[0].style.display = 'block';", element)

瀏覽器崩潰WebDriverException異常處理

比如在Chrome中長時間運行一個頁面會出現Out Of Memory內存不足的錯誤,此時WebDriver會拋出WebDriverException異常,基本所有api都會拋出這個異常,這個時候需要捕獲并進行特殊處理。

我的處理方式是記錄頁面的一些基本信息,比如url,cookie等,并定期寫入到文件中,如果檢測到該異常,則重啟瀏覽器并且加載url和cookie等數據。

selenium抓取頁面請求數據

網上有通過driver.requests或者通過解析日志來獲取頁面請求的方式,但是我感覺都不是很好使。最后使用mitmproxy代理進行抓包處理,然后啟動selenium時填入代理來實現。

proxy.py為在mitmproxy基礎上封裝的自定義代理請求處理,其代碼如下:

import os
import gzip
from mitmproxy.options import Options
from mitmproxy.proxy.config import ProxyConfig
from mitmproxy.proxy.server import ProxyServer
from mitmproxy.tools.dump import DumpMaster
from mitmproxy.http import HTTPFlow
from mitmproxy.websocket import WebSocketFlowclass ProxyMaster(DumpMaster):def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)def run(self, func=None):try:DumpMaster.run(self, func)except KeyboardInterrupt:self.shutdown()def process(url: str, request_body: str, response_content: str):# 抓包請求處理,可以在這兒轉存和解析數據passclass Addon(object):def websocket_message(self, flow: WebSocketFlow):# 監聽websockt請求passdef response(self, flow: HTTPFlow):# 避免一直保存flow流,導致內存占用飆升# flow.request.headers["Connection"] = "close"# 監聽http請求響應,并獲取請求體和響應內容url = flow.request.urlrequest_body = flow.requestresponse_content = flow.response# 如果返回值是壓縮的內容需要進行解壓縮if response_content.data.content.startswith(b'\x1f\x8b\x08'):response_content = gzip.decompress(response_content.data.content).decode('utf-8')Addon.EXECUTOR.submit(process, url, request_body, response_content)def run_proxy_server():options = Options(listen_host='0.0.0.0', listen_port=16666)config = ProxyConfig(options)master = ProxyMaster(options, with_termlog=False, with_dumper=False)master.server = ProxyServer(config)master.addons.add(Addon())master.run()if __name__ == '__main__':with open('proxy.pid', mode='w') as fin:fin.write(os.getpid().__str__())run_proxy_server()

在使用mitmproxy過程中,隨著時間推移proxy.py會出現占用內存飆升的問題,在github的issue區有人也遇到過,有說是因為http連接keep-alive=true請求會一直保存不會釋放,導致請求越多越占用內存,然后通過添加flow.request.headers["Connection"] = "close"來手動關閉連接,我加了以后有一定緩解,但還是不能從根本上解決。

最后通過寫入proxy.pid記錄代理程序進程,然后用另外一個程序定時重啟proxy.py來解決內存泄漏的問題。

最后感謝每一個認真閱讀我文章的人,禮尚往來總是要有的,雖然不是什么很值錢的東西,如果你用得到的話可以直接拿走:

這些資料,對于做【軟件測試】的朋友來說應該是最全面最完整的備戰倉庫,這個倉庫也陪伴我走過了最艱難的路程,希望也能幫助到你!凡事要趁早,特別是技術行業,一定要提升技術功底。

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

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

相關文章

Go通道操作全解析:從基礎到高并發模式

一、channel類型 Go 語言中的通道(channel)是一種特殊的類型。它類似于傳送帶或隊列,遵循先進先出(FIFO)原則,確保數據收發順序的一致性。每個通道都是特定類型的導管,因此在聲明時必須指定其元素類型。 channel是一種類型, 一種引用類型。 聲明通道類型的格式如下:…

Linux網絡--1、網絡基礎

目錄 一、網絡發展 二、理解分層 2.1OSI七層模型 2.2TCP/IP分層模型 2.3分層的好處 三、認識協議 3.1初步認識 3.2了解指定組織 3.3具體協議理解 3.3.1是什么 3.3.2為什么 3.3.3與OS的關系 3.4總結 四、網絡傳輸流程 4.1局域網網絡傳輸 4.1.1通信過程 4.1.2概念解析 4.2跨網…

前端視角下關于 WebSocket 的簡單理解

參考 RFC 6455: The WebSocket Protocol WebSocket 協議基礎 協議本質:在單個 TCP 連接上提供全雙工通信通道的協議核心優勢: 雙向實時通信(服務器主動推送)低延遲(相比 HTTP 輪詢)高效數據傳輸&#xff0…

自動化一鍵部署 LNMP 環境

第一步:準備環境 & 準備腳本文件1. 你在 CentOS 7 的服務器/虛擬機里打開終端,確認你有 root 權限或者能用 sudo。輸入下面命令確認你的系統版本:cat /etc/centos-release你應該看到類似:CentOS Linux release 7.9.2009 (Core…

react之React.cloneElement()

react提供的這個方法克隆組件的方法,可能我們在平常的開發中用的很少,主要可能是我們并不知道或者并不了解這個方法。因為我在之前react的children文章中用到過,所以我就進行了一系列的測試,發現真的非常的好用。我們同樣使用一些…

學習Java的Day27

今天學習的主要內容是在IntelliJ IDEA開發環境中,通過部署Tomcat服務器并連接MySQL數據庫,實現了一個完整的留言板系統。這個項目涵蓋了前后端開發的全流程,具體包括以下關鍵環節:開發環境搭建使用IntelliJ IDEA Ultimate版&#…

【計算機網絡 | 第3篇】物理媒介

文章目錄物理媒介介紹與物理媒體的分類🥝成本考量引導型傳輸媒體🍋引導型傳輸媒體:雙絞線🍋?🟩雙絞線類別雙絞線的發展歷程雙絞線的物理限制引導型傳輸媒體:同軸電纜🍋?🟩結構組成…

golang的切片

切片 為什么需要切片 用于元素的個數不確定,所以無法通過數組的形式來進行統計。此時就需要切片 切片,也因此可以粗略地理解為動態數組數組的長度不能用變量來確定,這時候切片slice也就派上用場了 切片地基本介紹 切片的英文是slice切片是數組…

在labview中實現視頻播放

這里分享一個迅雷的視頻播放控件APlayer,非常的好用。具體操作步驟如下: 1.下載控件: 首先下載http://aplayer.open.xunlei.com/codecs.zip,將codecs文件解壓后打開,按快捷鍵contrlA,隨后contrlc復制里面所有的文件;…

ubuntu 22.04 使用yaml文件 修改靜態ip

前提: 啟動服務 sudo systemctl start systemd-networkd 設置開機自啟 sudo systemctl enable systemd-networkd 檢查狀態(確保顯示 active (running)) sudo systemctl status systemd-networkd 若想停止: 停止當前運行的服務 sud…

閘機控制系統從設計到實現全解析:第 4 篇:Redis 緩存與分布式鎖實現

第 4 篇:Redis 緩存與分布式鎖實現 一、Redis 在系統中的核心作用票證信息緩存:將高頻訪問的票證數據(如狀態、有效期)緩存至 Redis,減少數據庫查詢,提升驗證響應速度。分布式鎖:在高并發場景下…

北京天津唐山廊坊滄州打撈日記

北京天津唐山廊坊滄州打撈日記 打撈搜蚯蚓疏通 北京:護城河畔的情誼打撈 清晨,北京的護城河在朝陽的映照下泛著微光。我接到一位年輕小伙的電話,聲音中滿是焦急。原來,他與女友在河邊約會時,不小心將女友送他的定情玉佩…

全志刷機工具:PhoenixSuit-全志芯片處理器-刷機工具安裝包及最詳細使用教程指南

全志刷機工具:PhoenixSuit-全志芯片處理器刷機工具安裝包及最詳細使用教程指南,此文章主要是分享機頂盒、電視盒子,全志芯片盒子(其中包含全志處理器、全志芯片、全志CPU等等)的刷機工具、刷機工具安裝教程以及如何使用…

淺談 VM 橋接模式:讓虛擬機像真實電腦一樣接入網絡

在虛擬化環境中,虛擬機(Virtual Machine, VM)與外部網絡之間的通信方式有多種,比如 NAT 模式、Host-Only 模式、橋接模式(Bridged Networking) 等。其中,橋接模式是最接近“真實物理機”網絡行為…

計算機視覺(1)-圖像采集設備選型全景表(工業 + 醫療 + 車載)

圖像采集設備選型全景表(工業 醫療 車載)一份面向工程師的“場景—設備—協議”速查表1 工業 & 醫療 & 通用場景應用場景主流設備形態接口 / 協議典型性能突出優勢致命短板動態范圍工業檢測AOI / 量測 / 缺陷工業相機 采集卡Camera Link HSCo…

計算機視覺(3)深度學習模型部署平臺技術選型與全棧實踐指南

一、部署平臺概述與分類 深度學習模型部署平臺的分類需兼顧技術特性與應用場景的適配性,基于“技術定位-場景適配”雙維度分類法,可將其劃分為通用開源框架、云廠商服務及專用邊緣工具三大類,各類別在設計目標、核心能力與場景覆蓋上呈現顯著…

Scratch編程:槍戰游戲(附源碼)

🎮 操作說明 W / A / S / D 或 方向鍵:移動 C:滑鏟 空格鍵:取消滑鏟 鼠標點擊:開火 數字鍵 1 / 2 / 3 / 4:切換武器 G:快速使用道具 F:近戰攻擊 Q:瞄準 / 使用技能…

應急響應復現

一、前言:當企業發生黑客入侵、系統崩潰或其它影響業務正常運行的安全事件時,急需第一時間進行處理,使企業的網絡信息系統在最短時間內恢復正常工作,進一步查找入侵來源,還原入侵事故過程,同時給出解決方案…

分布式事務Seata TCC模式篇

介紹 ? 官網: https://seata.apache.org/zh-cn/docs/user/mode/tcc ? 回顧Seata AT 模式基于 支持本地 ACID 事務 的 關系型數據庫,如下: 一階段 prepare 行為:在本地事務中,一并提交業務數據更新和相應回滾日志記錄。二階段 c…

Day37--動態規劃--52. 攜帶研究材料(卡碼網),518. 零錢兌換 II,377. 組合總和 Ⅳ,57. 爬樓梯(卡碼網)

Day37–動態規劃–52. 攜帶研究材料(卡碼網),518. 零錢兌換 II,377. 組合總和 Ⅳ,57. 爬樓梯(卡碼網) 本文全部都是 ” 完全背包 “ 問題,從零到入坑,從入坑到爬出來。 本…