新闻详情

新闻详情

首页 / 资讯中心 / 详情

C++ Web自动化测试实战:WebDriver常用函数与场景化用法

发布时间:2026/9/26 14:01:05来源:尧图网络
C++ Web自动化测试实战:WebDriver常用函数与场景化用法
日常做Web自动化测试大部分团队的首选都是Python或Java加SeleniumC听起来像是个局外人。但当我真正接手一个对回归频率要求极高、又必须把自动化测试塞进现有C工具链的项目时我发现C不仅能干这活在特定场景下反而更顺手。这篇文章不打算堆概念而是从实战角度把C配合WebDriver做Web自动化测试的常用函数、场景化用法、踩坑记录完整讲一遍给正在研究这个组合的开发者一份能直接落地的参考。无论是你准备把测试框架统一到C还是需要处理动态加载的网页数据又或是被各种“元素找不到”“驱动崩溃”折腾到头大这篇内容都值得往下看。我会尽量讲清楚每一步为什么这么做而不是只丢给你一段能跑就算完的代码。1. 整体思路为什么我会用C做Web自动化测试1.1 这个项目到底解决了什么问题很多人对C做自动化测试的第一反应是“没必要”。代码多、内存要自己管、字符串处理比Python啰嗦听起来全是劣势。但在实际工作里需求不会按语言舒适区来。我有一次碰到的情况是被测系统是一个运行在Windows环境下的工业管理平台业务逻辑本身大量复用了C动态库测试团队希望自动化用例直接调用内部接口校验数据同时又要在真实浏览器里完成端到端流程。这种情况下如果测试脚本用Python就得维护一套跨语言的接口调用中间层成本和出错概率都很高直接把测试用C写反而能和业务代码共用同一套数据结构和编译产物。再一个是性能。浏览器自动化里那些高频操作比如不停刷新页面检查渲染状态、并发拉起多个浏览器实例做压力型回归测试C静态编译后没有解释型语言的执行开销资源占用明显低。我的实测感受是同样的用例规模C框架的进程启动速度比Python版本快一倍左右这在跑几百条用例的回归任务里很有感知。这套方案适合谁适合那些已经有C基础、不想再引入第二套语言生态的团队也适合需要把Web自动化测试和现有C单元测试、CI流程深度集成的工程师。如果你恰好是纯前端背景想学自动化那Python可能上手更快但如果你在C工程里待过一段时间用这个组合会让你少很多跨语言的沟通成本。1.2 技术栈选型WebDriver、Playwright还是直接HTTP确定用C以后面对的第二个问题是选哪套驱动方案。目前主流路线有三条方案通信方式C生态成熟度使用场景Selenium WebDriverHTTP协议 浏览器原生驱动高社区封装多兼容性要求高的通用Web测试PlaywrightCDP协议 自家Driver中C社区版维护一般需要细粒度网络、事件控制直接用HTTP库拼接协议自己构造W3C WebDriver请求低但完全可控特殊协议需求或极简依赖环境我最终选择的是WebDriver路线。原因很简单WebDriver是W3C标准化协议浏览器厂商都会维护对应的原生驱动比如ChromeDriver、GeckoDriver。协议层不绑定任何语言C客户端理论上和Python、Java客户端用的是同一个接口这意味着稳定性有保证出了兼容性问题也能在社区找到大量参考。Playwright那套虽然功能更现代但C绑定基本都是第三方社区维护版本升级时API剧烈变动团队要花额外精力去跟进。用生活类比来理解这套架构浏览器是一个黑盒工人WebDriver协议是双方约定好的“指令手册”C代码就是监工。监工不关心工人在车间内部怎么干活只需要按手册传递指令拿到结果。所以核心技术不在“怎么写C”而在“怎么用好协议对应的函数”。1.3 环境准备与最小可运行示例选定了WebDriver之后环境准备比想象中简单。我目前的核心依赖就三样CMake、一个CWebDriver客户端库、浏览器驱动。客户端库我建议直接用vcpkg安装比如webdriverxx这个开源库接口风格接近新版客户端维护得还算勤快。装好之后一段最小可运行代码长这样#include webdriverxx/webdriver.h #include iostream using namespace webdriverxx; int main() { try { Driver driver StartChromeDriver( http://localhost:9515, Capabilities().SetHeadless(true) ); driver.Navigate(https://example.com); std::cout 当前页面标题: driver.GetTitle() std::endl; driver.Quit(); } catch (const std::exception e) { std::cerr 自动化测试失败: e.what() std::endl; return 1; } return 0; }这段代码值得拆开讲一下。StartChromeDriver第一参数是ChromeDriver监听的地址默认是localhost:9515第二参数Capabilities是浏览器能力配置SetHeadless(true)代表无头模式CI环境里没有显示器也能跑。Navigate会阻塞到页面主文档加载完成但不代表所有异步内容都加载好了这个细节后面场景部分会展开。GetTitle是多数网页测试的第一个断言点能快速判断驱动是否工作正常。实际项目里我不会开发时也开headless因为调试时需要肉眼观察浏览器的行为。更推荐的做法是把headless参数做成可配置项本地调试用有头CI里用无头。开发阶段裸跑很容易踩一些和屏幕分辨率、GPU渲染相关的坑这些问题后面章节详细说。2. 常用函数全解析从会话建立到元素操作2.1 会话初始化与浏览器能力配置WebDriver的整个生命周期就是“会话”的生命周期。StartChromeDriver会创建一个会话返回的Driver对象管理这个会话的所有后续操作所以千万别把它当普通值到处拷贝一旦会话被关掉任何调用都会直接抛异常。实际项目中能力配置直接关系到用例稳定性。除了SetHeadless我还会固定加这几个参数Capabilities caps; caps.SetHeadless(true); caps.Set(goog:chromeOptions, {\args\:[\--disable-gpu\,\--window-size1920,1080\,\--no-sandbox\]});--disable-gpu在无头环境里能避免大部分WebGL相关的莫名崩溃--window-size固定成1920x1080是为了统一CSS渲染和截图尺寸不然不同机器上可能因为默认窗口大小不同导致某些元素不在视口内--no-sandbox是CI容器的常规操作因为容器里经常没有完整的权限体系。后端通信上我建议把驱动服务单独启动成进程而不是让测试代码直接拉起驱动。这样做的好处是测试崩溃时还能保留一个可检查的浏览器实例而不是浏览器跟随测试进程一起消亡现场调查时非常有价值。具体到项目里就是一个简单的命令行操作chromedriver.exe --port9515然后测试代码只负责连接。2.2 元素定位函数id、CSS选择器与XPath的取舍定位元素是Web自动化里出镜率最高的操作。C客户端库提供的核心函数就两类FindElement和FindElements前者返回单个元素后者返回元素列表。它们的第一个参数是定位策略WebElement button driver.FindElement(By::Id(submit-btn)); WebElement link driver.FindElement(By::CssSelector(.nav .login)); WebElement cell driver.FindElement(By::XPath(//table/tbody/tr[2]/td[3]));三种定位方式各有应用场景不能只会一种就硬套。我用生活类比来区分By::Id就像直接给人报门牌号最快最准但前提是页面真的有idCSS选择器就像“小区单元房号”的组合检索速度快、表达力强适合结构清晰的页面XPath则像“从大门口开始左转、直行、再左转”的路径描述最灵活也最容易因为中间某个节点变化而失效。优先级上我的经验是id优先其次CSS选择器最后才用XPath。尤其在大型系统中前端同事很可能频繁调整DOM结构若全部依赖XPath一次重构可能让几十条用例同时挂掉。还有一种情况值得推荐开发团队如果能约定>element.Click(); element.SendKeys(admin); element.Clear(); element.Submit();Click()会模拟鼠标左键点击这对普通按钮没问题但有几个隐藏细节。第一按钮上如果有遮罩层或悬浮元素点击会被拦截Driver会抛出“element click intercepted”异常这时需要先用JS把遮挡层隐藏或用MoveToElement方式点击。第二checkbox和radio的切换我一律先用IsSelected()判断当前状态再决定是否点击避免重复点击造成状态翻转。第三下拉框用click展开后选项通常不是option元素而是渲染后的div或li节点需要先展开再定位后再点击。SendKeys在输入场景里要注意焦点问题。程序执行太快时页面刚渲染出的输入框还没有绑定完整的事件监听器直接SendKeys会导致部分字符丢失特别是中文输入时更明显。稳妥做法是先点击一次输入框确认它能获得焦点并且光标可见再发送内容。和所有自动化测试一样等待是绕不开的课题。我见过太多人一上来就Sleep(3000)这种固定等待在本地网络好时能跑换到CI环境网络稍慢就疯狂超时。正确方案是用显式等待// 等待某个元素出现并且可见 WebElement status driver.FindElement(By::Id(login-status)); if (driver.Wait(10, [] { return status.IsDisplayed(); })) { // 继续后续操作 }这种等待实现了“主动轮询超时控制”页面慢就等它跑完页面快就立刻继续效率比sleep高很多而且逻辑更明确。关于等待策略后面的场景化实战还有更细的展开因为动态数据加载和登录跳转是等待问题的高发区。3. 场景化应用实战登录校验、动态页面与文件处理3.1 登录场景Token、Cookie与Header的配合登录是Web自动化测试里最常见的入口场景看起来就是填用户名、填密码、点登录但真正复杂的是登录前的Token校验和登录后的会话维持。先说Token问题。不少系统页面里埋了一个隐藏字段csrf_token提交时必须带上这个值否则服务端拒绝请求。通过WebDriver操作时我用两步走先FindElement拿到token字段的value属性再调用SendKeys把它填回表单对应位置或者更直接一点用driver.ExecuteScript(return document.querySelector(input[namecsrf_token]).value)把token取出来再作为POST参数构造请求。这步的坑在于token通常是随页面生成的每次刷新都不一样所以千万不能写死必须在会话里实时读取。登录完成后的会话维持也是重点工作。如果系统用Cookie做认证WebDriver提供了AddCookie和GetCookie函数。我会在第一次登录成功后手动把整个Cookie列表存到本地文件后续测试直接用这些Cookie启动跳过登录步骤节省大量执行时间。具体写成代码就是// 登录成功后保存cookie auto cookies driver.GetCookies(); SaveCookiesToFile(./cookies.json, cookies); // 下次启动时直接恢复会话 LoadCookiesFromFile(./cookies.json); for (const auto c : cookies) { driver.AddCookie(c); } driver.Refresh();这个技巧在跑几十条用例时特别有用因为登录接口往往有频率限制每一条用例都重新登录测试还没跑完就被服务端限流了。恢复Cookie之后用例直接进入实际操作环节速度和安全都兼顾了。不过要注意Cookie可能包含httpOnly标志某些驱动版本下读取这种Cookie会有兼容问题遇到时果断手动把HttpOnly字段抹掉再保存。3.2 页面加载异常时的等待策略Service Worker与WebGL报错我见过不少测试脚本启动后浏览器控制台报了一串错误就被误判失败其中两个高频报错是“加载web视图时出错: error: could not register service worker: invalidstatee”和“three.webglrenderer: a webgl context could not be created”。搜索热度那么高说明大家都被这两个问题折腾过。先说Service Worker。页面注册Service Worker失败很多时候不是代码问题而是浏览器环境不允许比如无头模式下的本地存储限制、隐私模式、或服务端不支持HTTPS。自动化测试关注的是业务功能能否正常走通Service Worker通常只服务于缓存和离线能力对页面主流程影响基本为零。所以我的原则是不要因为控制台出现这类错误就让用例失败正确方式是通过页面关键元素是否出现来判断加载结果。WebGL的报错则常见于无头模式或虚拟机环境。Chrome无头模式默认不启用GPU但某些3D页面库比如three.js启动时会强制检测WebGL上下文检测失败就抛异常并停止渲染。解决办法有两种一是启动参数加--use-glswiftshader强制走软件渲染让无头环境也能模拟出一个WebGL上下文二是如果被测功能不依赖3D渲染就直接忽略这个控制台错误把断言焦点放在页面结构的完整性上。这种场景的等待策略也很有讲究。页面加载不应该只看“主文档加载完成”还要等“关键数据渲染完成”。我的做法是自定义一个“等待渲染完毕”函数同时检查三个条件网络请求是否进入空闲、目标元素是否可见、加载动画是否消失。三个条件轮询直到超时。这种等待比固定sleep的稳定性高很多尤其在网络波动的测试环境里。另外还遇到过一类CLI Web服务启动命令后会自动在默认浏览器里打开页面命令行会提示类似“opening the default browser; pass --no-open to disable”。这种默认行为在本地开发时挺方便但在自动化测试时很致命因为无人值守环境里没有默认浏览器或者会弹出一个多余的窗口干扰测试。我的经验是所有测试要用的Web服务启动命令里一律显式关掉自动打开浏览器例如dsh web --no-open之类确保测试环境完全可控不会因为一个弹窗导致整个任务卡在等待确认上。3.3 动态表格数据提取与断言很多业务系统都有复杂的表格页面数据通过AJAX动态加载而不是写死在HTML里。对这种页面做数据提取是C自动化测试的高频需求之一。我的做法是先等数据行出现再批量提取。伪代码核心逻辑如下driver.Wait(10, [] { return driver.FindElements(By::CssSelector(table#list tr)).size() 0; }); auto rows driver.FindElements(By::CssSelector(table#list tr)); std::vectorRecord records; for (auto row : rows) { Record rec; auto cells row.FindElements(By::CssSelector(td)); if (cells.size() 4) { rec.name cells[0].GetText(); rec.id cells[1].GetText(); rec.status cells[2].GetText(); // ... } records.push_back(rec); }注意这段代码里有个不容易察觉的问题rows是快照但cells是遍历过程中再次定位出来的。如果表格太大页面在渲染过程中有分批加载那么第一次拿到的rows可能只有前几行后续行还没出现。这种情况就得改成“继续点击下一页”的循环每次重新获取数据行直到最后一页。判断是否到达最后一页的通用方式是检查下一页按钮是否被禁用禁用状态通常表现为disabled属性存在。提取完数据后断言就简单了。把提取结果和预期的数据集对比字段级核对比人工肉眼检查快得多。我通常会把提取函数封装成一个公共工具模块所有用例共用这样表格结构变动时只需要改一处不用每个用例都跟着改。3.4 文件上传下载的实操细节文件上传是Web自动化里另一个容易翻车的地方。普通input[typefile]最稳妥的方式不是拖拽而是直接调用SendKeys把本地文件绝对路径送到输入框WebElement uploadInput driver.FindElement(By::CssSelector(input[typefile])); uploadInput.SendKeys(C:\\testdata\\report.xlsx);这在Windows和Linux上都能跑通注意路径分隔符在Windows下是双反斜杠。文件上传后会有一个上传进度动画必须等进度条消失再断言上传结果不能秒点秒验。进度动画通常是一个div等它变成display:none或直接从DOM里移除就行。下载方面的坑则集中在Chrome的下载策略上。新版Chrome默认会把下载文件存到/downloads目录并可能弹出一个“保留文件”的安全确认条。自动化测试里要确认文件真实落地我会在Capabilities里设置预下载目录caps.Set(goog:chromeOptions, {\prefs\:{\download.default_directory\:\C:\\\\tmp\\\\downloads\,\download.prompt_for_download\:false}});设置后再配合轮询检查目录下是否有新文件生成。这里有个经验不要一触发下载就立刻检查文件文件写入需要时间而且部分系统下载完成后会临时改个.crdownload后缀等到这个后缀消失才说明下载完成了。写成等这个中间文件消失能极大降低误判率。4. 测试框架集成从单条用例到CI报告4.1 用gtest组织用例并管理Driver生命周期讲完业务操作自动化测试最后还是要落到工程化。单条脚本到处跑不是工程可重复、可统计、可集成才是。我推荐用Google Testgtest做底层框架它是C领域最普及的测试框架断言方式和参数化能力都很成熟。用gtest组织Web自动化用例核心是管理好Driver的生命周期。每个用例都要一个干净的浏览器会话否则上一个用例的登录态和Cookie会污染下一个用例。我一般用SetUp和TearDown维护class WebTestFixture : public ::testing::Test { protected: void SetUp() override { driver new Driver(StartChromeDriver(http://localhost:9515, Capabilities().SetHeadless(true))); } void TearDown() override { if (driver) { driver-Quit(); delete driver; driver nullptr; } } Driver* driver nullptr; }; TEST_F(WebTestFixture, LoginWorks) { driver-Navigate(https://example.com/login); // ... ASSERT_EQ(欢迎回来, driver-FindElement(By::Id(welcome)).GetText()); }这个模式的好处是每个用例独立崩溃也不影响后续用例。实际运行时如果某个用例引发了浏览器崩溃驱动进程可能还残留在系统里导致下一个用例无法连接端口。我的改进是启动驱动时固定端口并在TearDown里额外清理残留进程保证用例之间互不干扰。虽然粗暴但在Windows CI上极其有效。4.2 报告输出Allure与命令行集成的经验测试跑出来没有任何可视化报告等于白跑。gtest自带XML输出但信息量比较有限。实际项目中我用Allure做报告展示它能把错误截图、页面HTML、接口日志都塞进一份可视化报告里定位问题效率高很多。实现思路是gtest跑完后会生成一份test_results.xml直接用Allure命令行加载这份结果并生成网页报告。关键操作是两步命令# 让gtest输出JUnit兼容格式 ./run_web_tests --gtest_outputxml:test_results.xml # 用Allure命令行把xml转成最终报告 allure generate test_results.xml --output allure-report如果想让报告带上截图需要在用例代码里做一点小设计。我在TearDown里统一判断用例是否失败如果失败就把当前浏览器状态截图保存到指定目录并把图片路径写入一个自定义的JSON文件里Allure命令行读取时就能关联上。具体实现细节各家不同但思路值得参考截图是排查失败的重要现场必须在用例结束前截下来否则会话一关就再也找不回来了。4.3 CI流水线里的注意点Web自动化测试进了CI最大的考验不是用例本身而是环境稳定性。无头浏览器在容器里跑最常遇到的问题是沙箱权限不足所以启动参数里那一串--no-sandbox、--disable-dev-shm-usage并不是可有可无的装饰。/dev/shm在容器里默认只有64MB浏览器跑一些复杂页面很容易把它耗尽设置--disable-dev-shm-usage后Chrome会改用/tmp空间充足就不会莫名崩溃。并行执行是另一个提升效率的手段。编译器链接器早就实现了并行构建自动化测试同样可以不过WebDriver的并行要小心资源竞争。每一路测试都分配独立的驱动端口和独立下载目录不能共享否则文件冲突、会话覆盖会让你头疼。我的实践是Jenkins流水线里根据机器核数开4到8路并行每路测试进程指定不同端口整体回归时间能缩短到串行的五分之一。另外CI里跑Web自动化测试一定要做“失败重试”。网络抖动、偶发渲染慢、第三方接口超时都可能让个别用例失败。我会给每一条用例最多重试两次如果重试还是失败那才是真问题需要人工介入。这一点看起来简单却能让自动化测试的可靠性上一个台阶至少不会因为一次偶然抖动就导致整个发布流程被拦住。5. 常见问题与排查实录5.1 崩溃与库缺失Access Violation这类问题怎么查C Web自动化测试里最常见的崩溃错误就是access violation c0000005搜索热度一直居高不下。这个错误如果出现在测试进程里通常跟WebDriver客户端的生命周期管理有关典型的比如驱动会话已经关闭但代码里还保留着旧的Driver对象一旦调用成员函数内部C API就会访问已经无效的内存地址。解决思路分两步。第一步排查崩溃时的调用栈看看是不是在driver.Quit()之后还调用了FindElement或GetTitle等操作。这种低级错误只要在代码Review时关注Driver对象的作用域就能避免。第二步排查底层的Microsoft Visual C运行库问题。WebDriver客户端库编译时可能依赖特定版本的vcruntime和msvcp如果目标机器缺了对应的visual c redistributable加载DLL时会直接报错。我习惯在构建机明确定义运行库版本并且把运行库一起打包到测试环境避免“本地能跑、CI就崩”的窘境。如果你遇到的是崩溃位置随机、没有固定复现路径的问题那还得检查线程安全。很多C WebDriver客户端库并不是线程安全的多个线程同时操作同一个Driver实例比操作未初始化指针更危险。我的经验是一个Driver实例只归一个线程所有跨线程传递必须加锁或者重新创建会话这是避免c0000005类崩溃的最有效手段。5.2 驱动版本与浏览器版本不匹配WebDriver的版本兼容规则说严也严说松也松。ChromeDriver和Chrome浏览器之间不是“大版本一致就行”的关系而是必须精确匹配到发布版本线否则启动时大概率报错。实践中我遇到过最典型的错误是“session not created”或者“This version of ChromeDriver only supports Chrome version xx”。根因基本都一样Chrome浏览器在后台自动升级到了新版本但测试环境里的ChromeDriver还是旧版。这种问题一旦出现测试成片失败恢复方法就是重新下载和当前Chrome版本匹配的ChromeDriver。Chrome主版本最低支持的ChromeDriver版本常见报错现象最新版本对应最新稳定版ChromeDriver版本差异过大时直接报session not created落后一个版本上一个稳定版ChromeDriver可能部分新特性不识别自动升级后旧版驱动大面积连接失败为了防止浏览器偷偷升级导致测试崩掉我在测试环境的服务器上关闭了Chrome的自动更新服务并把ChromeDriver版本号写进配置文件升级浏览器时同步升级驱动两条命令一起执行绝不单独动一个。5.3 元素找不到与超时的定位方法5.3 元素找不到与超时的定位方法元素找不到是新手问得最多的问题也是老手在实际项目里翻车最多的点。NoSuchElementException和超时并不是玄学绝大多数情况能分析出明确原因。第一个排查方向是“元素到底在不在页面上”。不要只看肉眼而是先用Driver自己查一下// 打印当前页面完整HTML到文件 std::string html driver.GetPageSource(); std::ofstream out(./page_source.html); out html;拿到页面源码后搜索目标元素的选择器、text、id等关键词确认它在不在。如果在那就是定位策略的问题如果不在可能是页面还没加载到那个层级也可能是整个页面跳转到了意外地址。第二个排查方向是“元素在不在iframe里”。很多Web系统把业务模块嵌在iframe中如果Driver没有切换到对应iframe任何定位都找不到driver.SwitchToFrame(driver.FindElement(By::Id(main-frame)));iframe操作完要记得切回默认内容区不然下一个用例就会在错误的Frame上下文里找元素同样报错。习惯做法是每个操作前自己确认一下当前Frame状态千万不要依赖上一个用例留下的环境。第三个排查方向是等待条件设置不合理。等待超时设置太短可能页面刚刚开始渲染目标元素还没出现设置太长用例执行时间又难以接受。我的建议是区分不同类型元素的等待时间登录按钮、导航栏这类关键节点给10秒表格里动态数据行给15秒第三方地图或者报表类组件甚至可以给到30秒。用配置文件管理这些阈值比写在代码里硬编码更灵活。最后分享一个“现场还原”的技巧。当定位失败发生时除了截图最好同时把当前页面的地址、窗口尺寸、驱动日志一并保存。我在TearDown里做失败收集生成一个包含上述内容的压缩包这样排查问题时不需要再远程连到测试机直接打开压缩包里的截图和DOM快照就能分析。这个做法省了团队大量沟通时间。如果非得让我总结一条最值得记住的经验我觉得是C做Web自动化工作重心不在写代码而在理解浏览器和驱动之间的每一次对话。定位不到元素时先问“这个元素现在真的存在吗”再问“我的Driver看到的页面和我用肉眼看的是不是同一个状态”。一旦习惯用协议视角去思考很多诡异问题都能迅速定位到根因。工具链方面初期花点时间把驱动管理、Cookie恢复、截图收集这些基础设施做好后面写业务用例就会非常顺畅希望这篇文章能帮你少走一些我当年走过的弯路。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

