当前位置: 首页 > news >正文

Playwright 完全指南:从入门到实战,解锁自动化测试新范式

在UI自动化测试与Web操作自动化领域,Selenium长期占据主导地位,但随着前端技术的快速发展(如SPA单页应用、动态渲染、跨浏览器兼容性要求提升),传统工具逐渐暴露出等待机制繁琐、跨浏览器一致性差、维护成本高等痛点。微软推出的 Playwright 应运而生,以“开箱即用的稳定性”“跨浏览器无缝兼容”“智能化的操作体验”三大核心优势,迅速成为自动化领域的新宠。本文将从Playwright的核心特性出发,详细讲解其使用方法、典型使用场景,并结合实战案例,帮助你快速掌握这一强大工具。

一、认识Playwright:它是什么?为什么选择它?

1.1 Playwright 简介

Playwright 是微软2020年开源的自动化测试工具,支持 Chromium(Chrome/Edge)、Firefox、WebKit(Safari) 三大浏览器内核,提供Python、JavaScript/TypeScript、C#三种编程语言API,可用于UI自动化测试、端到端(E2E)测试、页面操作自动化、网络爬虫等场景。

其设计目标是解决传统自动化工具的核心痛点:

  • 无需手动编写等待逻辑(自动等待元素可交互)

  • 一套代码跨三大浏览器,无需适配

  • 原生支持多页面、iframe、文件上传下载等复杂场景

  • 内置录制与代码生成功能,降低入门门槛

1.2 Playwright 核心优势(对比传统工具)

特性

Playwright

传统工具(如Selenium)

跨浏览器支持

原生支持Chromium/Firefox/WebKit,API完全一致

需分别适配不同浏览器驱动,API存在差异

等待机制

自动等待元素“可交互”,无需手动写WebDriverWait

需手动设置等待(显式/隐式),易出现“元素未就绪”错误

元素定位

提供get_by_*语义化定位(如get_by_test_id),支持文本、角色、标签

依赖By.ID/XPATH/CSS,语义化弱

多页面/标签页处理

原生支持页面切换、上下文隔离,API简洁

需手动管理window_handles,逻辑繁琐

录制与代码生成

内置codegen工具,可视化录制生成代码

需依赖第三方插件(如Selenium IDE),生成代码冗余

网络控制

支持拦截请求、修改响应、模拟网络状态

需依赖浏览器插件或第三方库,配置复杂

移动端模拟

原生支持模拟手机/平板分辨率、触摸操作

需额外配置移动设备模拟器,兼容性差

二、Playwright 快速上手:从环境搭建到基础使用

2.1 环境搭建(以Python为例)

Playwright支持Python 3.8+,环境搭建仅需3步:

步骤1:安装Playwright库
# 安装Playwright核心库
pip install playwright
步骤2:安装浏览器驱动

Playwright会自动下载对应版本的浏览器驱动(无需手动管理版本):

# 安装Chromium、Firefox、WebKit浏览器驱动
playwright install
步骤3:验证安装

创建test_playwright.py,运行以下代码,若能打开Chrome并导航到百度,则安装成功:

from playwright.sync_api import sync_playwright# 同步方式(Python常用)
with sync_playwright() as p:# 启动Chrome浏览器(headless=False表示显示浏览器窗口)browser = p.chromium.launch(headless=False)# 创建新页面page = browser.new_page()# 导航到百度page.goto("https://www.baidu.com")# 打印页面标题print("页面标题:", page.title())# 关闭浏览器browser.close()

2.2 Playwright 核心概念

在使用前,需理解3个核心对象,它们是Playwright操作的基础:

  • Playwright实例:通过sync_playwright()创建,是启动浏览器的入口,一个实例可管理多个浏览器。

  • Browser(浏览器实例):对应一个浏览器窗口(如Chrome窗口),可创建多个页面。

  • Page(页面实例):对应浏览器的一个标签页,所有页面操作(导航、点击、输入)都通过Page对象完成。

