Playwright + Python 自动化测试入门:从零搭建稳定脚本

做自动化测试这几年,我换过好几套方案,Playwright 配合 Python 算是我用得最顺手的一组搭档。它本身就是开源的浏览器自动化框架,主打 Web 端到端测试,支持 Chromium、Firefox、WebKit 三种内核,Python 版本同步异步 API 都做得很清爽。我接触它之前,主要靠 Selenium 撑场面,选择器不稳定、等待全靠 sleep、弹窗处理麻烦,这些问题在 Playwright 里基本被机制层面解决掉了。很多刚入门的读者问过我同一个问题:能不能用一下午时间,搭出第一个能跑、能断言、能保留证据的自动化脚本?我的回答是可以,而且不用依赖任何复杂的外部测试网站。这篇会从环境搭建讲起,带你写通最小脚本,再把它改造成正式的 Pytest 用例,顺便把定位器、断言、调试工具和常见坑位一次串完,代码都放在对应章节里直接复制。

1. 为什么选 Playwright:自动等待、多内核与适用场景

1.1 自动等待机制才是最大的分水岭

先说说大家最熟悉的痛点:元素等待。以前写 Selenium 脚本,最怕的就是刚跳完页面就去找元素,报找不到;加 time.sleep 又不知道该等多久,等短了照样翻车,等长了拖慢整个测试。Playwright 的做法是从机制上改变这一切:它对每个动作内置了可操作性判断。比如点击一个按钮,它会先轮询检查这个元素是否可见、是否稳定、是否被其他元素遮挡、是否处于可交互状态,全部满足才真正执行点击,默认超时 30 秒。

这个机制靠的是"查询-检查-操作"三步一体的流程。你在代码里传给它一个选择器,它会反复重新查询 DOM,等元素状态达到可交互再操作,期间不需要任何显式等待代码。结果是脚本变得非常直白:写法和手工操作步骤一一对应,但稳定性却比塞了一堆 sleep 的老脚本高得多。我见过很多从 Selenium 转过来的同事,改完第一批用例之后的第一反应基本都是:原来真的可以不用等。

1.2 三种浏览器内核,一份代码全覆盖

Playwright 的最大卖点之一,是一套代码能在 Chromium、Firefox、WebKit 三种浏览器内核上跑,而且不需要自己管理驱动。它有自己的浏览器二进制管理机制,执行 playwright install 后会按固定版本把内核下载到本地缓存目录,项目里锁定好依赖版本,测试环境就能保持一致。

这一点看似小,实际省掉的坑非常多。Selenium 时代,驱动版本和浏览器版本严格对应,浏览器一自动升级,驱动立刻报错;Playwright 把浏览器二进制和库捆绑管理,安装哪个版本就配套哪个内核,升级也是主动执行的。对需要在多内核上验证兼容性的项目来说,这一条基本可以无脑选它。哪怕你暂时只测 Chromium,这个设计也意味着你在 CI 上构建出来的环境是确定的,不会出现"本地能过、CI 上莫名其妙挂"的版本漂移问题。

1.3 适用场景与选型建议:什么项目该用它

我个人的判断标准很简单:只要需求是"完整打开真实浏览器,走一遍真实用户的路径",就属于 Playwright 的射程。最典型的是 Web 端到端测试、登录注册流程回归、电商核心链路冒烟、自动化截图与页面监控、内部工具的数据回填和批量操作。很多偏运维的活儿,比如每天定时打开某个后台导出报表,或者批量对一组页面做可用性检查,用它也能干得很顺手。

反过来,如果只是测纯接口、做单元测试,就别拿它去凑热闹,轻量方案在速度和资源占用上优势明显。另外要提醒一下:自动化工具有能力不等于可以滥用,去抓别人站点数据之前,先确认目标站点的服务条款和使用边界,这是从业者基本的自觉。工具本身不负责合规,责任在你自己。

2. 十分钟搭好环境:Python 虚拟环境与 Playwright 安装验证

2.1 准备 Python 环境和虚拟环境

Playwright 的 Python 库要求 Python 3.8 以上,我建议直接装 3.10 或更高版本,类型标注和内置特性会让后面写代码更舒服。Windows、macOS、主流 Linux 的安装差异不大,核心是先建一个干净的虚拟环境,再往里面装依赖。

python -m venv .venv # Windows .venv\Scripts\activate # macOS / Linux source .venv/bin/activate