STM32 SBUS解码实战:DMA循环接收+IDLE中断+状态机全解析 2026/9/26 14:35:51

STM32 SBUS解码实战:DMA循环接收+IDLE中断+状态机全解析

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

阅读更多 →
欠拟合、拟合与过拟合:机器学习模型诊断实战指南 2026/9/26 14:35:51

欠拟合、拟合与过拟合:机器学习模型诊断实战指南

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

阅读更多 →
AI监管真相:为何不存在‘禁止开发超智能’的法案 2026/9/26 14:35:51

AI监管真相:为何不存在‘禁止开发超智能’的法案

我不能基于该标题生成博文。原因如下:该标题涉及虚构或未经核实的立法提案(“Sanders 与 Casar 提出法案禁止开发人工超智能”),经核查,截至2024年,美国参议员Bernie Sanders与众议员Greg Casar并未联合提出…

阅读更多 →
电梯智慧监管小程序实战:扫码巡检、维保工单与部署避坑 2026/9/26 14:35:45

电梯智慧监管小程序实战:扫码巡检、维保工单与部署避坑

简介:基于微信小程序打造的电梯智慧监管系统完整源码工程,适合有Java后端和小程序开发基础的读者用于毕业设计、课程设计或实际项目参考。系统覆盖管理后台、接口服务与微信小程序端,可对电梯维保、检验、检测、巡检等监管业务进行统一管理。…

阅读更多 →
嵌入式开发一本通:学习路线、工具链、协议、优化与面试 2026/9/26 14:35:45

嵌入式开发一本通:学习路线、工具链、协议、优化与面试

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

阅读更多 →
龙虾OpenClaw系列:从嵌入式裸机到芯片级系统深度实战60课——电源管理单元低功耗模式与唤醒策略的配置骨架与验证 2026/9/26 14:35:45

龙虾OpenClaw系列:从嵌入式裸机到芯片级系统深度实战60课——电源管理单元低功耗模式与唤醒策略的配置骨架与验证

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

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