2.3 基础操作:页面导航与元素交互

Playwright的API设计简洁直观,以下是最常用的基础操作,代码可直接运行:

(1)页面导航与标题获取
from playwright.sync_api import sync_playwrightwith sync_playwright() as p:browser = p.chromium.launch(headless=False)page = browser.new_page()# 1. 导航到指定URLpage.goto("https://www.baidu.com")# 2. 获取页面标题(自动等待页面加载完成)print("当前标题:", page.title())  # 输出:百度一下,你就知道# 3. 刷新页面page.reload()# 4. 后退/前进page.goto("https://www.zhihu.com")page.go_back()  # 回到百度page.go_forward()  # 回到知乎browser.close()
(2)元素定位与交互(点击、输入)

Playwright提供了**7种元素定位方式**,推荐优先使用get_by_*系列(语义化、稳定),避免依赖易变的classXPath

定位方式

方法示例

适用场景

测试ID(推荐)

page.get_by_test_id("search-input")

元素有data-testid属性(专为测试设计)

文本定位

page.get_by_text("登录")

按钮、链接等有明确文本的元素

角色定位(ARIA)

page.get_by_role("button", name="提交")

符合无障碍标准的元素(如按钮、输入框)

标签文本定位

page.get_by_label("用户名")

表单输入框(对应<label>关联的元素)

占位符定位

page.get_by_placeholder("请输入密码")

placeholder的输入框

CSS选择器

page.locator("#username")

复杂定位场景(如组合条件)

XPath

page.locator("//input[@name='password']")

极端复杂场景(尽量避免)

交互代码示例(模拟百度搜索):

from playwright.sync_api import sync_playwrightwith sync_playwright() as p:browser = p.chromium.launch(headless=False)page = browser.new_page()page.goto("https://www.baidu.com")# 1. 定位搜索输入框,输入“Playwright”(自动等待输入框可交互)search_input = page.get_by_placeholder("请输入查询内容")search_input.fill("Playwright")  # 输入文本# 2. 定位搜索按钮,点击(自动等待按钮可点击)search_btn = page.get_by_text("百度一下")search_btn.click()# 3. 等待搜索结果加载,断言结果包含“Playwright”page.wait_for_load_state("networkidle")  # 等待网络空闲(所有请求完成)assert "Playwright" in page.title(), "搜索结果验证失败"browser.close()

(3)断言:验证页面状态

Playwright提供了expect断言库,支持对元素状态、文本、属性等进行验证,无需额外导入:

# 1. 断言元素可见
expect(page.get_by_text("搜索结果")).to_be_visible()# 2. 断言元素文本包含指定内容
expect(page.locator(".result-title")).to_contain_text("Playwright")# 3. 断言输入框值正确
expect(page.get_by_placeholder("请输入查询内容")).to_have_value("Playwright")# 4. 断言页面URL包含指定路径
expect(page).to_have_url("https://www.baidu.com/s?wd=Playwright")

2.4 核心功能:解决复杂场景

Playwright的强大之处在于对复杂场景的原生支持,无需额外插件,以下是高频场景的实现方法:

(1)多页面/标签页处理

当操作触发新标签页时,Playwright可自动捕获新页面,无需手动管理window_handles

from playwright.sync_api import sync_playwrightwith sync_playwright() as p:browser = p.chromium.launch(headless=False)page = browser.new_page()page.goto("https://www.baidu.com")# 1. 点击“关于百度”,触发新标签页# 先监听新页面事件with page.expect_popup() as popup_info:page.get_by_text("关于百度").click()  # 触发新页面# 2. 获取新页面实例new_page = popup_info.value# 3. 操作新页面new_page.wait_for_load_state()print("新页面标题:", new_page.title())  # 输出:关于百度# 4. 切换回原页面page.bring_to_front()page.get_by_placeholder("请输入查询内容").fill("回到原页面")browser.close()

(2)iframe 操作

对于嵌套在iframe中的元素,Playwright通过frame_locator直接定位,无需切换上下文:

