news 2026/9/6 6:06:01

告别Selenium:8款替代工具助你轻松搞定浏览器自动化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
告别Selenium:8款替代工具助你轻松搞定浏览器自动化

先讲个上周刚发生的事。有朋友做电商代运营,每天早上第一件事就是把竞品价格爬回来自动比价,用的就是Selenium。他跟我吐槽说,本来以为Selenium自动化脚本写一次就一劳永逸了,结果浏览器一升级、驱动一换版本,脚本就集体罢工,光排查环境问题就耗掉半天。他问我:网上天天吹的替代工具,到底哪款能让我少加两天班?

这问题我太熟了。做了这么多年自动化采集和测试,Selenium确实是经典,但它的痛点也足够经典:配置麻烦、启动慢、代码啰嗦,还有那个一升级就头疼的WebDriver版本匹配问题。更别提现在的网站上各种反爬校验和滑块验证,Selenium那套浏览器特征实在太明显,脚本经常搞不定。所以我后来在大部分场景里都换掉了Selenium,有些替代工具省事程度真的超出预期。

这篇文章就把我用过、踩过坑、认可有效的8款Selenium替代工具一次性拆完。不吹不黑,结合真实场景讲清楚每款适合干什么、代码怎么写、坑在哪儿,最后再给一张对比表和一套个人搭配方案,帮你直接照着选。

1. 为什么要换掉 Selenium:先看清它的问题在哪

1.1 配置成本高:驱动与浏览器版本匹配是老大难

Selenium要跑起来,必须额外下载一个与浏览器版本严格对应的WebDriver。Chrome一更新,chromedriver不跟着换,脚本直接报错说版本不匹配。这个“更新地狱”在团队协作里尤其致命:有人浏览器停在旧版,有人自动升级到新版,同一个脚本在不同机器上表现完全不一致。

更要命的是,不是只有Chrome有这个问题。Firefox要用geckodriver,Edge要用msedgedriver,Safari还要单独开启远程自动化开关。你要是负责维护一套跨浏览器用例,光是驱动列表就够写张Excel了。替代工具里,Playwright、Puppeteer这类新型框架普遍把浏览器下载和驱动管理内置了,装一个包就自带对应浏览器版本,彻底摆脱手动匹配。

1.2 运行效率低:每个操作都在完整浏览器里走一圈

Selenium的设计初衷是模拟真实用户操作,所以每个find_element、click、send_keys都要通过WebDriver协议在浏览器和脚本之间做一次往返通信。这种架构稳定,但性能开销巨大。跑一百个页面的回归用例,Selenium可能要一小时,而同样逻辑用Playwright或Puppeteer,可能十几分钟就结束了。

我做爬虫项目时对此感受更深。Selenium启动一个完整Chrome实例,内存随随便便吃掉几百兆,并发开三个实例就卡得不行。后来换成协议级控制的替代工具,配合无头模式,并发能力翻了好几倍。如果你每天要抓大量数据,这个效率差距就是实打实的成本差距。

1.3 代码冗余:简单操作被复杂API放大了

Selenium的API设计比较“教科书”,每个步骤都写得很死。想在输入框里填个值、点个按钮,你得先显式等待元素出现,再滚动到元素位置,再判断可点击,最后才操作。这一套下来,一个简单动作写上七八行代码是常态。而Playwright的auto-wait、Cypress的链式调用、DrissionPage的简洁选择器,都能把同样的事情压缩到两三行。

更不用说Selenium里那些容易踩的坑:元素被遮挡、iframe里定位不到、阴影DOM穿透不了……每一样都要自己查资料、写Workaround。说白了,Selenium把大量的底层复杂度直接暴露给了使用者,而优秀的替代工具会帮你把这些复杂度吞掉。

1.4 反爬特征明显:正则检测和滑块校验容易失败

如果你的用途是数据采集而不是纯测试,那你应该深有体会:大量网站已经开始在JavaScript里检测navigator.webdriverwindow.chrome这些浏览器指纹。Selenium驱动起来的浏览器,这些特征跟真实用户浏览器差距很大,网站很容易识别出是自动化工具在访问,轻则弹验证码,重则直接封IP封账号。

