Selenium自动化测试实战:从框架搭建到工程化落地
1. 项目概述从“能用”到“好用”的自动化测试进阶之路做自动化测试尤其是UI自动化Selenium几乎是绕不开的名字。很多朋友包括我自己刚入门的时候都觉得这玩意儿不就是装个驱动、写几行定位元素的代码然后让浏览器自己动起来吗听起来挺酷上手也快但真到了项目里准备用它来提升测试效率、保障质量时才发现坑是一个接一个。脚本跑着跑着就报错元素死活定位不到浏览器版本一升级就全军覆没多线程并发时各种稀奇古怪的问题……这些才是Selenium自动化测试的“实战”常态。今天我就结合自己这些年踩过的坑、填过的土来聊聊如何让Selenium从“玩具”变成真正可靠的“工程化工具”。无论你是刚接触自动化测试的新手还是正在为团队搭建自动化框架的测试开发希望这些从实战中总结的经验能帮你少走些弯路。2. 核心思路与框架选型为什么是Selenium以及如何用好它2.1 Selenium的定位与核心价值在决定使用Selenium之前我们必须清楚它的能力边界。Selenium WebDriver的核心价值在于它提供了一套标准化的、跨浏览器的API允许我们用代码模拟真实用户对浏览器的操作。它不是一个“录制回放”工具而是一个“编程驱动”工具。这意味着它的稳定性和可靠性极大程度上取决于我们如何编写驱动它的代码。很多人抱怨Selenium不稳定其实很多时候问题出在我们的脚本设计上比如没有处理好异步加载、没有使用稳健的等待策略、或是定位方式过于脆弱。与Playwright、Cypress等后起之秀相比Selenium的优势在于其成熟度、广泛的社区支持、以及无与伦比的浏览器兼容性尤其是对老旧企业级浏览器的支持。它的劣势也很明显比如原生不支持自动等待、API相对底层、对现代前端框架如单页应用的复杂交互支持需要更多编码。因此选择Selenium通常是基于对浏览器兼容性有强要求或者技术栈历史包袱较重的场景。对于全新的、技术栈现代的Web应用Playwright在易用性和稳定性上可能更有优势但Selenium凭借其生态和W3C标准背景依然是企业级自动化测试的中坚力量。2.2 测试框架的选型与分层设计单纯使用Selenium WebDriver写脚本是远远不够的我们必须将其嵌入到一个测试框架中。在Python生态里pytest是绝对的主流选择它比unittest更灵活、插件更丰富、报告更美观。结合pytest我们可以很容易地实现测试用例的发现、执行、夹具fixture管理以及丰富的钩子函数。一个健壮的自动化测试框架必须进行清晰的分层设计这能极大提升代码的可维护性和复用性。我推荐的核心分层如下基础层Driver层封装WebDriver的初始化、退出、以及浏览器通用配置如无头模式、窗口大小、下载路径等。这一层要保证浏览器实例管理的单一性和可控性。页面对象层Page Object Layer这是Selenium自动化测试设计的灵魂。将每个页面或页面中的重要组件如导航栏、搜索框抽象成一个类。这个类内部封装了该页面的所有元素定位器Locators和页面操作方法如输入、点击、获取文本。测试脚本不直接操作WebDriver API而是调用页面对象的方法。这样做的好处是当页面UI发生变化时我们只需要修改对应的页面对象类而不需要修改大量的测试用例脚本。业务层Business Layer/Flow Layer将多个页面对象的操作串联起来形成完整的用户业务流程。例如“用户登录”这个业务可能涉及登录页面的输入和点击以及登录成功后跳转到首页的验证。业务层使得测试用例读起来更像是在描述一个用户故事提升了可读性。测试用例层Test Case Layer使用pytest编写具体的测试函数。这一层应该非常“瘦”只包含测试数据、业务层的调用以及断言。它关注的是“测试什么”而不是“怎么测试”。数据层Data Layer将测试数据如用户名、密码、搜索关键词从测试脚本中剥离出来可以通过文件JSON, YAML, Excel、数据库或外部接口来管理。便于数据驱动测试pytest的pytest.mark.parametrize非常好用。工具层Utils Layer存放公共工具方法如读取配置文件、生成日志、发送测试报告邮件、处理验证码如果不可避免、数据库操作、API请求等。一个典型的pytest项目目录结构可能长这样project_root/ ├── conftest.py # pytest全局配置文件定义fixture ├── pytest.ini # pytest配置文件 ├── requirements.txt # 项目依赖 ├── configs/ # 配置文件目录 │ └── config.yaml ├── data/ # 测试数据目录 │ └── test_data.json ├── logs/ # 日志目录 ├── reports/ # 测试报告目录 ├── pages/ # 页面对象层 │ ├── __init__.py │ ├── base_page.py # 所有页面对象的基类 │ ├── login_page.py │ └── home_page.py ├── flows/ # 业务流层 │ ├── __init__.py │ └── login_flow.py ├── test_cases/ # 测试用例层 │ ├── __init__.py │ └── test_login.py └── utils/ # 工具层 ├── __init__.py ├── logger.py └── webdriver_manager.py注意分层不是教条对于中小型项目可以将业务层和页面对象层适当合并。但页面对象模式PO是必须坚持的这是保证UI自动化脚本长期可维护性的基石。3. 环境搭建与依赖管理从源头避开版本冲突3.1 浏览器与驱动的“爱恨情仇”这是Selenium新手踩的第一个也是最经典的一个坑。错误信息通常是WebDriverException: Message: ‘chromedriver’ executable needs to be in PATH。其核心矛盾在于Chrome/Edge/Firefox浏览器会频繁自动更新但WebDriver驱动如chromedriver需要与浏览器主版本严格匹配。传统做法手动管理去浏览器驱动官网下载对应版本的驱动放入系统PATH或项目指定目录。这种方式极其繁琐且容易出错特别是在CI/CD环境中。现代最佳实践自动管理使用webdriver-manager库Python这是一个第三方库可以自动检测本地已安装的浏览器版本并下载匹配的驱动。pip install webdriver-manager在代码中from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager # 自动下载并使用匹配的chromedriver service Service(ChromeDriverManager().install()) driver webdriver.Chrome(serviceservice)使用Selenium 4.6 的Selenium Manager官方推荐从Selenium 4.6版本开始官方集成了用Rust编写的Selenium Manager。当你创建WebDriver实例时如果未指定驱动路径它会自动在后台为你处理驱动的下载和匹配。这是目前最省心的方案。from selenium import webdriver from selenium.webdriver.chrome.service import Service as ChromeService # 无需指定驱动路径Selenium Manager会自动处理 driver webdriver.Chrome(serviceChromeService())确保你的selenium库版本在4.6以上即可。实操心得在团队协作和CI/CD环境中强烈推荐使用Selenium Manager。它彻底将我们从“驱动版本管理”的泥潭中解放出来。唯一需要注意的是某些内网环境可能需要配置代理才能从网络下载驱动。3.2 虚拟环境与依赖锁定Python项目必须使用虚拟环境如venv,conda来隔离项目依赖。这能避免不同项目间包版本的冲突。更重要的是必须使用requirements.txt或Pipfile来精确锁定所有依赖的版本特别是selenium、pytest、webdriver-manager等核心库的版本。这能保证在任何机器上包括CI服务器都能复现完全一致的环境。一个可靠的requirements.txt示例selenium4.15.0 pytest7.4.0 pytest-html4.1.0 pytest-xdist3.5.0 webdriver-manager4.0.1 allure-pytest2.13.2 PyYAML6.0.1 requests2.31.0使用pip install -r requirements.txt来安装所有依赖。4. 元素定位与等待策略稳定性的核心命门超过70%的Selenium脚本失败都源于元素定位问题和没有正确等待。4.1 元素定位优先级与策略定位元素时应遵循以下优先级原则唯一ID如果元素有稳定且唯一的id这是最佳选择。driver.find_element(By.ID, “username”)CSS Selector这是最强大、最灵活、性能也较好的定位方式。优先使用class、属性等组合定位。例如driver.find_element(By.CSS_SELECTOR, “button.submit-btn[type‘submit’]”)XPath当CSS无法精确定位时使用。尽量避免使用绝对路径以/开头应使用相对路径和属性组合。好的XPath//div[class‘container’]//input[placeholder‘搜索’]避免的XPath/html/body/div[3]/div[2]/div/div[1]/form/input[2]一旦DOM结构微调立即失效Name、Class Name、Tag Name、Link Text/Partial Link Text在简单场景下可以使用但通常不如CSS和XPath精准。避坑技巧永远不要依赖元素的文本内容text()或顺序索引如div[1]作为定位的主要依据因为它们极易变化。应该寻找元素那些业务逻辑不变的属性比如>from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 等待最多10秒直到“登录按钮”可见且可点击 login_button WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.ID, “loginBtn”)) ) login_button.click()expected_conditions模块提供了丰富的条件如presence_of_element_located: 元素出现在DOM中不一定可见。visibility_of_element_located: 元素可见。element_to_be_clickable: 元素可见且可点击最常用。text_to_be_present_in_element: 元素包含特定文本。invisibility_of_element_located: 元素不可见或从DOM中消失用于等待加载动画消失。最佳实践混合使用。设置一个较短的全局隐式等待如5秒作为兜底。在关键交互步骤如点击按钮后页面跳转、弹窗出现、数据加载前使用针对性的显式等待。这既保证了脚本的健壮性又避免了不必要的全局长时间等待。5. 高级交互与特殊场景处理5.1 处理弹窗Alert/Confirm/Promptfrom selenium.webdriver.common.alert import Alert # 等待弹窗出现 WebDriverWait(driver, 5).until(EC.alert_is_present()) alert Alert(driver) # 获取弹窗文本 print(alert.text) # 点击确认 alert.accept() # 点击取消 # alert.dismiss() # 输入文本针对Prompt # alert.send_keys(“输入内容”)5.2 处理下拉选择框Select不要用click去模拟选择使用Select类。from selenium.webdriver.support.ui import Select select_element driver.find_element(By.ID, “country”) select Select(select_element) # 通过可见文本选择 select.select_by_visible_text(“中国”) # 通过value属性选择 # select.select_by_value(“cn”) # 通过索引选择 # select.select_by_index(1)5.3 处理文件上传对于input type“file”元素直接使用send_keys传入文件的绝对路径即可。upload_element driver.find_element(By.CSS_SELECTOR, “input[type‘file’]”) upload_element.send_keys(“/Users/yourname/Downloads/test_file.pdf”)注意这种方法无法绕过操作系统级别的文件选择对话框。如果网站使用的是自定义的文件上传组件非原生input则需要借助pyautogui等桌面自动化库来操作文件对话框但这会引入不稳定性应尽量避免或与开发协商使用原生input。5.4 执行JavaScript当Selenium的API无法完成某些操作时可以借助执行JavaScript的能力。# 滚动到页面底部 driver.execute_script(“window.scrollTo(0, document.body.scrollHeight);”) # 滚动到某个元素可见 element driver.find_element(By.ID, “target”) driver.execute_script(“arguments[0].scrollIntoView(true);”, element) # 修改元素属性例如让一个隐藏的元素可见仅用于调试或特殊处理 driver.execute_script(“document.getElementById(‘hiddenElem’).style.display ‘block’;”) # 获取页面性能数据 performance_data driver.execute_script(“return window.performance.timing;”)5.5 处理iframe如果元素位于iframe内部必须先切换到该iframe上下文操作完成后记得切回。# 通过ID或Name切换 driver.switch_to.frame(“iframe_id_or_name”) # 通过索引切换从0开始 # driver.switch_to.frame(0) # 通过WebElement切换 # iframe_elem driver.find_element(By.TAG_NAME, “iframe”) # driver.switch_to.frame(iframe_elem) # 在iframe内操作元素 driver.find_element(By.ID, “inner_button”).click() # 操作完成后切回主文档 driver.switch_to.default_content() # 或者切回上一级iframe # driver.switch_to.parent_frame()6. 框架增强与最佳实践6.1 使用Page Object Model (POM) 设计模式如前所述POM是UI自动化的基石。这里展示一个基类和子类的简单示例# base_page.py from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class BasePage: def __init__(self, driver): self.driver driver self.wait WebDriverWait(driver, 10) def find_element(self, by, locator): “”“查找单个元素加入显式等待”“” return self.wait.until(EC.presence_of_element_located((by, locator))) def find_elements(self, by, locator): return self.driver.find_elements(by, locator) def click(self, by, locator): element self.wait.until(EC.element_to_be_clickable((by, locator))) element.click() def input_text(self, by, locator, text): element self.find_element(by, locator) element.clear() element.send_keys(text) # login_page.py from selenium.webdriver.common.by import By from .base_page import BasePage class LoginPage(BasePage): # 定位器 USERNAME_INPUT (By.ID, “username”) PASSWORD_INPUT (By.ID, “password”) LOGIN_BUTTON (By.CSS_SELECTOR, “button.login-btn”) ERROR_MSG (By.CLASS_NAME, “error-message”) def __init__(self, driver): super().__init__(driver) self.driver driver def login(self, username, password): “”“登录业务流程”“” self.input_text(*self.USERNAME_INPUT, username) self.input_text(*self.PASSWORD_INPUT, password) self.click(*self.LOGIN_BUTTON) def get_error_message(self): “”“获取错误提示文本”“” try: return self.find_element(*self.ERROR_MSG).text except: return “”6.2 数据驱动测试使用pytest的pytest.mark.parametrize装饰器可以轻松实现数据驱动。# test_login.py import pytest from pages.login_page import LoginPage test_data [ (“correct_user”, “correct_pwd”, “登录成功”), (“wrong_user”, “correct_pwd”, “用户名或密码错误”), (“correct_user”, “”, “密码不能为空”), ] pytest.mark.parametrize(“username, password, expected”, test_data) def test_login(driver, username, password, expected): “”“使用不同数据测试登录功能”“” login_page LoginPage(driver) driver.get(“https://example.com/login”) login_page.login(username, password) if expected “登录成功”: # 断言跳转到首页或出现成功提示 assert “dashboard” in driver.current_url else: # 断言出现对应的错误提示 actual_error login_page.get_error_message() assert expected in actual_error6.3 并发执行与测试报告使用pytest-xdist插件可以并行运行测试用例大幅缩短执行时间。# 使用2个worker并行执行 pytest -n 2 # 自动检测CPU核心数 pytest -n auto生成美观的测试报告对于结果分析至关重要。pytest-html可以生成基础的HTML报告而allure-pytest可以生成非常专业、交互性强的Allure报告。# 生成pytest-html报告 pytest --htmlreport.html --self-contained-html # 生成Allure报告 pytest --alluredir./allure-results # 生成后使用命令行启动Allure服务查看 allure serve ./allure-results7. 常见“坑”与排查实录7.1ElementNotInteractableException或ElementClickInterceptedException现象定位到了元素但点击或输入时失败。排查元素不可见等待元素可见EC.visibility_of_element_located而不仅仅是存在于DOMEC.presence_of_element_located。元素被遮挡可能有弹窗、悬浮层、固定的页头页脚挡住了目标元素。使用driver.execute_script(“arguments[0].scrollIntoView(true);”, element)滚动到元素可见区域。或者检查并关闭遮挡物。元素处于禁用状态检查元素是否有disabled属性。需要等待其变为可用状态可以自定义等待条件。有多个相同元素定位器可能匹配到了多个元素但第一个匹配的元素是不可交互的如隐藏的。确保你的定位器是唯一的。7.2NoSuchElementException现象找不到元素。排查等待时间不足增加显式等待时间或检查页面加载是否真的完成了。iframe/Shadow DOM目标元素是否在iframe或Shadow DOM内部需要先切换上下文。页面跳转或刷新在操作元素前页面发生了跳转或刷新旧的元素引用失效。需要重新定位。定位器写错了使用浏览器开发者工具的Console输入$$(“你的CSS选择器”)或$x(“你的XPath”)来验证定位器是否正确。动态ID/Class前端框架如React, Vue可能会生成随机的ID或类名。需要寻找更稳定的定位方式如通过属性、层级关系或让开发添加固定的测试属性如>from selenium.webdriver.chrome.options import Options chrome_options Options() chrome_options.add_argument(“--headlessnew”) # Chrome 109 推荐使用new chrome_options.add_argument(“--no-sandbox”) # 在Linux CI环境中常需要 chrome_options.add_argument(“--disable-dev-shm-usage”) # 解决共享内存问题 chrome_options.add_argument(“--disable-gpu”) # 某些环境下需要 chrome_options.add_argument(“--window-size1920,1080”) # 设置窗口大小 driver webdriver.Chrome(optionschrome_options)注意在Headless模式下有些页面的行为可能与有界面模式略有不同例如文件下载。务必在Headless模式下充分测试所有场景。8. 持续集成与维护策略8.1 集成到CI/CD以GitHub Actions为例自动化测试只有集成到CI/CD流水线中才能发挥最大价值。以下是一个简单的GitHub Actions工作流示例# .github/workflows/automated-tests.yml name: Automated UI Tests on: push: branches: [ main, develop ] pull_request: branches: [ main ] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Set up Python uses: actions/setup-pythonv4 with: python-version: ‘3.10’ - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt - name: Run UI Tests with pytest run: | # 假设你的测试入口在 test_cases/ 目录 pytest test_cases/ -v --htmlreport.html --self-contained-html - name: Upload test report uses: actions/upload-artifactv3 if: always() # 即使测试失败也上传报告 with: name: ui-test-report path: report.html8.2 测试脚本的维护UI自动化测试脚本是“活”的需要随着产品迭代而维护。定期运行至少每天在测试环境运行一次全套脚本及早发现因产品变更导致的脚本失效。失败分析建立机制当CI中的自动化测试失败时第一时间通知负责人。区分是脚本问题定位器失效还是真实的缺陷。定位器管理考虑将定位器集中管理在单独的配置文件或常量文件中而不是硬编码在页面对象里。这样当UI变化时只需修改一个地方。代码审查将自动化测试代码纳入团队的代码审查流程保证代码质量和设计模式的一致性。UI自动化测试是一把双刃剑用得好能极大提升回归效率和质量信心用不好则会成为沉重的维护负担。其成功的关键不在于技术本身有多高深而在于良好的设计模式如POM、稳健的等待策略、清晰的框架分层以及将其作为产品代码一样进行维护的决心。从一个小模块开始逐步扩展持续重构你会发现Selenium能成为你测试武器库中非常可靠的一员。