# 场景:操作iframe中的登录按钮
from playwright.sync_api import sync_playwrightwith sync_playwright() as p:browser = p.chromium.launch(headless=False)page = browser.new_page()page.goto("https://example.com/with-iframe")# 1. 定位iframe(通过id、name或CSS)iframe = page.frame_locator("#login-iframe")  # iframe的id为login-iframe# 2. 操作iframe中的元素iframe.get_by_label("用户名").fill("testuser")iframe.get_by_label("密码").fill("testpass")iframe.get_by_role("button", name="登录").click()# 3. 验证登录成功(iframe外的元素)expect(page.get_by_text("欢迎回来,testuser")).to_be_visible()browser.close()

(3)文件上传与下载

Playwright支持文件上传(通过set_input_files)和下载(通过wait_for_event捕获下载事件):

# 1. 文件上传示例
def test_file_upload():with sync_playwright() as p:page = p.chromium.launch(headless=False).new_page()page.goto("https://example.com/upload")# 定位文件上传输入框,上传本地文件upload_input = page.get_by_test_id("file-upload")upload_input.set_input_files("test_upload.txt")  # 本地文件路径# 点击上传按钮page.get_by_text("开始上传").click()# 断言上传成功expect(page.get_by_text("上传完成")).to_be_visible()# 2. 文件下载示例
def test_file_download():with sync_playwright() as p:page = p.chromium.launch(headless=False).new_page()page.goto("https://example.com/download")# 监听下载事件with page.expect_download() as download_info:page.get_by_text("下载报告").click()  # 触发下载# 获取下载对象download = download_info.value# 保存下载文件到指定路径download.save_as("downloaded_report.xlsx")# 验证文件存在import osassert os.path.exists("downloaded_report.xlsx"), "文件下载失败"

(4)网络拦截与模拟

Playwright可拦截网络请求、修改响应、模拟弱网或离线状态,常用于测试异常场景:

# 场景1:拦截请求,返回模拟数据(无需依赖后端)
def test_network_intercept():with sync_playwright() as p:page = p.chromium.launch(headless=False).new_page()# 拦截所有/api/user开头的请求,返回模拟用户数据def handle_request(route):# 模拟JSON响应mock_data = {"code": 200,"data": {"name": "模拟用户", "age": 25}}route.fulfill(status=200,content_type="application/json",body=str(mock_data).replace("'", '"')  # 转换为JSON字符串)# 注册拦截规则page.route("**/api/user", handle_request)# 导航到页面,触发请求page.goto("https://example.com/user")# 断言页面显示模拟数据expect(page.get_by_text("模拟用户")).to_be_visible()# 场景2:模拟弱网状态
def test_weak_network():with sync_playwright() as p:# 创建浏览器上下文时设置网络条件context = p.chromium.launch_persistent_context(headless=False,network_conditions={"download": 500 * 1024, "upload": 500 * 1024, "latency": 2000}# 下载/上传速度:500KB/s,延迟:2000ms(弱网))page = context.new_page()page.goto("https://example.com")# 验证弱网下页面加载状态expect(page.get_by_text("加载中...")).to_be_visible(timeout=10000)  # 延长超时时间context.close()

(5)录制与代码生成

Playwright内置codegen工具,可通过可视化操作录制代码,适合新手快速入门或复杂页面的代码生成:

# 命令格式:playwright codegen [URL]
playwright codegen https://www.baidu.com

运行命令后,会打开两个窗口:

  • 浏览器窗口:手动操作页面(如搜索、点击),操作会被录制。

  • 代码窗口:实时生成对应的Python/JS/C#代码。

录制完成后,代码可直接保存为文件,稍作优化即可用于自动化测试,极大降低了入门成本。

三、Playwright 核心使用场景:从测试到自动化

Playwright的灵活性使其适用于多种场景,以下是最典型的5类场景,附实战思路:

3.1 场景1:UI自动化测试(跨浏览器+响应式)