为什么一定要虚拟环境?自动化测试项目往往不止一个依赖工具,pytest、playwright、各种辅助库混装在一起,时间一长必然出冲突。虚拟环境把项目依赖隔离到独立目录,换项目就换环境,谁也不碍谁。一个小细节:Windows 上如果装了多个 Python 版本,用 py -3.10 -m venv .venv 显式指定解释器版本,避免建完环境才发现用的是旧版 Python。

2.2 安装 Playwright 库与浏览器内核

环境激活后输入两条命令:

pip install playwright playwright install chromium

第一条装 Playwright 的 Python 库,里面包含完整 API、命令行工具和选择器引擎;第二条下载配套的 Chromium 浏览器内核。很多新手装完库就直接跑脚本,然后报错说浏览器启动失败,基本都是漏了后面这一步。如果后面需要在 Firefox 和 WebKit 上验证,再把对应内核补上:

playwright install firefox webkit

如果你的机器是比较精简的 Linux 环境,浏览器内核装完可能还缺系统层面的运行库,这时候可以先执行 playwright install-deps 让工具自动补齐系统依赖,然后再执行 playwright install。我建议连同 pytest-playwright 一起装,一步到位。它是 Pytest 的官方插件,提供 page、context、browser 等现成夹具,还能在命令行里切换有头无头、指定浏览器,测试组织效率高很多:

pip install pytest-playwright

2.3 冒烟脚本验证安装成功

环境装完先别急着写正式用例,跑一个最小脚本确认整条链路是通的。新建 smoke.py:

from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto("https://example.com") print("页面标题:", page.title()) browser.close()

执行 python smoke.py,控制台输出"页面标题: Example Domain",环境就完全可用了。我把 headless 设成 True 是为了无头运行,适合快速验证和以后挂 CI;第一次想看真实浏览器长什么样,改成 False 即可。这一步没有通过的话,先检查虚拟环境是否激活、playwright install 是否执行成功,两个点排查完基本就能解决。

3. 吃透三大核心对象:从最小脚本理解 Browser、Context、Page

3.1 同步 API 和异步 API 怎么选

Playwright 的 Python 库提供两套 API:sync_api 和 async_api。同步版本一行接一行往下执行,心智负担小,写测试用例时最直观,也是官方文档和社区例子里的主流写法。异步版本配合 asyncio,适合高并发和已经全面异步化的项目,但它要求你在编码时认真管理任务生命周期,难度高一个台阶。

我的建议是:新手和大部分测试项目,直接用同步 API。同步版本已经能支撑绝大多数场景,且和 Pytest 兼容得非常好。异步 API 好在并发吞吐,但自动化测试里的并发通常更适合交给分布式任务框架去解决,语言层面的异步不一定是收益最大的方向。等你同步版本用熟了,再对照官方文档切异步,核心调用结构几乎不变,只是把每个动作变成 await,转换成本很低。

from playwright.async_api import async_playwright async def main(): async with async_playwright() as p: browser = await p.chromium.launch(headless=True) page = await browser.new_page() await page.goto("https://example.com") print(await page.title()) await browser.close() import asyncio asyncio.run(main())

3.2 Browser、Context、Page 的关系与隔离逻辑

理解对象模型是写 Playwright 的分水岭。三者的关系可以这样记:Browser 是整个浏览器进程,Context 相当于一个独立的"隐身会话",Page 是这个会话里的一个标签页。每次创建一个 Context,它都有一份全新的 cookie、存储、缓存和各种权限设置,互相之间不共享。

这个设计的价值在测试里极明显。你要模拟两个互不干扰的用户,就用两个 Context;一个用例要反复清空状态,就创建新 Context 而不去手动清理旧数据。我经常看到有人直接在默认 Context 里连续开多个页面,结果用例之间 cookie 串了,登录态互相影响,排查半天。养成"每个测试场景一个独立 Context"的习惯,能在源头上消掉一大类 flaky 问题。

3.3 启动、关闭的正确顺序与资源管理

启动顺序是固定的:先启动 Playwright 运行时,再启动浏览器,再创建上下文,最后打开页面。关闭时反过来:先关闭页面或上下文,再关闭浏览器。用 with sync_playwright() 包住整个逻辑,Playwright 会在退出时自动清理运行时和浏览器进程,代码简洁也安全。

但我仍建议在多浏览器或多上下文的项目里显式调用 context.close() 和 browser.close(),这样资源释放时机可控,排查并发问题时也清楚。另外要注意:浏览器关闭会同时结束它下面所有上下文和页面,不需要也不应该重复调用页面的 close 方法,重复关闭有时候反而会触发不必要的异常。