相关新闻

OpCore-Simplify:三分钟搞定macOS启动配置的终极方案

OpCore-Simplify:三分钟搞定macOS启动配置的终极方案

OpCore-Simplify:三分钟搞定macOS启动配置的终极方案 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 在非苹果硬件上运行macOS系统一直是技…

2026/7/6 4:39:23阅读更多 →
从缓存到执行:我实现了自己的任务编排引擎

从缓存到执行:我实现了自己的任务编排引擎

背景:为什么需要自己再造一个 团队接入 monorepo 任务编排工具后,构建快了很多。但我一直对两个问题好奇: 缓存的"三层架构"到底怎么设计的? .turbo/cache 目录下的 .tar.gz 文件,里面存了什么?怎么做到"第一次去本地读,第二次去远程读"的降级策略…

2026/7/6 4:39:23阅读更多 →
实对称矩阵 7 大核心性质证明:从正交对角化到舒尔分解的 3 种应用

实对称矩阵 7 大核心性质证明:从正交对角化到舒尔分解的 3 种应用

实对称矩阵的工程实践:从理论证明到机器学习应用的7大核心解析实对称矩阵在机器学习、优化算法和数值计算中扮演着关键角色。不同于纯数学视角的推导,本文将聚焦于如何将这些理论性质转化为实际工程应用中的有力工具。我们将通过Python代码示例、算法实现…