核心需求:验证页面UI在不同浏览器、不同分辨率下的一致性,确保功能正常。

Playwright优势:一套代码跨Chromium/Firefox/WebKit,原生支持响应式模拟。

实战案例:电商首页UI测试(验证导航栏、轮播图、商品列表)

import pytest
from playwright.sync_api import sync_playwright# 跨浏览器测试:参数化浏览器类型
@pytest.mark.parametrize("browser_type", ["chromium", "firefox", "webkit"])
def test_ecommerce_homepage(browser_type):with sync_playwright() as p:# 启动指定浏览器browser = getattr(p, browser_type).launch(headless=True)  # 无头模式,适合CIpage = browser.new_page()# 响应式测试:模拟不同设备分辨率viewports = [{"width": 1920, "height": 1080},  # 桌面{"width": 1366, "height": 768},   # 笔记本{"width": 375, "height": 667}    # 手机(iPhone 8)]for viewport in viewports:page.set_viewport_size(viewport)page.goto("https://example-ecommerce.com")# 1. 验证导航栏可见expect(page.get_by_test_id("navbar")).to_be_visible()# 2. 验证轮播图加载完成expect(page.locator(".carousel-item.active")).to_be_visible()# 3. 验证商品列表至少有10个商品expect(page.locator(".product-card")).to_have_count(10, timeout=10000)print(f"✅ {browser_type} - {viewport} 测试通过")browser.close()

3.2 场景2:端到端(E2E)测试(全业务流程)

核心需求:模拟真实用户操作全流程(如“登录→搜索商品→加入购物车→下单”),验证业务逻辑正确性。

Playwright优势:自动等待、多页面处理、网络控制,确保流程稳定性。

实战案例:电商下单全流程测试

from playwright.sync_api import sync_playwright
from utils.config import Config  # 自定义配置,存储测试账号config = Config()
TEST_USER = config.get("username")
TEST_PASS = config.get("password")def test_ecommerce_checkout():with sync_playwright() as p:browser = p.chromium.launch(headless=False)page = browser.new_page()page.goto("https://example-ecommerce.com")# 步骤1:登录page.get_by_text("登录").click()page.get_by_label("用户名").fill(TEST_USER)page.get_by_label("密码").fill(TEST_PASS)page.get_by_role("button", name="登录").click()expect(page.get_by_text(f"欢迎回来,{TEST_USER}")).to_be_visible()# 步骤2:搜索商品page.get_by_test_id("search-input").fill("无线耳机")page.get_by_test_id("search-btn").click()expect(page.get_by_text("搜索结果:无线耳机")).to_be_visible()# 步骤3:加入购物车page.locator(".product-card").filter(has_text("无线耳机Pro")).get_by_text("加入购物车").click()expect(page.get_by_test_id("cart-count")).to_have_text("1")# 步骤4:进入购物车并结算page.get_by_test_id("cart-icon").click()page.get_by_text("去结算").click()# 步骤5:填写收货地址(假设已保存地址,直接选择)page.get_by_label("选择地址").click()page.get_by_text("北京市海淀区xx路").click()# 步骤6:提交订单page.get_by_role("button", name="提交订单").click()# 断言:订单提交成功expect(page.get_by_text("订单提交成功")).to_be_visible()expect(page.get_by_test_id("order-id")).to_be_visible()  # 验证订单号生成print(f"✅ 下单流程测试通过,订单号:{page.get_by_test_id('order-id').text_content()}")browser.close()

3.3 场景3:可视化回归测试(截图+视频)

核心需求:UI迭代后,自动对比页面截图,发现视觉差异(如按钮位置、颜色、文字变化)。

Playwright优势:支持全页截图、元素截图、视频录制,结合第三方工具(如playwright-snapshot)实现差异对比。

实战案例:页面截图对比(首页改版后回归)