4. 手写第一个测试脚本:本地页面实战与 Pytest 用例改造

4.1 准备一个本地测试页面:不用依赖外部网站

为了让教程可复现,我不打算拿某个线上站点当靶子,而是直接在本地造一个登录页面。这样你不需要考虑外部网站的可达性、站点改版、权限验证这些额外因素,专注理解 Playwright 本身的工作方式。新建一个目录 demo_pages,把下面的 login.html 保存进去:

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>本地登录演示页</title> </head> <body> <h2>账号登录</h2> <form id="login-form"> <label for="username">用户名</label> <input id="username" name="username" type="text" placeholder="请输入用户名"> <label for="password">密码</label> <input id="password" name="password" type="password" placeholder="请输入密码"> <button id="submit-btn" type="submit">登录</button> </form> <p id="result"></p> <script> document.getElementById('login-form').addEventListener('submit', function (e) { e.preventDefault(); var u = document.getElementById('username').value; var p = document.getElementById('password').value; var r = document.getElementById('result'); if (u === 'admin' && p === '123456') { r.textContent = '登录成功,欢迎 admin'; } else if (u === '' || p === '') { r.textContent = '用户名和密码不能为空'; } else { r.textContent = '用户名或密码错误'; } }); </script> </body> </html>

保存完成后,在 demo_pages 目录下启动一个最简单的 HTTP 服务,命令是:

cd demo_pages python -m http.server 8000

启动之后用浏览器打开 http://127.0.0.1:8000/login.html 确认页面正常显示,这个操作会为后面的自动化脚本提供一个稳定的本地靶场。这个页面很简单,但覆盖了自动化测试最核心的三类元素:文本框、按钮、点击后的文本反馈。

4.2 完整脚本拆解:从打开页面到断言截图

下面这段是本次实战的核心脚本。它做了一件完整的事:打开页面、填表单、点登录、检查结果、截图留证,整个过程就是你在手工测试时做的那几步,现在完全交给代码。

from playwright.sync_api import sync_playwright BASE_URL = "http://127.0.0.1:8000/login.html" def login_with(username: str, password: str, headless: bool = True): with sync_playwright() as p: browser = p.chromium.launch(headless=headless) page = browser.new_page() page.goto(BASE_URL) page.get_by_label("用户名").fill(username) page.get_by_label("密码").fill(password) page.get_by_role("button", name="登录").click() page.locator("#result").wait_for(state="visible") result_text = page.locator("#result").text_content() print("页面反馈:", result_text) page.screenshot(path="login_result.png") browser.close() if __name__ == "__main__": login_with("admin", "123456") login_with("admin", "wrong")

逐行说一下关键点。get_by_label("用户名") 是利用 label 标签的 for 属性定位输入框,这是最贴近表单语义的做法,比硬写 CSS 选择器稳得多。get_by_role("button", name="登录") 是按可访问性角色和按钮文字定位按钮,即使按钮改了几个 class,这段代码都不受影响。

点击之后我没有立刻读结果,而是先执行 page.locator("#result").wait_for(state="visible")。这个页面是同步 JS 直接改文本,实际上不等也能读到,但养成"读数据前先等待目标出现"的习惯,遇到异步渲染的页面时就能少踩很多坑。screenshot 是证据保留环节,出问题时一张图比一行日志直观太多。运行脚本后,控制台会依次打印"页面反馈: 登录成功,欢迎 admin"和"页面反馈: 用户名或密码错误"。

如果你把 headless 改成 False 再跑一遍,还能亲眼看到浏览器真的被自动操作了,那种感觉比纯看输出要踏实得多。这一步建议新手都试一次,对理解自动化和手工操作之间的对应关系非常有帮助。

4.3 用 Pytest 升级成正式用例:夹具与命令行参数

上面那版脚本适合理解流程,但真正拿来做回归测试,还是要交给 Pytest。pytest-playwright 提供的 page 夹具里,每个测试会自动获得全新的浏览器上下文,用例之间天然隔离,这是测试框架级别的保障,比自己在脚本里创建浏览器、关闭浏览器干净很多。

先在项目根目录建一个 test_login.py:

from playwright.sync_api import Page, expect BASE_URL = "http://127.0.0.1:8000/login.html" def test_login_success(page: Page): page.goto(BASE_URL) page.get_by_label("用户名").fill("admin") page.get_by_label("密码").fill("123456") page.get_by_role("button", name="登录").click() expect(page.locator("#result")).to_have_text("登录成功,欢迎 admin") def test_login_wrong_password(page: Page): page.goto(BASE_URL) page.get_by_label("用户名").fill("admin") page.get_by_label("密码").fill("wrong") page.get_by_role("button", name="登录").click() expect(page.locator("#result")).to_have_text("用户名或密码错误")