这也是为什么后来出现了DrissionPage这类走“接管真实浏览器”路线的工具,以及各种stealth插件。我自己实测下来,Selenium跑不过的滑块校验,DrissionPage配合轨迹模拟大概率能过;Playwright配合Stealth插件也有不错效果。如果你还在为验证码头秃,工具选对了能省下一大半工夫。

2. 选型逻辑:替代工具不是越新越好,场景要匹配

2.1 先区分你的任务类型:爬虫、测试还是混合型

很多人问我“哪款是Selenium的最强替代”,这是个伪命题。替代工具之间不是简单的谁比谁强,而是赛道不同。

任务可以大致分成三类。第一类是爬虫和数据采集,核心诉求是快、隐蔽、能扛并发;第二类是自动化测试,核心诉求是稳定、好断言、好调试;第三类是两者混合,比如登录然后抓数据,既要操作页面又要批量取数。你得先想明白自己主要干哪类活,再去挑工具,否则很容易选错方向。

比如你只是写个脚本每天定时抓几个静态页面的价格,那根本没必要上浏览器自动化,Requests加BeautifulSoup就够了,速度快十倍还不容易被封。反过来,如果你要做的是电商下单流程的UI回归测试,那Requests这种方案完全使不上劲,得靠Playwright或Cypress这类测试框架。

2.2 再看你的技术栈:Python、Node.js还是Java

语言生态也是硬约束。Python是自动化爬虫的大本营,DrissionPage、Scrapy、Playwright的Python binding都是成熟方案;JavaScript/TypeScript环境下,Puppeteer和Cypress是主流;Java后端项目里,虽然Playwright也支持,但HtmlUnit这种免驱动轻量方案有时候更省心。

还有一点容易被忽略:团队里其他人的维护能力。我见过不少项目用Puppeteer写得飞起,但整个团队没人熟悉Node,后续维护全靠作者一个人。选工具时要把团队的平均水平和后续接手成本都算进去,不然省了技术债,欠了人情债。

2.3 动态页面占比决定要不要“真浏览器”

选工具的另一个关键判断点是目标页面到底有多少内容是JavaScript动态渲染的。

如果页面数据主要是服务端渲染,打开就有,那用Requests或Scrapy直接拿HTML解析最划算,速度和稳定性都碾压任何浏览器方案。如果页面大量依赖Ajax请求动态加载,那可以用两层方案:先用Requests分析接口,直接调接口拿JSON,效率最高;接口加密破解不了时,再上无头浏览器做兜底。

这个判断多做几次之后,你会发现真正需要完整浏览器自动化的场景其实没有想象中那么多。多数情况下,接口直连加少量渲染兜底就能覆盖九成需求。替代Selenium,不只是换工具,更是换思路。

3. 8款省事实用的替代工具逐款拆解

3.1 Playwright:自动等待+免驱动,最省心的全能型选手

Playwright是微软开源的新一代自动化测试框架,支持Chromium、Firefox、WebKit三款浏览器引擎,Python、JavaScript、Java、.NET四种语言都有官方binding。它最大特点是“免驱动”和“自动等待”。安装时自带浏览器,不用额外下载driver;写代码时不用显式写sleep和WebDriverWait,元素不出现就自动重试等待,稳定性和代码简洁度都比Selenium提升一大截。

我用Python版给大家演示一段最简单的搜索操作:

from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(headless=False) page = browser.new_page() page.goto("https://example.com") page.fill("#kw", "python") # 自动等待输入框可操作 page.click("#su") # 自动等待按钮可点击 page.wait_for_timeout(2000) # 简单停留观察结果 print(page.title()) browser.close()

这里没有一行等待代码,没有driver路径配置,都是框架自动处理的。Playwright还自带playwright codegen命令,你打开一个页面手动点几下,它就能自动录制成脚本,做原型验证非常爽。

需要注意:Playwright的文件下载处理也比较顺手。以前用Selenium下载文件要配preferences、判断文件是否下载完成,Playwright可以用page.expect_download()上下文管理器等待下载事件,逻辑清晰很多。还有网络拦截功能,可以直接中止图片和CSS请求,减少无意义的流量消耗,实测大型页面加载能快30%以上。

3.2 DrissionPage:国产开源工具,把反爬和滑块难题降维处理