from playwright.sync_api import sync_playwright
import os
from PIL import Image
from pixelmatch.contrib.PIL import pixelmatchdef test_visual_regression():# 1. 定义截图路径base_screenshot_path = "screenshots/base/homepage.png"  # 基准截图(旧版)new_screenshot_path = "screenshots/new/homepage.png"    # 新截图(新版)diff_path = "screenshots/diff/homepage.png"             # 差异截图# 2. 创建目录(若不存在)os.makedirs(os.path.dirname(base_screenshot_path), exist_ok=True)os.makedirs(os.path.dirname(new_screenshot_path), exist_ok=True)os.makedirs(os.path.dirname(diff_path), exist_ok=True)# 3. 生成新截图(新版页面)with sync_playwright() as p:page = p.chromium.launch(headless=True).new_page()page.goto("https://example-ecommerce.com")page.screenshot(path=new_screenshot_path, full_page=True)  # 全页截图# 4. 对比新旧截图(若基准截图不存在,先创建)if not os.path.exists(base_screenshot_path):# 首次运行,保存基准截图import shutilshutil.copy(new_screenshot_path, base_screenshot_path)print("⚠️  基准截图不存在,已创建,下次运行将进行对比")return# 5. 像素级对比base_img = Image.open(base_screenshot_path)new_img = Image.open(new_screenshot_path)diff_img = Image.new("RGB", base_img.size)# 计算差异像素数diff_pixels = pixelmatch(base_img, new_img, diff_img, threshold=0.1)# 6. 保存差异截图并断言diff_img.save(diff_path)assert diff_pixels == 0, f"❌ 视觉差异检测失败,差异像素数:{diff_pixels},差异截图已保存至 {diff_path}"print("✅ 视觉回归测试通过,无差异")

3.4 场景4:合法网络爬虫(数据采集)

核心需求:从动态渲染的网站(如SPA)采集数据(如商品信息、新闻内容),传统爬虫(如Requests)无法获取JS渲染后的数据。

Playwright优势:支持JS渲染,可模拟用户操作(如滚动加载、点击展开),获取动态数据。

实战案例:采集电商商品列表数据(滚动加载更多)

from playwright.sync_api import sync_playwright
import jsondef crawl_ecommerce_products():products = []with sync_playwright() as p:browser = p.chromium.launch(headless=True)  # 无头模式,隐蔽采集page = browser.new_page()page.goto("https://example-ecommerce.com/category/electronics")# 滚动加载更多商品(模拟用户滚动)last_height = page.evaluate("document.body.scrollHeight")while True:# 滚动到底部page.evaluate("window.scrollTo(0, document.body.scrollHeight)")# 等待新商品加载page.wait_for_timeout(2000)  # 等待2秒(根据网站调整)# 检查是否加载完成new_height = page.evaluate("document.body.scrollHeight")if new_height == last_height:breaklast_height = new_height# 采集所有商品数据product_cards = page.locator(".product-card").all()for card in product_cards:product = {"name": card.locator(".product-name").text_content(),"price": card.locator(".product-price").text_content(),"rating": card.locator(".product-rating").text_content(),"sales": card.locator(".product-sales").text_content().replace("销量:", ""),"link": card.locator(".product-link").get_attribute("href")}products.append(product)browser.close()# 保存数据到JSON文件with open("ecommerce_products.json", "w", encoding="utf-8") as f:json.dump(products, f, ensure_ascii=False, indent=2)print(f"✅ 数据采集完成,共采集 {len(products)} 个商品,已保存至 ecommerce_products.json")return products# 运行采集
crawl_ecommerce_products()

⚠️ **注意**:爬虫需遵守网站robots.txt协议,仅用于合法数据采集,避免过度请求影响网站正常运行。

3.5 场景5:自动化运维(定期检查+告警)

核心需求:定期检查网站可用性(如是否能正常访问、关键接口是否可用),异常时发送告警(邮件/企业微信)。

Playwright优势:轻量、稳定,可结合定时任务(如Cron、Airflow)实现自动化检查。

实战案例:网站可用性监控(每日9点检查,异常时发邮件)