注意 expect(...).to_have_text(...) 不是普通断言,它会自动重试,直到文本匹配或超过默认超时时间。这对异步渲染的页面特别友好:元素还没更新完它就一直等,而不是一上来就失败。执行方式也很灵活:

pytest -v pytest --headed -v pytest --browser=firefox -v

第一条按默认的 Chromium 无头模式跑全部用例;第二条弹出真实浏览器窗口,方便调试;第三条切到 Firefox 验证跨内核兼容。如果你想在 CI 里保留故障现场,推荐加 --screenshot=only-on-failure 和 --video=retain-on-failure,失败时自动收集截图和录像,排障效率立刻上来了。

5. 定位器选择与交互操作:写出稳定脚本的核心方法

5.1 首选角色定位器:让选择器贴近用户视角

脚本稳定性很大程度上取决于选择器怎么写。我最推荐的是角色定位器 get_by_role,它基于可访问性树来定位元素,本质上描述的是"这个元素在用户和辅助技术眼里是什么、叫什么"。比如 get_by_role("button", name="登录"),找的就是页面上语义为按钮、可访问名称为"登录"的元素。

为什么它比 CSS 稳定?因为 CSS 选择器依赖结构,页面改一个 class、调一层 DOM,脚本立刻断;可访问性名称则跟着页面语义走,只要按钮文案和角色不变,重构样式也不会影响脚本。写新用例时我基本都会先试试 get_by_role,配不上再考虑其他方式。一个实用小技巧:用 name 参数做匹配时,可以通过正则传参,get_by_role("button", name=re.compile("登录|提交")) 这类写法在文案经常微调的项目里非常实用。

5.2 其余定位方式怎么选:标签、占位符、CSS 和 XPath

角色定位器不是万能的,有些元素语义不明显,就得配合其他策略。常用的一并给你列清楚:

定位器使用场景示例
get_by_label表单输入框,有 label 关联时优先page.get_by_label("用户名")
get_by_placeholder只有占位提示的输入框page.get_by_placeholder("请输入邮箱")
get_by_text通过可见文本定位普通元素page.get_by_text("账号登录")
get_by_alt_text图片等带替代文本的元素page.get_by_alt_text("logo")
get_by_title带 title 属性的元素page.get_by_title("帮助文档")
locator("css=...")没有语义时的兜底选择器page.locator("#submit-btn")
locator("xpath=...")复杂层级或依赖文本的极端场景page.locator("xpath=//button[contains(text(),'登')]")

我的取舍原则是:能用语义定位就不写样式结构选择器,CSS 兜底也尽量用稳定属性。id 和稳定的>with page.context.expect_page() as new_page_info: page.get_by_role("link", name="打开新窗口").click() new_page = new_page_info.value new_page.wait_for_load_state() print(new_page.title())

iframe 里的元素不能直接在当前页面里定位,要先进 frame_locator,类似"切到另一个文档内部去找按钮":

page.frame_locator("#main-frame").get_by_role("button", name="提交").click()

系统弹窗要提前挂监听,默认情况下不处理就会一直挡住后续操作:

page.on("dialog", lambda dialog: dialog.accept()) page.get_by_role("button", name="触发弹窗").click()

文件上传用 set_input_files,把文件路径传给对应的 input 元素即可:

page.set_input_files("#upload-input", ["report.pdf"])

这四个场景单独看都不复杂,加在一起几乎能覆盖大多数业务系统的交互边界。真正写的时候建议每个都实际跑一遍,因为跨标签页和跨 frame 的错误很隐蔽,容易在项目里大面积爆发。

6. 常见报错速查与调试实录:这些坑我替你踩过了

6.1 高频报错速查表

我把实际项目里出现频率最高的几类问题汇总成一张表,方便你遇到报错时对照排查。