2026/7/6 4:34:23阅读更多 →
EEPROM与MCU高速数据检索优化方案

EEPROM与MCU高速数据检索优化方案

1. 项目背景与核心器件选型在嵌入式系统开发中,快速精确的数据检索是一个常见但极具挑战性的需求。传统方案往往面临速度瓶颈或存储容量限制,而采用25CSM04 EEPROM与PIC18F87K22微控制器的组合,则能很好地平衡性能、成本和实现复杂度。25CSM0…

2026/7/6 7:19:38阅读更多 →
OASIS Ring智能戒指:Vibe Coding新宠,能否成为AI交互最佳硬件?

OASIS Ring智能戒指:Vibe Coding新宠,能否成为AI交互最佳硬件?

OASIS Ring:跳出“小号手环”的创新之作主流智能戒指历经多次迭代,却始终难以摆脱「小号手环」的标签,功能多局限于健康数据监测。而OASIS Ring另辟蹊径,不把重点放在健康数据上,而是将戒指打造成输入设备,…

2026/7/6 7:19:38阅读更多 →
【JAVA毕设源码分享】基于springboot护工管理便捷服务系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于springboot护工管理便捷服务系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/6 7:19:38阅读更多 →
03-模拟开关相关知识点

03-模拟开关相关知识点

1.引入 2.开关芯片等效模型 CMOS等效模型见:02-MOS管相关知识点-CSDN博客 3.信号切换等效模型 4.模拟开关电阻衰减模型误差分析 (1)模拟开关误差计算方法 (2)衰减等效电路 (3)漏电流误差简易估…

2026/7/6 7:19:38阅读更多 →
STM32F410RB与25CSM04实现1.8MB/s高速数据存储方案

STM32F410RB与25CSM04实现1.8MB/s高速数据存储方案

1. 项目概述:基于25CSM04与STM32F410RB的高速数据检索系统在嵌入式系统中,快速访问非易失性存储数据一直是个经典难题。最近我在一个工业传感器项目中,需要实现每秒200次的环境参数记录与检索。经过多次测试,最终选用Microchip的2…

2026/7/6 7:19:38阅读更多 →
Java设计模式23种实战详解:从理论到落地,附完整可运行代码

Java设计模式23种实战详解:从理论到落地,附完整可运行代码

引言 设计模式是软件工程中经过反复验证的解决方案,是开发高质量代码的基石。GoF(Gang of Four)提出的23种经典设计模式,至今仍是Java开发者的必备技能。然而,许多同学在学习时往往只停留在“看懂”层面,遇…

2026/7/6 7:14:37阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/6 4:26:20阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/6 2:48:33阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/6 0:10:35阅读更多 →
Seraphine:基于LCU API的英雄联盟智能游戏助手技术解析与应用指南