from playwright.sync_api import sync_playwright
import smtplib
from email.mime.text import MIMEText
from datetime import datetime# 邮件配置
SMTP_SERVER = "smtp.qq.com"
SMTP_PORT = 465
SMTP_USER = "your-email@qq.com"
SMTP_PASS = "your-app-password"  # 邮箱授权码
RECIPIENTS = ["admin@example.com"]def send_alert_email(error_msg):"""发送告警邮件"""subject = f"【网站监控告警】{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"content = f"网站可用性检查失败,错误信息:\n{error_msg}"msg = MIMEText(content, "plain", "utf-8")msg["Subject"] = subjectmsg["From"] = SMTP_USERmsg["To"] = ",".join(RECIPIENTS)try:with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as server:server.login(SMTP_USER, SMTP_PASS)server.sendmail(SMTP_USER, RECIPIENTS, msg.as_string())print("⚠️  告警邮件已发送")except Exception as e:print(f"❌ 告警邮件发送失败:{str(e)}")def check_website_availability():"""检查网站可用性"""try:with sync_playwright() as p:browser = p.chromium.launch(headless=True)page = browser.new_page()# 1. 检查首页可访问page.goto("https://example.com", timeout=10000)  # 10秒超时assert page.title() == "Example Website", f"页面标题异常:{page.title()}"# 2. 检查关键接口(如登录接口)response = page.request.get("https://example.com/api/health", timeout=5000)assert response.status == 200, f"健康检查接口异常,状态码:{response.status}"assert response.json()["status"] == "ok", f"接口返回异常:{response.json()}"# 3. 检查关键按钮可点击expect(page.get_by_text("立即体验")).to_be_visible(timeout=5000)browser.close()print(f"✅ 网站可用性检查通过({datetime.now().strftime('%Y-%m-%d %H:%M:%S')})")return Trueexcept Exception as e:error_msg = f"{str(e)}"print(f"❌ 网站可用性检查失败:{error_msg}")send_alert_email(error_msg)return False# 运行检查(可结合Cron定时执行)
if __name__ == "__main__":check_website_availability()

四、Playwright 最佳实践:提升效率与稳定性

4.1 优先使用 Page Object(PO)模式

对于复杂项目,使用PO模式封装页面元素和操作,降低维护成本(参考前文PO模式博客)。示例:

# page_objects/home_page.py
class HomePage:def __init__(self, page):self.page = page# 封装元素self.search_input = page.get_by_test_id("search-input")self.search_btn = page.get_by_test_id("search-btn")self.login_link = page.get_by_text("登录")# 封装操作def search_product(self, keyword):self.search_input.fill(keyword)self.search_btn.click()return SearchResultPage(self.page)  # 返回新页面实例# 测试用例中使用
def test_search():with sync_playwright() as p:page = p.chromium.launch().new_page()home_page = HomePage(page)home_page.page.goto("https://example.com")search_result_page = home_page.search_product("无线耳机")expect(search_result_page.get_result_count()).to_be_greater_than(0)

4.2 定位策略:优先使用 data-testid

开发时在元素上添加data-testid属性(专为测试设计,不随UI变更),避免依赖classXPath

<!-- 推荐:添加data-testid -->
<button data-testid="submit-btn" class="btn-primary">提交</button><!-- 不推荐:class可能随样式变更 -->
<button class="btn-primary submit-btn-v2">提交</button>

Playwright定位:

# 推荐
page.get_by_test_id("submit-btn").click()# 不推荐(class变更会导致定位失败)
page.locator(".btn-primary.submit-btn-v2").click()

4.3 并行执行测试用例

结合pytest-xdist实现并行执行,提升测试效率:

# 安装插件
pip install pytest-xdist# 4个进程并行执行所有用例
pytest test_playwright/ -n 4

4.4 集成日志与报告

使用loguru记录日志,allure-pytest生成可视化报告:

# 安装依赖
pip install loguru allure-pytest# 执行用例并生成Allure报告
pytest test_playwright/ --alluredir=allure-results# 查看报告
allure serve allure-results

五、常见问题与解决方案

5.1 问题1:元素定位不到,提示“Timeout”

原因:元素未加载完成、在iframe中、定位方式依赖易变属性。

解决方案

  • 优先使用get_by_testid/get_by_text等语义化定位;

  • 确认元素是否在iframe中,使用frame_locator定位;

  • 延长超时时间(如expect(page.get_by_testid("btn")).to_be_visible(timeout=15000))。

5.2 问题2:浏览器启动失败,提示“Browser not found”

原因:浏览器驱动未安装或版本不匹配。

解决方案

  • 执行playwright install重新安装驱动;

  • 若指定浏览器(如Firefox),确保已安装:playwright install firefox

5.3 问题3:录制的代码冗余,如何优化?

原因codegen会录制所有操作,包括多余的点击和等待。

解决方案

  • 删除冗余的wait_for_timeout(Playwright自动等待);

  • 将重复操作封装为函数(如登录、搜索);

  • 替换locatorget_by_*语义化定位。

六、总结:Playwright 为何成为自动化首选?

Playwright的出现,重新定义了UI自动化的体验——它解决了传统工具的“痛点”(如等待、跨浏览器、复杂场景),同时降低了入门门槛(录制功能、简洁API)。无论是UI自动化测试、E2E测试,还是数据采集、自动化运维,Playwright都能以“稳定、高效、易用”的特性胜任。

对于测试工程师:Playwright大幅降低维护成本,一套代码覆盖所有浏览器,可视化回归测试提升效率;

对于开发工程师:可快速编写E2E测试,验证功能完整性,配合CI/CD实现自动化部署;

对于数据分析师:无需掌握复杂JS逆向,即可采集动态渲染网站的数据。

如果你还在为Selenium的等待问题、跨浏览器兼容性烦恼,不妨试试Playwright——它可能会成为你自动化工具链中的“终极解决方案”。

http://www.dtcms.com/a/389572.html

相关文章:

  • OpenCV:直接用NV21/NV12格式,画线、贴图都是相加效果,而不是替换、覆盖
  • MCP3421与STM32电压采集实现
  • 表白网页制作免费网站制作 表白网站建设教程
  • 嵌入式Linux C语言程序设计一、二
  • cocos做简单自动发射追踪子弹 切换敌人
  • C#知识学习-014(修饰符_3)
  • Linux 下逆向解析 VNC Server 密码文件为明文密码(逆向解析passwd)
  • Linux dma_resv机制原理、实现与应用详解
  • LangGraph 进阶学习
  • Alibaba Cloud Linux与 RHEL/CentOS版本对应关系
  • Python实现PDF文本与表格转换
  • 医疗行业数字化转型:构建安全合规、高效协同的智慧医疗文档管理新范式
  • 怎么看一个网址是否安全?
  • 【LLM】RAG架构如何重塑大模型
  • 企业级数据库管理实战(四):从 C/S 到 B/S架构,数据库管理工具的演进
  • 基于AI的PDF复杂表格结构识别与智能解析(方案1)
  • CS336第三课
  • 云蝠智能大模型呼叫对话延迟无限接近1秒
  • Datax-web安装 | 配置环境
  • 算法<java>——查找(顺序、二分、插值、分块、斐波那契)
  • Mysql杂志(十九)——InnoDB的索引结构
  • CrowdStrike推出AI驱动新工具 聚焦补丁管理与威胁情报短板
  • 收集飞花令碎片——C语言指针
  • MySQL 初识:架构定位与整体组成
  • 【开发者导航】规范驱动且开源的 AI 时代开发流程工具:GitHub Spec-Kit
  • 区块链加速器:Redis优化以太坊交易池性能方案
  • 资源分布的均衡性(Poisson Disk Sampling)探索
  • STM32开发(中断模式)
  • Qt QPieSlice详解
  • C++多线程编程