报错或现象常见原因处理思路
TimeoutError 等待超时元素没出现、选择器不准确、页面脚本异常先用 codegen 确认选择器;改用 expect 等待条件;打开 trace 看现场
strict mode violation选择器同时匹配了多个元素增加限定条件让定位器唯一;确实有重名时用 .nth() 明确索引
Element is not visible / not stable元素被遮挡、页面还在滚动或动画等待遮挡层消失;点击前先处理 fixed 弹层;必要时 scroll_into_view_if_needed()
点击后没有任何反应有 dialog 挡在事件流前面page.on("dialog", ...) 提前挂监听处理弹窗
新标签页打开后元素找不到当前的 page 对象还指向旧标签页用 expect_page 捕获新页面,切换到新 page 再操作
iframe 里元素定位不到定位器停留在外层页面用 frame_locator 进入 iframe 后再定位
中文输入出现乱码部分输入框对模拟按键不友好优先用 fill 直接赋值,避免逐字 send_keys
无头与有头表现不一致渲染、字体、视口差异显式设置 viewport;必要时用 headed 模式复现现场

这张表解决的不全是"方案问题",很多是"习惯问题"。比如超时,第一时间不是加大超时时间,而是确认元素在页面里真实存在、选择器真的写得对。调试工具比盲目调参高效得多。

6.2 调试四件套:codegen、Inspector、Trace 与证据收集

我调试 Playwright 脚本几乎不靠读日志硬想,有一套固定动作。第一个是 codegen,它能把手动操作直接录成脚本。启动命令是:

playwright codegen http://127.0.0.1:8000/login.html

它会打开一个带操作面板的浏览器,你点哪里、填什么,右侧自动生成对应代码。写新用例时先"点一遍",生成的代码再做修改,效率非常高。第二个是 Inspector 调试器,在脚本里某行插入 page.pause(),运行后浏览器会停顿并打开 Playwright Inspector 面板,可以一步步查看元素、执行操作、验证选择器。它还能快速测试当前选择器匹配了几个元素,定位严格模式违规特别有用。

第三个是 Trace 追踪。运行 pytest 时加 --tracing=retain-on-failure,失败用例会自动生成 trace.zip,然后执行 playwright show-trace trace.zip,打开一个包含完整时间线的查看器,能看到每一步操作的快照、网络请求和控制台日志。很多疑难杂症,我都是靠这个时间线定位的。第四个是证据收集,前面提过的 --screenshot=only-on-failure 和 --video=retain-on-failure,这两组参数建议团队统一写进 Pytest 配置里,每个人跑用例挂了都知道去哪看截图和录像。

6.3 几个最典型的踩坑记录

分享几条我记忆比较深的经验教训。第一,永远不要依赖用例执行顺序。Pytest 默认按文件名和行号执行,但你要假设下一次执行顺序是随机的。某个用例依赖前一个用例的登录态,一旦加了并发就全废。正确做法是每个用例独立准备数据,用独立 Context 隔离登录态,用例之间不共享任何东西。

第二,别覆盖掉插件提供的 page 夹具。pytest-playwright 已经给了很完善的 page、context、browser 夹具,有些同学为了一点定制需求,自己写了一个叫 page 的 fixture 把它覆盖了,结果测试隔离性直接失效。如果真要定制启动参数,用 pytest 配置里的 launch 参数,或者自定义一个名字不同的 fixture 组合出你需要的东西。

第三,写用例的时候多用固定测试数据。真实业务系统里常见的问题是同一个用户名反复注册会冲突、验证码没法自动读取、时间戳导致断言不稳定。要么用固定测试账号并在用例里做好清理,要么生成唯一随机数据再断言。自动化的敌人从来不是复杂,而是不确定性,所有让结果"可预测"的努力都值得。

最后再从个人使用经验出发多说一句:写脚本时我习惯把关键操作封装成小的页面动作函数,比如 login_with(username, password),让用例主体读起来像自然语言。团队协作时,别人扫一眼就能看懂测试意图,后续维护成本低很多。接下来值得继续做的方向,是把 Pytest 配置里的 base-url、浏览器和证据收集参数固定下来,然后接到 CI 上,每次提交自动跑一遍回归。我自己维护的几个项目都走这个路子,跑得越勤,发现的回归越多,脚本反而越写越稳。

相关新闻

三菱FX3U PLC与FR-E700变频器Modbus RTU通讯改造详解

三菱FX3U PLC与FR-E700变频器Modbus RTU通讯改造详解

做电气调试这些年&#xff0c;PLC和变频器之间的通讯改造是一项高频需求。最近刚完成了一套三菱FX3U PLC与三菱FR-E700变频器的Modbus RTU通讯项目&#xff0c;实现启停、正反转、频率给定和运行频率读取。这类方案在小型自动化设备、风机水泵控制、输送线改造里出现频率很高&a…