DrissionPage是我近两年最喜欢推荐给爬虫玩家的工具,作者是国内的开发者。它的核心思路是用一个库同时管理浏览器控制和数据请求:既能像Requests一样直接发HTTP请求,也能像Selenium一样操作浏览器页面,而且两边数据还能无缝互传。

最吸引人的是它对反爬的处理。Selenium的浏览器会被检测出webdriver特征,而DrissionPage可以接管你自己启动的Chrome浏览器,本质上就是一个真实用户在操作真浏览器,指纹特征跟普通用户没有区别。应对滑块验证码时,配合轨迹模拟函数,成功率比我用Selenium加stealth插件高得多。

举个例子,这是DrissionPage实现搜索操作的代码:

from DrissionPage import ChromiumPage page = ChromiumPage() page.get("https://example.com") page.ele("#kw").input("python") page.ele("#su").click()

是不是感觉特别像Requests的简洁风格?它对中文网站的特性适配很好,很多抓取任务都能直接定位元素搞定,不需要绕来绕去找XPath。DrissionPage还有个专门做数据采集的SessionPage模式,针对无需渲染的接口请求比requests库还顺手。

我自己在帮客户处理电商详情页抓取时,大量用了DrissionPage。那些带滑块、带行为验证的站点,Selenium几乎全军覆没,DrissionPage配合合理操作频率能稳定跑一整天。如果你做爬虫经常被验证码卡脖子,这个工具值得第一个试。

3.3 Puppeteer:Node生态里的最强无头浏览器库

Puppeteer是Chrome官方DevTools团队维护的Node.js库,主要控制Chromium或Chrome。它的最大优势是背靠Chrome团队,API设计紧跟浏览器能力,性能和兼容性都不用担心。相比Selenium,Puppeteer的安装过程会主动下载指定版本的Chromium,不需要再手动管理driver。

Node.js环境下,Puppeteer代码写起来也很直观:

const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch({ headless: false }); const page = await browser.newPage(); await page.goto('https://example.com'); await page.type('#kw', 'python'); await page.click('#su'); await new Promise(r => setTimeout(r, 2000)); console.log(await page.title()); await browser.close(); })();

Puppeteer的截图和PDF生成能力是全行业公认的强。做定时任务每天晚上自动给数据报表截图、生成PDF发给老板,用Puppeteer几十行代码就能稳定跑。它也很适合做SPA页面的预渲染和SEO优化。

但需要注意,Puppeteer只支持Chromium系浏览器,跨浏览器测试场景就力不从心了。另外它默认是无头模式,如果目标网站对无头浏览器有检测策略,要记得开headless: false或使用puppeteer-extra-plugin-stealth插件隐藏特征。我的经验是:纯Node团队、主要跑Chrome场景,选Puppeteer非常顺手;需要跨浏览器测试就上Playwright。

3.4 Cypress:前端测试的体验派标杆,测试断言写得像聊天

如果你做的是前端项目的E2E测试,不是爬虫,那Cypress可能是最提升幸福感的选择。它不像Selenium那样通过WebDriver远程控制浏览器,而是直接跑在浏览器内部,所以执行速度极快,又有时间旅行调试能力——每跑一步你可以回放看当时页面的状态。

Cypress的测试代码写法很自然,自带断言和等待机制,没有Selenium那种“等待+查找+操作”的割裂感:

describe('登录功能测试', () => { it('输入正确账号密码可以跳转首页', () => { cy.visit('/login') cy.get('#username').type('admin') cy.get('#password').type('123456') cy.get('button[type="submit"]').click() cy.url().should('include', '/dashboard') cy.contains('欢迎回来').should('be.visible') }) })

Cypress还自带Test Runner可视化界面,用例跑起来每一步都有实时视频和DOM快照,定位问题效率极高。不用像Selenium那样另外搭报告框架,内置的Mocha风格报告足够日常使用。

它的局限也很明显:主要支持Chromium系和Firefox,对多标签页、跨域操作支持不好,也不能用两个浏览器同时操作来测实时通信场景。可以说,Cypress是“测试专用工具”,适合纯前端团队用来做业务回归,不适合数据采集类任务。

3.5 Scrapy:纯爬虫场景的工业级持久方案

如果在你的实际工作里,需要每天都抓大量不同网站的同类数据,那Scrapy才是比Selenium聪明得多的方案。它不是浏览器自动化工具,而是一个完整的爬虫框架——自带异步调度、并发下载、数据管道去重、中间件扩展、日志统计,几乎所有爬虫工程化的问题都帮你考虑过了。

Scrapy抓一个带翻页的列表站点,核心代码不过如此:

import scrapy class QuotesSpider(scrapy.Spider): name = "quotes" start_urls = ["https://quotes.toscrape.com/"] def parse(self, response): for quote in response.css("div.quote"): yield { "text": quote.css("span.text::text").get(), "author": quote.css("small.author::text").get(), } next_page = response.css("li.next a::attr(href)").get() if next_page: yield response.follow(next_page, self.parse)

这个爬虫天生支持并发请求,默认配置下每秒抓十几个页面毫无压力,这是Selenium永远追不上的。很多看似需要自动化浏览器的任务,其实页面数据就在那个接口里,只是你还没找到规律。先用开发者工具分析网络请求,找到数据接口,再用Scrapy请求接口拿JSON,比开浏览器省力一百倍。

如果页面确实需要JS渲染,Scrapy也能通过搭配scrapy-playwright中间件或Splash渲染服务来解决,做到“静态用Scrapy,动态才渲染”的组合策略。我的建议是:所有长期运行的采集项目,首选Scrapy做地基,浏览器自动化只做兜底环节。

3.6 BeautifulSoup + Requests:最轻量的“伪替代”,静态页面一把梭

要说“更省事”,没有比Requests加BeautifulSoup更省事的组合了。一个负责发请求,一个负责解析HTML,代码量最小,部署最方便,也几乎没有被反爬检测的风险,因为你的请求看起来就是一个普通的HTTP访问。

最简单的使用方式:

import requests from bs4 import BeautifulSoup r = requests.get("https://example.com") soup = BeautifulSoup(r.text, "html.parser") for item in soup.select(".title"): print(item.get_text())

这个方案只适合页面数据直接写在HTML里的场景。但现实中很多网站的数据是接口动态返回的,这时候你可以退一步:用开发者工具看到接口返回的JSON,直接用Requests调接口拿数据,解析都省了。

我见过太多朋友一上来就开Selenium去抓数据,其实那个页面根本不需要执行JavaScript。动手写代码之前先花十分钟分析页面结构,能用Requests解决的坚决不上浏览器,这个习惯能帮你省下大量时间和带宽。轻量方案看着不酷,但最多人靠它干活。

3.7 TestCafe:跨浏览器测试不用单独下载驱动

TestCafe是DevExpress出品的Node.js端到端测试框架,相比Selenium最大的优势是免驱动,而且免浏览器的远程设置。你只要装了Node.js,写个脚本就能直接跑在Chrome、Firefox、Edge甚至Safari的远程实例上,配置成本几乎为零。

示例代码和Cypress风格接近,但TestCafe更偏向“面向浏览器自动化”的通用能力,对多标签页、文件下载、屏幕截图的支持都比Cypress更灵活:

import { Selector } from 'testcafe'; fixture('登录测试').page('https://example.com/login'); test('输入正确账号密码可以登录', async t => { await t .typeText('#username', 'admin') .typeText('#password', '123456') .click('button[type=submit]') .expect(Selector('body').innerText).contains('欢迎回来'); });

它内置了等待机制和智能选择器,不用写timeout参数,还有自动并发跑用例的能力。适用于需要同时覆盖多浏览器的测试团队,但如果你只是做爬虫,它不太合适。

3.8 HtmlUnit:Java后端里的轻量无头浏览器选择

HtmlUnit是Java生态里一个老牌的无头浏览器实现,支持JavaScript执行、表单提交、Cookie管理,而且不需要启动额外浏览器进程,速度比Selenium快得多。如果你的项目是Java后端,又不想在服务器上装一堆浏览器和驱动,HtmlUnit是个值得留意的选择。

一个简单的Java例子:

import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlPage; public class Example { public static void main(String[] args) throws Exception { try (WebClient webClient = new WebClient()) { webClient.getOptions().setJavaScriptEnabled(true); webClient.getOptions().setCssEnabled(false); HtmlPage page = webClient.getPage("https://example.com"); System.out.println(page.getTitleText()); } } }

需要说明的是,HtmlUnit的JavaScript引擎和真实浏览器有差距,复杂的现代前端框架页面它不一定能渲染完整,遇到这类场景还是得请出Playwright或者真实浏览器。但在Java服务里做轻量数据解析、定时巡检,它足够便宜高效。

4. 一张对比表:快速找到适合你的那一款

工具选型最怕选择困难,我做了一张速查表,从语言生态、驱动要求、适用场景等维度把8款工具放在一起对比。没有最好的工具,只有最匹配你当前任务的工具。

工具语言生态免驱动执行JS典型场景反爬友好度上手难度
PlaywrightPython/JS/Java/.NET是,安装自带浏览器完整E2E测试、复杂爬虫、多浏览器
DrissionPagePython是,接管真实浏览器通过真实浏览器执行国内站点、滑块验证、文件下载
PuppeteerNode.js是,安装自带Chromium完整截图、PDF、SPA抓取、测试
CypressJS/TS是,驱动内置完整前端E2E测试、回归测试不适用
ScrapyPython无浏览器不支持,可扩展大规模静态数据采集
BeautifulSoup+RequestsPython无浏览器不支持轻量静态抓取、接口调试极低
TestCafeJS/TS是,免驱动完整跨浏览器E2E测试不适用
HtmlUnitJava是,内置引擎部分支持Java后端轻量解析

如果你是非Java的爬虫玩家,这表格里你只需要重点关注前两行和第五六行。Playwright适合结构化测试和重交互抓取,DrissionPage适合跟反爬斗智斗勇的场景,Scrapy加Requests组合适合长期大规模采集。

如果你是前端测试工程师,Cypress和TestCafe选一个就行,团队在意调试体验就选Cypress,需要更宽浏览器矩阵就选TestCafe。

5. 常见问题与排查心得:替代过程中最容易踩的坑

5.1 页面一直加载不出来或者执行超时怎么办

很多人在从Selenium切换到Playwright后遇到的第一个问题,是新框架的等待策略不够符合预期。Selenium默认是找不到元素就立刻报错,而Playwright默认会等满超时时间,所以某些场景下反而会觉得“卡住了”。

建议做法:全局设置超时时间,同时手动关闭页面里不必要的阻塞资源。

browser = p.chromium.launch() context = browser.new_context() context.route("**/*.{png,jpg,jpeg,css}", lambda route: route.abort()) page = context.new_page() page.set_default_timeout(10000) # 10秒超时 page.goto("https://example.com", wait_until="domcontentloaded")

wait_until="domcontentloaded"能减少等资源加载的时间。如果页面数据是Ajax延迟加载的,建议用page.wait_for_selector()等待具体的业务元素出现,而不是无脑用固定sleep。

5.2 点击按钮下载图片或文件时,脚本没反应或文件保存不下来

这种情况我遇到过很多次,根因通常是:点击下载按钮后,文件下载是走浏览器下载机制的,而不是正常的页面跳转。Selenium对下载预处理的配置很繁琐,而Playwright可以直接监听下载事件,DrissionPage也有专门的下载管理器。

DrissionPage的处理逻辑就简单很多,点击下载后直接用库的下载等待API获取文件,不需要自己去猜下载路径。如果目标网站的下载按钮实际上是发送一个GET或POST请求,那更推荐的做法是用抓包先拿到真实下载链接,直接用Requests来拉文件,并发和稳定性都会好很多。

5.3 滑块验证或行为验证过不去,加了延时也没用

滑块过不去的核心问题有两个:一是浏览器自动化特征太明显,二是滑动轨迹不像真人。Selenium驱动的浏览器很容易被检测出webdriver特征,所以先换用能接管真实浏览器的DrissionPage,或者给Playwright加stealth插件。

第二步是轨迹模拟。真人滑动是先快后慢、中间有微小停顿和抖动,不是匀速直线。你可以自己在代码里模拟一下这段轨迹:

import random import time def human_like_track(distance): track = [] current = 0 while current < distance: step = random.randint(3, 12) current += step track.append(current) time.sleep(0.01) # 最后再调整一两步到目标位置 track.append(distance) return track

关键是不追求完美,而是追求“不像机器人”。当然,验证码方案本身也在进化,反爬技术永无止境,这里只是基础思路。如果目标网站验证强度特别高,我建议直接考虑接口逆向或第三方打码服务。