Seraphine:基于LCU API的英雄联盟智能游戏助手技术解析与应用指南

Seraphine:基于LCU API的英雄联盟智能游戏助手技术解析与应用指南 【免费下载链接】Seraphine 英雄联盟战绩查询工具 项目地址: https://gitcode.com/gh_mirrors/se/Seraphine 技术架构先行:官方接口的合规应用 你是否曾在BP阶段手忙脚乱&#x…

2026/7/6 0:03:39阅读更多 →
多协议远程连接管理工具mRemoteNG:告别混乱,统一你的远程桌面管理

多协议远程连接管理工具mRemoteNG:告别混乱,统一你的远程桌面管理

多协议远程连接管理工具mRemoteNG:告别混乱,统一你的远程桌面管理 【免费下载链接】mRemoteNG mRemoteNG is the next generation of mRemote, open source, tabbed, multi-protocol, remote connections manager. 项目地址: https://gitcode.com/gh_m…

2026/7/6 0:03:39阅读更多 →
COUNT(DISTINCT) 与 GROUP BY 去重统计:5 亿数据量下的性能实测与选型指南

COUNT(DISTINCT) 与 GROUP BY 去重统计:5 亿数据量下的性能实测与选型指南

COUNT(DISTINCT) 与 GROUP BY 去重统计:5 亿数据量下的性能实测与选型指南在数据分析和处理领域,去重统计是最基础也是最频繁使用的操作之一。当数据量达到亿级规模时,不同的去重统计方法在性能上可能产生天壤之别。本文将基于 5 亿行数据的实…

2026/7/6 0:03:39阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/6 4:45:01阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/6 4:45:01阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/6 4:45:03阅读更多 →