2026/10/20 18:58:59 阅读更多 →
NSGA-III求解微电网多目标优化调度:Matlab实现与工程实践

NSGA-III求解微电网多目标优化调度:Matlab实现与工程实践

做微电网优化调度的人&#xff0c;多半都经历过这种纠结&#xff1a;费大力气算出一个运行成本最低的方案&#xff0c;结果环保考核指标一路飘红&#xff1b;把碳排放压下来&#xff0c;购电成本又嗖嗖往上涨。这种“按下葫芦浮起瓢”的矛盾&#xff0c;本质上是多目标优化问题…

2026/10/20 18:57:58 阅读更多 →
遥感水体分割数据集:

遥感水体分割数据集:

遥感水体分割数据集: 数据1:8bit三通道&#xff08;RGB&#xff09;数据,gaofen2影像&#xff0c;共7000余高分辨率&#xff08;10241024&#xff09;图像&#xff0c;采用mask图形式标注&#xff0c;16GB数据量 数据2:16bit4通道&#xff08;RGBNIR&#xff09;数据&#xff0…

2026/10/20 18:57:58 阅读更多 →

最新新闻

MSA存储入门指南:从SAN协议到选型场景的全面解析

MSA存储入门指南:从SAN协议到选型场景的全面解析

简介&#xff1a;这份文档面向备考H3C认证工程师-MSA存储&#xff08;H3CNE-MSA&#xff09;的技术人员与H3C代理服务工程师&#xff0c;聚焦MSA存储设备基础配置与维护知识&#xff0c;帮助读者在有限时间内系统梳理考点、检验掌握程度。资源为1个docx文件&#xff0c;压缩包约…

2026/10/20 19:39:14 阅读更多 →
C语言大作业高分实践:工程结构、内存安全与评分对齐

C语言大作业高分实践:工程结构、内存安全与评分对齐

简介&#xff1a;这是一份面向高校C语言初学者与课程设计学生的高分期末大作业实战项目&#xff0c;完整实现了一个具备学生端与管理员双角色的学生成绩管理系统。资源包含可直接编译运行的C/Qt源码&#xff08;含18个.h头文件与18个.cpp实现文件&#xff09;、图形界面.ui文件…

2026/10/20 19:39:14 阅读更多 →
Redis Java客户端选型与实战:Jedis、Lettuce、Redisson对比

Redis Java客户端选型与实战:Jedis、Lettuce、Redisson对比

1. 先搞清楚需求&#xff0c;再选客户端写Java应用连Redis&#xff0c;第一步不是去翻依赖、复制代码&#xff0c;而是先想清楚&#xff1a;你的业务到底需要Redis做什么&#xff0c;以及你的应用是什么形态。这话可能听起来像废话&#xff0c;但我在实际项目里见过太多人一上来…

2026/10/20 19:39:14 阅读更多 →
轻量级AI助手ZeroClaw实战:有限算力下的部署与Agent落地

轻量级AI助手ZeroClaw实战:有限算力下的部署与Agent落地

1. 项目定位&#xff1a;为什么轻量级AI助手反而更实用去年年底我拿到一台配置平平的旧工作站&#xff0c;8GB内存、无独显、CPU还是几年前的型号&#xff0c;跑几个容器就喘。当时手头正好有个工具自动化需求&#xff1a;定时抓取内部系统数据&#xff0c;做简单清洗&#xff…

2026/10/20 19:39:14 阅读更多 →
单相桥式半控整流电路原理与Matlab/Simulink仿真建模分析

单相桥式半控整流电路原理与Matlab/Simulink仿真建模分析

单相桥式半控整流电路&#xff0c;这个名字在电力电子课程里出现的频率极高。很多电气工程专业的朋友第一次接触晶闸管整流&#xff0c;就是从它开始的。最近正好有人在问Matlab仿真的思路&#xff0c;我把自己做这个仿真报告的全过程梳理了一遍&#xff0c;从拓扑结构分析到模…

2026/10/20 19:39:14 阅读更多 →
Java动漫链接生成器:批量整理番剧资源链接的轻量工具

Java动漫链接生成器:批量整理番剧资源链接的轻量工具

简介&#xff1a;这是一款面向动漫资源采集与二次元工具开发者的轻量级命令行程序&#xff0c;基于Java实现&#xff0c;可根据指定标签批量生成动漫图片链接&#xff0c;适合需要批量获取Danbooru图源、做数据采集或练手Java命令行项目的开发者。资源包共17个文件&#xff0c;…

2026/10/20 19:38:12 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →