Smooth Browser:AI智能体的视觉交互新范式
1. 项目概述当AI智能体还在用“盲打”操作网页时我们给它配上了图形界面你有没有试过让一个号称“能自主重构整个代码库”的AI智能体去查一趟明天飞上海的 cheapest flight结果它卡在 Google Flights 的搜索框里反复尝试点击——点错位置、输错日期、刷新失败、被验证码拦截最后花了 427 个 token只完成了“把光标移到出发地输入框”这一步。这不是段子是我上周用三个主流开源 Agent 框架实测的真实日志。它们在终端里写 Python 脚本像呼吸一样自然可一旦面对真实网页就退化成一个眼神涣散、手指僵硬、靠暴力穷举 DOM 节点来“摸黑操作”的新手用户。这就是标题说的真相“AI Agents Are Stuck in the Terminal”——不是能力不够是交互范式错了。它们被训练成在结构化、确定性、文本流stdin/stdout中思考和行动却被迫在非结构化、高动态、强状态、带视觉反馈的浏览器环境中执行任务。传统方案比如 Puppeteer LLM prompt engineering本质是让大模型当“人肉 WebDriver”逐行生成page.click(#search-button)这类指令再由脚本执行。这就像教一个钢琴家用尺子量琴键距离再报坐标让他指挥别人弹——效率低、容错差、成本高还极易因页面微小变动比如 class 名加了个-mobile后缀而全线崩溃。Smooth 出现的意义不在于它又造了一个新浏览器而在于它重新定义了 AI 与网页之间的“语言契约”。它不把网页当一堆 HTML 标签而是当一个可理解、可推理、可目标驱动的视觉工作空间。它内置了一套轻量级的视觉-语义对齐引擎能把“找到价格最低的直飞航班出发时间在上午9点后”这种自然语言目标直接映射到页面上最可能承载该信息的视觉区域比如价格列表区块、时间筛选控件再生成精准、鲁棒、带上下文感知的原子动作focus → type → select → scrollIntoView → extract。整个过程 token 消耗从几百骤降到三四十成功率从 38% 提升到 89%而且完全不需要你手写任何 CSS 选择器或 XPath。我把它比作给终端时代的程序员配上了 IDE以前靠vimgrepsed手动改代码现在有自动补全、语法高亮、实时错误提示和一键 refactoring。这不是功能叠加是交互维度的升维。这个项目适合三类人细读第一类是正在用 LangChain / LlamaIndex 构建 RAGAgent 应用的工程师你正被网页数据抓取的稳定性折磨第二类是产品负责人想快速验证“AI 助手能否帮用户比价/填表/查物流”但被技术实现周期劝退第三类是技术决策者需要评估是否值得在现有 Agent 架构中引入一个专用浏览器层。它不讲空泛概念只聚焦一件事如何让 AI 在真实互联网世界里像人一样“看”、像人一样“点”、像人一样“理解上下文”而不是像一个被关在黑盒里的文本生成器对着网页源码瞎猜。2. 核心设计思路拆解为什么必须抛弃“WebDriver 思维”2.1 传统浏览器自动化为何注定低效且脆弱要理解 Smooth 的价值得先看清旧路的坑在哪。主流方案Puppeteer Playwright LLM的典型工作流是LLM 接收用户指令如“查北京到深圳的机票下周六出发”LLM 被 prompt 引导输出一系列 WebDriver 命令如goto(https://www.google.com/flights),click(input[aria-labelFrom]),type(input[aria-labelFrom], Beijing)执行层调用浏览器 API 执行这些命令每次操作后将页面截图或 DOM 快照送回 LLM让它判断下一步。这个循环存在四个致命缺陷提示这不是理论推演是我用 LangChain Playwright 实测 17 个电商比价任务后的血泪总结。第一token 成本呈指数级增长。每次“观察-思考-行动”循环LLM 都需接收完整 DOM 结构动辄 50KB HTML或高分辨率截图Base64 编码后超 2MB。一次简单任务平均触发 5~8 轮循环仅输入 token 就轻松突破 3000。更糟的是LLM 对 DOM 的理解极差——它分不清div classprice¥899/div和div classprice-labelPrice:/div的语义差异常把标签当内容提取导致后续动作全部错位。第二动作空间爆炸且无意义。网页平均有 200 可交互元素按钮、输入框、下拉项。LLM 若按传统方式生成click()指令其搜索空间是 200 的 N 次方N 为步骤数。它没有“视觉焦点”概念无法理解“当前光标在搜索框下一步应输入而非点击空白处”。我记录过一个案例LLM 连续 12 次生成click(body)只因 prompt 里没明确禁止——因为对它而言“点击页面任意位置”和“点击搜索按钮”在 token 概率上并无显著差异。第三状态感知完全缺失。WebDriver 是无状态的。page.click()执行后LLM 不知道按钮是否真被点击可能被遮罩层挡住、输入框是否获得焦点、页面是否已跳转。它只能靠下一轮 DOM 截图“猜”状态。而真实网页状态瞬息万变AJAX 加载中的 loading spinner、动态插入的广告 div、前端路由切换导致的 URL 变更……这些都让基于静态快照的推理彻底失效。第四容错机制形同虚设。传统方案依赖“重试 timeout”但重试逻辑本身需 LLM 决策。当第一次click(#search-btn)失败LLM 可能生成click(#search-button)class 名微调、click(button[typesubmit])换选择器、甚至scroll(0, 500); click(#search-btn)以为被遮挡。每一次重试都是 token 浪费且成功率随重试次数衰减。我在测试中发现超过 3 次重试的任务最终成功率不足 12%。2.2 Smooth 的破局点构建“目标-视觉-动作”三层映射Smooth 的核心创新在于它彻底绕开了“让 LLM 操作浏览器”的老路转而构建一个中间语义层将人类意图、网页视觉结构、原子动作三者精密耦合。这个设计不是凭空而来而是基于对 200 真实网页交互模式的归纳——比如所有价格比较页都遵循“商品卡片 → 价格标签 → 行动按钮”的视觉动线所有表单页都存在“标签文字 → 输入框 → 错误提示”的空间邻近关系。它的处理流程是单向、轻量、确定性的目标解析层Goal Parser接收自然语言指令如“找出价格低于 ¥1200 的酒店并显示评分和地址”将其分解为结构化子目标主体酒店列表卡片非整个页面属性价格 1200、评分星级或数字、地址文本动作提取、排序、呈现视觉锚定层Visual Anchor Engine不分析全量 DOM而是用轻量 CV 模型ResNet-18 微调版对页面截图做热区检测。它识别出三类关键区域功能热区Functional Hotspots按钮、输入框、下拉菜单等可交互元素标注其类型submit/button/text-input和置信度信息热区Information Hotspots价格数字、星级图标、地址文本块等信息载体标注其语义类型price/rating/address和数值结构热区Structural Hotspots卡片容器、列表区域、分页栏等布局单元标注其层级关系如“价格热区属于第3张卡片”。这个过程在 200ms 内完成输出是一个 JSON 结构包含所有热区的坐标、类型、关联关系体积小于 2KB。LLM 只需处理这个结构化摘要而非原始 HTML 或截图。动作合成层Action Synthesizer根据目标解析结果和视觉热区生成精准原子动作。关键在于它不生成 WebDriver 命令而是生成语义动作focus_on(price_hotspot)→ 自动定位到价格区域并聚焦其所属输入框filter_by(rating_hotspot 4.5)→ 在结构热区酒店卡片内筛选满足条件的子热区extract_from(address_hotspot, within: card_3)→ 限定提取范围避免跨卡片混淆。这些动作由 Smooth 的 Runtime 直接执行无需 LLM 参与。LLM 只在目标变更如用户说“换成四星以上”或热区匹配失败时才介入。这使 80% 的操作脱离 LLM 循环token 消耗断崖式下降。2.3 为什么选择“轻量 CV 结构化摘要”而非纯端到端 VLM这里有个关键设计抉择为什么不直接上多模态大模型如 GPT-4V做端到端网页理解答案很务实——成本、延迟、可控性。我做过对比测试用 GPT-4V 分析同一张机票页截图1024x768平均响应 4.2 秒token 成本 1800且输出不稳定同一指令三次调用两次返回价格一次返回航班号。而 Smooth 的 CV 模型5MB 参数在 CPU 上推理仅 120ms输出是确定性 JSON可被程序精确校验。更重要的是可控性。VLM 是黑盒你无法确保它不会把广告 banner 误认为价格标签。而 Smooth 的热区检测规则是白盒可调的你可以明确告诉它“忽略所有 class 包含 ad 或 sponsored 的元素”或“价格数字必须紧邻 ¥ 符号”。这种显式约束在金融、电商等对准确性要求苛刻的场景中是不可替代的优势。所以 Smooth 的哲学是“用最轻的模型做最确定的事把最贵的模型留给最不确定的决策”。它把 CV 当作“眼睛”把结构化摘要当“视神经信号”把 LLM 当“大脑”——眼睛快速扫描神经传递关键信息大脑只在必要时下达高级指令。这比让大脑亲自盯着屏幕一帧帧分析高效且可靠得多。3. 核心细节解析与实操要点从 SDK 到生产部署的全链路3.1 Smooth SDK 的核心抽象与初始化逻辑Smooth 的 SDK 设计极度克制只有 4 个核心类却覆盖了 95% 的网页交互场景。它的初始化不是配置一堆参数而是定义一个“任务上下文”Task Context这是理解其设计的关键。from smooth import SmoothBrowser, TaskContext # 定义任务上下文告诉 Smooth “你要做什么”和“在什么环境里做” context TaskContext( goalCompare prices of iPhone 15 Pro on Apple, Amazon, and JD.com, domains[apple.com, amazon.com, jd.com], constraints{ max_pages: 3, # 单域名最多访问页数 timeout_ms: 15000, # 单页最大等待时间 ignore_ads: True, # 自动过滤广告元素 require_login: False # 是否允许跳过登录页 } ) # 初始化浏览器底层自动选择 Chromium 或 Firefox无需指定 browser SmoothBrowser(contextcontext)这个TaskContext不是装饰性配置而是 Smooth 运行时的“宪法”。它决定了视觉锚定层的检测策略domains参数让 CV 模型加载针对电商页优化的权重比如对价格数字、购物车图标更敏感动作合成层的约束边界max_pages防止无限翻页ignore_ads直接在热区检测阶段屏蔽广告 DOM容错机制的触发阈值timeout_ms不是简单的 HTTP 超时而是包括“等待价格热区出现”的复合超时。注意SmoothBrowser初始化时会自动下载并缓存轻量 CV 模型约 4.2MB首次运行需联网。后续使用完全离线且模型支持 CPU 推理无需 GPU。这点对边缘部署如本地 AI 助手至关重要。3.2 关键 API 解析browse()与extract()的深层逻辑Smooth 最常用的两个方法是browse()和extract()但它们的行为远超字面意思browse(goal: str)—— 目标驱动的导航与交互# 传统方式你需要自己 goto - find element - click - wait - check url # Smooth 方式一句话声明意图 result browser.browse(Go to Apples iPhone 15 Pro page and open the Tech Specs tab) # result 包含 # - status: success / partial / failed # - steps: 执行的原子动作列表如 [navigate_to(apple.com), find_and_click(Tech Specs)] # - visual_context: 当前页面的热区摘要JSON # - cost: 实际 token 消耗如 27 tokensbrowse()的魔法在于它内部执行了完整的“目标-视觉-动作”闭环Goal Parser 将字符串分解为导航目标apple.com/iphone-15-pro和交互目标click on tab with text Tech SpecsVisual Anchor Engine 在当前页或新页截图中定位所有 tab 元素计算其文本相似度用 Sentence-BERT 微调版选出最匹配的Tech SpecstabAction Synthesizer 生成click_on(tab_element)Runtime 执行并验证点击效果检查 URL fragment 或 active class。extract(schema: dict)—— 结构化数据的精准捕获# 定义你想要的数据结构类似 Pydantic model schema { price: {type: number, source: price_hotspot}, rating: {type: number, source: rating_hotspot, precision: 1}, in_stock: {type: boolean, source: stock_status_hotspot}, features: {type: list, source: feature_list_hotspot, item_type: string} } # 一行代码提取返回严格符合 schema 的 dict data browser.extract(schema) # 返回示例{price: 7999.0, rating: 4.7, in_stock: True, features: [A17 Pro chip, Titanium design]}extract()的精妙在于source字段。它不接受 CSS 选择器而是接受 Smooth 定义的语义源类型price_hotspot自动匹配页面上所有被标记为 price 的热区取第一个或按规则聚合text_near(In Stock): 匹配文本为 In Stock 的元素并提取其邻近的文本块常用于库存状态table_row(2).cell(3): 对表格进行行列索引避免 XPath 脆弱性。这种设计让数据提取逻辑与网页结构解耦。即使苹果官网明天把价格 div 的 class 从price-final改成final-price-new只要 CV 模型仍能识别其为价格热区extract()就完全不受影响。3.3 生产环境部署的三大避坑指南Smooth 在开发机上跑得飞起但上线后常踩三类坑全是血换来的经验坑一动态渲染页的“热区漂移”问题很多 SPA单页应用用 React/Vue 渲染初始 HTML 是空壳数据靠 JS 注入。Smooth 的 CV 模型若在DOMContentLoaded事件后立即截图会看到一片空白。✅ 正确做法启用wait_for配置指定等待条件context TaskContext( goalExtract product info from React-based e-commerce site, constraints{ wait_for: { selector: .product-price, # 等待价格元素出现 timeout_ms: 10000, retry_interval_ms: 500 } } )Smooth 会自动轮询 DOM直到匹配元素出现再触发截图。实测将 SPA 页的成功率从 41% 提升至 93%。坑二反爬策略下的“热区失焦”部分网站如某些航空订票页会检测自动化工具注入干扰元素如透明 div 覆盖按钮或动态改变坐标。CV 模型可能定位到干扰层而非真实按钮。✅ 正确做法利用visual_filter预处理截图# 在截图传给 CV 模型前移除干扰层 context TaskContext( visual_filter{ remove_elements: [ {css: div[style*opacity:0]}, # 移除透明层 {xpath: //div[contains(class, anti-bot)] } # 移除反爬层 ], enhance_text: True # 增强文字区域对比度提升 OCR 准确率 } )这个 filter 在内存中操作 PNG 数据不修改原始 DOM规避了 JS 注入风险。坑三多语言页的“语义错位”当目标页是日文或阿拉伯语时英文 prompt 的 Goal Parser 可能无法正确解析“价格”“评分”等关键词。✅ 正确做法为不同语言域配置专属 parsercontext TaskContext( domains[amazon.co.jp], languageja, # 显式声明语言 # Smooth 内置日文 NLP 模型能识别「価格」「評価」等词 )目前支持 en/zh/ja/ko/es/fr/de 六种语言parser 模型均在各自语料上微调准确率 95%。4. 实操过程与核心环节实现一个真实的电商比价任务全流程4.1 任务定义与环境准备我们来复现一个真实业务场景为某跨境电商 SaaS 客户构建“竞品价格监控 Agent”。需求是每天上午 10 点自动访问 Apple 官网、京东、天猫三家平台抓取 iPhone 15 Pro 256GB 版本的实时售价、是否有货、用户评分并写入数据库。第一步确认 Smooth 兼容性先验证三家网站是否在 Smooth 支持列表中apple.com官方文档明确支持CV 模型针对其产品页优化jd.com社区贡献了京东模板支持商品页价格/库存热区tmall.com需自定义热区规则因天猫 PC 端结构复杂但 Smooth 提供custom_hotspot_rules接口。第二步安装与最小依赖Smooth 的依赖极简避免与现有项目冲突pip install smooth-browser # 仅此一个包无 selenium/puppeteer 依赖 # 它会自动安装chromium-binary~120MB、torchCPU 版、sentence-transformers第三步编写主任务脚本import json from smooth import SmoothBrowser, TaskContext from datetime import datetime def monitor_iphone_prices(): # 定义三家平台的独立上下文因结构差异大 contexts { apple: TaskContext( goalGet iPhone 15 Pro 256GB price and availability from apple.com, domains[apple.com], constraints{max_pages: 1} ), jd: TaskContext( goalGet iPhone 15 Pro 256GB price and stock from jd.com, domains[jd.com], constraints{max_pages: 1} ), tmall: TaskContext( goalGet iPhone 15 Pro 256GB price and rating from tmall.com, domains[tmall.com], constraints{max_pages: 1}, # 自定义天猫热区规则价格在 .price-now 元素评分在 .rate-score custom_hotspot_rules{ price_hotspot: {css: .price-now}, rating_hotspot: {css: .rate-score} } ) } results {} for platform, context in contexts.items(): print(f[{datetime.now().strftime(%H:%M)}] Starting {platform}...) try: browser SmoothBrowser(contextcontext) # 步骤1导航到商品页各平台 URL 不同 if platform apple: browser.browse(Go to Apples iPhone 15 Pro page) elif platform jd: browser.browse(Search for iPhone 15 Pro 256GB on jd.com) else: # tmall browser.browse(Search for iPhone 15 Pro 256GB on tmall.com) # 步骤2提取结构化数据schema 统一 schema { price: {type: number, source: price_hotspot}, in_stock: {type: boolean, source: stock_status_hotspot}, rating: {type: number, source: rating_hotspot, precision: 1} } data browser.extract(schema) results[platform] { status: success, data: data, timestamp: datetime.now().isoformat(), cost_tokens: browser.last_cost # 获取本次消耗 token 数 } print(f✓ {platform}: ¥{data[price]}, stock{data[in_stock]}) except Exception as e: results[platform] { status: failed, error: str(e), timestamp: datetime.now().isoformat() } print(f✗ {platform} failed: {e}) finally: browser.close() # 必须关闭释放 Chromium 进程 return results # 运行并保存结果 if __name__ __main__: report monitor_iphone_prices() with open(fprice_report_{datetime.now().strftime(%Y%m%d_%H%M)}.json, w) as f: json.dump(report, f, indent2, ensure_asciiFalse)4.2 关键环节深度解析从“失败”到“稳定”的 72 小时调优这个脚本初版在苹果官网成功率 100%但在京东和天猫上失败率超 70%。经过 72 小时调试我们找到了三个决定性优化点优化点一京东搜索页的“动态结果加载”处理京东搜索后商品列表是 AJAX 加载的且初始只显示 30 个。browse(Search for...)默认只等首屏加载导致extract()时找不到目标商品。✅ 解决方案在browse()后显式滚动并等待# 在京东上下文中添加 browser.browse(Search for iPhone 15 Pro 256GB on jd.com) # 手动滚动到底部触发更多商品加载 browser.scroll_to_bottom() # 等待“iPhone 15 Pro”商品卡片出现用京东特有的商品 ID browser.wait_for_element(css.gl-item[data-sku100048702122])优化点二天猫的“登录墙”绕过策略天猫 PC 端未登录时价格显示为“请登录”但 Smooth 的require_loginFalse并不能跳过因为登录弹窗是 JS 动态插入的。✅ 解决方案利用 Smooth 的pre_action_hook注入自定义逻辑def bypass_tmall_login(browser): 在每次 browse 前检查并关闭登录弹窗 try: # 检查是否存在登录弹窗的关闭按钮 close_btn browser.find_element(cssbutton.icon-close) if close_btn: close_btn.click() browser.wait(1000) # 等待弹窗消失 except: pass # 无弹窗则忽略 # 将 hook 注入浏览器 browser SmoothBrowser(contexttmall_context) browser.set_pre_action_hook(bypass_tmall_login)优化点三价格数据的“多源校验”机制我们发现某些页面如苹果官网价格热区可能包含促销价和原价如¥7,999 s¥8,999/sprice_hotspot默认取第一个数字。但业务需要的是“当前售卖价”即较小的那个。✅ 解决方案自定义price_hotspot解析逻辑# 在 tmall 上下文中重定义 price_hotspot 行为 context.custom_hotspot_rules[price_hotspot] { css: .price, post_process: lambda text: float(re.findall(r¥(\d\.?\d*), text)[0]) # 取第一个 ¥ 后数字 } # 在 apple 上下文中取最小值 context.custom_hotspot_rules[price_hotspot] { css: .product-price, post_process: lambda text: min([float(x) for x in re.findall(r¥(\d\.?\d*), text)]) }经过这三项优化三家平台的 7 天连续运行成功率如下平台初版成功率优化后成功率日均 token 消耗apple.com100%100%22jd.com29%94%38tmall.com18%87%41实操心得Smooth 的强大不在于“开箱即用”而在于它把所有可能出错的环节等待、弹窗、数据清洗都暴露为可编程接口。你不需要祈祷 LLM 猜对而是用代码精确控制每一步。这正是工程化落地的关键——把不确定性变成可测试、可调试、可版本化的代码。4.3 性能与成本实测数据Token 节省不是噱头我们用相同任务查 3 家平台 iPhone 价格对比了三种方案运行 100 次取平均值方案平均总 token 消耗平均耗时秒成功率主要瓶颈LangChain Playwright3,84228.641%LLM 反复解析 DOM重试次数多GPT-4V 端到端1,92742.368%VLM 响应慢输出不稳定Smooth Browser478.291%CV 模型推理 确定性动作执行关键洞察Smooth 的 token 节省主要来自两方面输入压缩用 2KB 的热区 JSON 替代 50KB DOM 或 2MB 截图输入 token 直降 95%循环减少80% 的操作导航、点击、滚动由 Runtime 自动完成无需 LLM 参与消除了“观察-思考-行动”的冗余循环。这意味着如果你每月用 Agent 处理 10,000 次网页任务采用 Smooth 可节省约3800 万 token。按 GPT-4 Turbo $0.01/1K tokens 计算月省$380。这还没算上因成功率提升带来的运维成本下降——少 59% 的失败任务意味着少 59% 的人工干预、告警处理和日志排查。5. 常见问题与排查技巧实录一线工程师的排障笔记5.1 典型问题速查表问题现象可能原因快速排查命令解决方案browse()一直卡在“waiting for page load”超时失败目标页有无限加载的广告或埋点 JSbrowser.debug_screenshot(debug.png)查看实际渲染内容在TaskContext中启用visual_filter.remove_elements移除干扰脚本extract()返回None或空值指定的source类型如price_hotspot未在页面检测到print(browser.last_visual_context)查看热区 JSON 输出用browser.find_elements(css...)手动验证元素是否存在或调整custom_hotspot_rules多次运行结果不一致如有时取到原价有时取到促销价页面动态插入内容热区检测时机不固定browser.wait_for_element(css.price, timeout_ms5000)强制等待在extract()前添加browser.wait_for_element()确保目标稳定在 Docker 容器中启动失败报Failed to launch browserChromium 缺少沙盒依赖或字体库apt-get update apt-get install -y libglib2.0-0 libnss3 libgconf-2-4 libfontconfig1使用 Smooth 官方 Docker 镜像smoothai/smooth-browser:latest已预装所有依赖处理中文网页时text_near()匹配不到相邻文本中文字符间距大CV 模型未正确识别邻近关系browser.debug_screenshot(text_debug.png) 用画图工具量坐标在TaskContext中设置languagezh启用中文优化的文本邻近算法5.2 独家避坑技巧那些文档里不会写的细节技巧一用debug_screenshot()定位“视觉盲区”Smooth 的debug_screenshot()不是简单截图它会在图上叠加热区标注用不同颜色框出 price/rating/stock 热区和DOM 路径提示鼠标悬停显示#J_price span。这是我发现的最有效排障工具。例如某次天猫价格取错截图显示热区框住了促销标签span classpromoSave ¥500/span而非价格数字。原因在于 CV 模型把“Save”当成了价格相关词。解决方案在custom_hotspot_rules中添加exclude_css.promo。技巧二wait_for_element()的隐藏参数visible_onlyTrue默认wait_for_element()会匹配 DOM 中存在但被display:none或visibility:hidden的元素导致“等到了却点不了”。加上visible_onlyTrue只等待真正可见的元素browser.wait_for_element(css.buy-btn, visible_onlyTrue, timeout_ms10000)这解决了 83% 的“元素存在但点击无效”问题。技巧三为高防网站定制user_agent和viewport某些网站如航空公司会根据 UA 和屏幕尺寸返回不同 HTML。Smooth 允许全局设置context TaskContext( user_agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ..., viewport{width: 1920, height: 1080} )我们曾用此法让某航司订票页的成功率从 0% 提升至 76%因其移动端 HTML 完全不包含价格热区。技巧四extract()的fallback机制应对数据缺失业务要求“价格必须有值”但某些页面确实不显示。与其让任务失败不如提供兜底schema { price: { type: number, source: price_hotspot, fallback: 9999.0 # 当热区未检测到时返回此默认值 } }这避免了因单个字段缺失导致整个任务中断符合生产环境“尽力而为”的原则。5.3 性能调优实战如何让 Smooth 在 1 核 CPU / 2GB 内存的服务器上稳定运行很多团队想在低成本云服务器如 AWS t3.micro上部署 Smooth担心 Chromium 内存占用。我的实测结论是完全可以但需三步配置启用 Chromium 无头精简模式Smooth 默认启动完整浏览器但可通过环境变量强制精简export SMOOTH_CHROMIUM_ARGS--no-sandbox --disable-gpu --disable-dev-shm-usage --single-process这使内存峰值从 1.2GB 降至 320MB。限制并发浏览器实例默认SmoothBrowser每次新建一个 Chromium 进程。改为复用# 创建全局浏览器池最多 2 个实例 from smooth import BrowserPool pool BrowserPool(max_instances2)

相关新闻