5.4 Cookie登录态怎么复用,才能避免每次跑脚本都要重新登录

很多系统要求登录态,每次都重新登录不仅慢,还可能触发风控。替代工具普遍提供了上下文存储机制,可以把登录态保存下来,下次直接加载。

Playwright的写法大概是:

context = browser.new_context() page = context.new_page() page.goto("https://example.com/login") # 手动登录一次 context.storage_state(path="state.json") # 下次脚本里直接加载登录态 context = browser.new_context(storage_state="state.json")

DrissionPage更直接,它接管的是真实浏览器,登录态天然保留在浏览器Profile里,你只要指定用户目录启动,cookie、localStorage全都还在,跨脚本复用登录态非常自然。

5.5 并发跑多个任务,开太多浏览器把内存撑爆了

浏览器自动化不是无节制并发的东西,一个Chromium实例空闲时也要占用两三百兆内存。我的经验是单个浏览器实例控制在3到5个页面以内,再多就考虑用线程或进程池横向扩展机器,或者优化逻辑优先用接口方案而不是开浏览器。Playwright支持同一个Context下开多个Page,任务之间可以复用一个浏览器进程,能省不少资源。

6. 我的实际搭配方案:不同任务怎么组合用

替代Selenium不是“换一把锤子砸所有钉子”,而是一套组合拳。我现在做项目时的固定搭配是这样的:长期采集任务用Scrapy打底,处理静态页面和接口数据;遇到必须走浏览器交互、又怕反爬拦截的场景,上DrissionPage接管真实浏览器;如果是做测试框架建设或者需要跨浏览器验证功能,选Playwright;如果只是临时爬个静态页面,Requests加BeautifulSoup,五分钟后出结果。

给正准备从Selenium迁移的朋友一个建议:不要一次性把全部脚本重写。先把任务按类型归类,优先迁移那些“最容易崩溃”和“维护成本最高”的脚本,用新工具跑通之后再逐步扩大范围。这样既能快速看到效果,也能控制风险。

最后分享一个让我感触很深的小细节。以前我用Selenium写爬虫脚本,每天最怕看到的就是清晨的告警邮件;现在换了工具组合,告警邮件几乎绝迹了。技术选型这件事,最值得投入时间的不是学更多API,而是想清楚每个任务到底需要多重的工具。工具省事,工作才会省心。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 6:04:23

基于单片机控制的无线烟雾检测报警系统论文

文章目录摘要设计内容资源获取摘要 家庭火灾是一种常见的安全隐患&#xff0c;其危险性随着现代生活方式和家庭用电设备的增加而不断增加。为了提高火灾的及时性识别和处理&#xff0c;采取措施来预防火灾的发生变得尤为重要。在这些预防措施中&#xff0c;安装火灾报警器是一…

作者头像 李华
网站建设 2026/9/6 6:04:13

通达信筹码集中度指标:COST公式与实战详解

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

作者头像 李华
网站建设 2026/9/6 5:57:57

现代人为什么不喜欢八卦?

八卦的定义&#xff1a;嚼舌根&#xff08;低效行为&#xff09;&#xff1a; 带着恶意揣测&#xff0c;传播未经证实的谣言&#xff0c;或者过度打探他人的私生活。这种行为不仅不能带来权力&#xff0c;反而会消耗人脉&#xff0c;破坏个人的道德和能力形象。职场八卦&#x…

作者头像 李华
网站建设 2026/9/6 5:56:12

奔驰开源ARDEP:嵌入式车载开发新范式的硬核拆解

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

作者头像 李华
网站建设 2026/9/6 5:53:57

安卓手机如何实现类iOS体验:从灵动岛到控制中心的交互迁移指南

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

作者头像 李华
网站建设 2026/9/6 5:53:05

传统老板转型电商:他以为最难的是学电脑,结果是验证码

传统老板转型电商&#xff1a;他以为最难的是学电脑&#xff0c;结果是验证码 一位做建材二十年的老板&#xff0c;转型电商后的第一次深夜来电&#xff1a; 「我以为最难的是学电脑&#xff0c;用了俩月倒也熟练了。真正的噩梦是验证码——它不按常理出牌啊&#xff01;我生意…

作者头像 李华