smolagents 网页浏览器自动化实战:用 CodeAgent + Selenium/Helium 构建自主浏览 Agent
smolagents 网页浏览器自动化实战用 CodeAgent Selenium/Helium 构建自主浏览 Agent【免费下载链接】smolagents smolagents: a barebones library for agents that think in code.项目地址: https://gitcode.com/gh_mirrors/smo/smolagents本文基于 smolagents 官方示例文档 docs/source/zh/examples/web_browser.md 展开讲解如何构建一套基于 Agent 的网页浏览器自动化系统由CodeAgent编写并执行 Python 代码驱动 Chrome 浏览器通过 Helium 完成页面导航、点击、页内搜索与弹窗处理再以截图回调把浏览器视觉状态回灌给多模态大模型最终实现自主的信息检索与提取。读完本文你将能完整复现该 Agent 的三个自定义工具、截图回调机制与 Helium 操作指令的写法并理解step_callbacks、observations_images、additional_authorized_imports等关键参数在源码中的真实作用从而把这套模式迁移到自己的网站数据抓取、UI 验证与内容监控场景。一、系统能力与整体架构官方文档定义了这个 Agent 需要完成五类动作导航到网页Navigate to web pages点击元素Click on elements在页面内搜索Search within pages处理弹出窗口和模态框Handle popups and modals提取信息Extract information从源码结构看这套系统由三层角色协作完成大脑CodeAgent。它不直接调用浏览器 API而是让 LLM 每一步生成一段 Python 代码交给本地 Python 执行器运行。这正是 smolagents think in code 的核心范式。四肢Helium 三个自定义tool工具。go_to、click、scroll_down等 Helium 函数供模型在代码中直接调用search_item_ctrl_f、go_back、close_popups三个tool工具补齐页面搜索、回退与关弹窗的能力。眼睛save_screenshot步骤回调。每个动作步结束后自动截取浏览器画面写入记忆步的observations_images字段作为下一步模型的图像输入同时把当前 URL 追加进observations文本。这套示例在仓库中不仅有 notebook 形态的文档还有一份可直接运行的脚本版本 src/smolagents/vision_web_browser.py其工具定义与截图回调和文档逐段对应并额外提供了命令行入口可作为文档 → 生产脚本的参考映射。二、安装依赖按照文档运行该示例需要安装浏览器自动化栈与 smolagents 本体pip install smolagents selenium helium pillow -q其中selenium提供 WebDriver 抽象helium在 Selenium 之上封装了go_to/click/Text等更易读的语义化 APIpillow用于处理截图图像。若模型走 Hugging Face Inference Client还需通过.env提供访问凭证——文档中的load_dotenv()负责加载它。三、导入库并定义三个核心浏览器工具文档的导入段需要同时引入 Selenium 与 smolagents 的记忆步类型回调签名要用到ActionStepfrom io import BytesIO from time import sleep import helium from dotenv import load_dotenv from PIL import Image from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from smolagents import CodeAgent, tool from smolagents.agents import ActionStep # Load environment variables load_dotenv()接下来是三个tool装饰的核心浏览器交互工具。tool会自动解析函数的类型注解与 docstring生成工具名、参数 schema 与描述供模型在 system prompt 中看到并调用。tool def search_item_ctrl_f(text: str, nth_result: int 1) - str: Searches for text on the current page via Ctrl F and jumps to the nth occurrence. Args: text: The text to search for nth_result: Which occurrence to jump to (default: 1) elements driver.find_elements(By.XPATH, f//*[contains(text(), {text})]) if nth_result len(elements): raise Exception(fMatch n°{nth_result} not found (only {len(elements)} matches found)) result fFound {len(elements)} matches for {text}. elem elements[nth_result - 1] driver.execute_script(arguments[0].scrollIntoView(true);, elem) result fFocused on element {nth_result} of {len(elements)} return result tool def go_back() - None: Goes back to previous page. driver.back() tool def close_popups() - str: Closes any visible modal or pop-up on the page. Use this to dismiss pop-up windows! This does not work on cookie consent banners. webdriver.ActionChains(driver).send_keys(Keys.ESCAPE).perform()各工具的语义细节值得注意search_item_ctrl_f(text, nth_result1)模拟CtrlF页面内搜索。它用 XPathcontains(text(), ...)找出所有包含目标文本的节点把第nth_result个节点scrollIntoView滚到视口顶部并返回匹配总数——模型据此判断第 1 处没找到、还有几处可跳。文档版本直接把text拼进 XPath仓库脚本版本则改进了这一点src/smolagents/vision_web_browser.py 中的_escape_xpath_string会用concat()处理含引号的输入避免 XPath 注入式语法错误。若搜索文本含单引号建议参考该实现自行转义。go_back()调用driver.back()回退上一页对应浏览器的前进/后退栈。close_popups()向页面发送ESCAPE键用于关闭带叉号的模态框/弹窗。docstring 明确声明它对 cookie 同意横幅无效——这类横幅通常不响应 Escape需要用 Helium 的Text(...).exists() 点击同意按钮来处理见后文操作指令。三个工具共享一个模块级变量driver下节初始化它们作为闭包捕获该变量因此工具定义必须放在driver初始化之前声明、在初始化之后使用。四、配置 Chrome 驱动与截图回调4.1 Chrome 启动参数# Configure Chrome options chrome_options webdriver.ChromeOptions() chrome_options.add_argument(--force-device-scale-factor1) chrome_options.add_argument(--window-size1000,1350) chrome_options.add_argument(--disable-pdf-viewer) chrome_options.add_argument(--window-position0,0) # Initialize the browser driver helium.start_chrome(headlessFalse, optionschrome_options)四个参数的作用--force-device-scale-factor1强制 1x 缩放保证截图像素与 CSS 像素一致高分屏上会否则截图模糊、坐标漂移--window-size1000,1350固定视口让每次截图的构图稳定--disable-pdf-viewer防止 PDF 内容被浏览器内置查看器接管--window-position0,0固定窗口位置。helium.start_chrome封装了 Chrome 驱动初始化示例中headlessFalse意味着浏览器窗口可见便于观察 Agent 行为生产环境可考虑无头模式需保证环境内有可用显示器或 X server。4.2 截图回调save_screenshotdef save_screenshot(memory_step: ActionStep, agent: CodeAgent) - None: sleep(1.0) # Let JavaScript animations happen before taking the screenshot driver helium.get_driver() current_step memory_step.step_number if driver is not None: for previous_memory_step in agent.memory.steps: # Remove previous screenshots for lean processing if isinstance(previous_memory_step, ActionStep) and previous_memory_step.step_number current_step - 2: previous_memory_step.observations_images None png_bytes driver.get_screenshot_as_png() image Image.open(BytesIO(png_bytes)) print(fCaptured a browser screenshot: {image.size} pixels) memory_step.observations_images [image.copy()] # Create a copy to ensure it persists # Update observations with current URL url_info fCurrent url: {driver.current_url} memory_step.observations ( url_info if memory_step.observations is None else memory_step.observations \n url_info )这段回调是整个视觉闭环的关键逐行拆解其设计意图sleep(1.0)等待 JavaScript 动画渲染完成再截图避免截到过渡帧。滚动淘汰旧截图遍历agent.memory.steps把步号落后当前两步以上的ActionStep的observations_images置为None。这是一个 token 预算管理策略——浏览器任务每一步都带一张 PNG上下文会迅速膨胀而模型通常只需要当前与上一步的画面来判断状态变化。写入observations_imagesimage.copy()创建副本确保图像对象持久存活原文注释 Create a copy to ensure it persists, important!。该字段是ActionStep数据类的正式成员见 src/smolagents/memory.pyobservations: str | None与observations_images: list[PIL.Image.Image] | None并列存在。追加当前 URL 到observations即使代码执行没有任何print输出模型也能在观察中看到自己当前所在的页面地址。这些字段并非摆设。在 src/smolagents/memory.py 的ActionStep.to_messages中可以看到消费路径observations_images会被包装成roleUSER的图像消息observations被包装成roleTOOL_RESPONSE的文本消息随下一步的model_input_messages一起送回给模型。换句话说截图 → 记忆步 → 多模态输入的链路是 smolagents 记忆层的内建能力回调只是负责填充数据。4.3step_callbacks的注册机制从源码结构看CodeAgent继承自MultiStepAgent其构造函数签名见 src/smolagents/agents.pystep_callbacks既可以是list[Callable]也可以是dict[Type[MemoryStep], Callable | list[Callable]]。_setup_step_callbacks的注册逻辑在 src/smolagents/agents.pydef _setup_step_callbacks(self, step_callbacks): # Initialize step callbacks registry self.step_callbacks CallbackRegistry() if step_callbacks: # Register callbacks list only for ActionStep for backward compatibility if isinstance(step_callbacks, list): for callback in step_callbacks: self.step_callbacks.register(ActionStep, callback) # Register callbacks dict for specific step classes elif isinstance(step_callbacks, dict): for step_cls, callbacks in step_callbacks.items(): if not isinstance(callbacks, list): callbacks [callbacks] for callback in callbacks: self.step_callbacks.register(step_cls, callback) else: raise ValueError(step_callbacks must be a list or a dict) # Register monitor update_metrics only for ActionStep for backward compatibility self.step_callbacks.register(ActionStep, self.monitor.update_metrics)也就是说传入列表时回调只对ActionStep动作步生效——这正是截图回调想要的时机在模型输出代码并执行完之后触发而框架还会自动为ActionStep追加一个monitor.update_metrics回调负责累计 token 用量与耗时等指标。五、创建浏览器自动化 CodeAgentfrom smolagents import InferenceClientModel # Initialize the model model_id meta-llama/Llama-3.3-70B-Instruct # You can change this to your preferred model model InferenceClientModel(model_idmodel_id) # Create the agent agent CodeAgent( tools[go_back, close_popups, search_item_ctrl_f], modelmodel, additional_authorized_imports[helium], step_callbacks[save_screenshot], max_steps20, verbosity_level2, ) # Import helium for the agent agent.python_executor(from helium import *, agent.state)InferenceClientModel的定义位于 src/smolagents/models.py通过 Hugging Face 推理端点调用模型model_id可替换为你有权限访问的其他模型。这里有一个重要前提截图会以图像形式进入模型上下文因此模型必须具备视觉VLM能力否则截图无法被看到Agent 会退化成盲操作。仓库脚本版本 src/smolagents/vision_web_browser.py 也印证了模型能力的影响它对较难的 GitHub trending 任务标注了 The agent is able to achieve this request only when powered by GPT-4o or Claude-3.5-sonnet英文文档版本则默认推荐Qwen/Qwen2-VL-72B-Instruct这类视觉模型。CodeAgent各参数结合源码说明参数文档取值源码行为tools3 个浏览器tool在 src/smolagents/agents.py 的_setup_tools中按tool.name建索引并自动追加final_answer工具self.tools.setdefault(final_answer, FinalAnswerTool())模型据此提交最终答案modelInferenceClientModel作为每步的generate目标支持多模态消息additional_authorized_imports[helium]在 src/smolagents/agents.py 中与BASE_BUILTIN_MODULES取并集得到本地 Python 执行器的白名单若代码 import 了白名单外的模块会被拦截并提示 Consider passing said import underadditional_authorized_imports见 src/smolagents/agents.py#L1747step_callbacks[save_screenshot]按上文机制注册到ActionStep每步执行后触发截图max_steps20MultiStepAgent默认值也是 20src/smolagents/agents.py#L300超过后 Agent 以max_steps_error状态结束verbosity_level2对应LogLevel2时输出每步代码、工具输出等完整日志便于调试 Agent 的决策过程最后一行agent.python_executor(from helium import *, agent.state)是容易被忽略但必不可少的一步它把from helium import *预执行进 Agent 的共享命名空间agent.state使模型后续生成的代码可以裸写go_to(...)、click(...)而无需每步重复 import。这也解释了为什么helium必须同时出现在additional_authorized_imports白名单里——预执行本身也要通过 import 检查。六、编写 Helium 操作指令代码执行器只保证语法正确模型是否会用Helium 还得靠 prompt 教学。文档给出的helium_instructions会拼接在任务请求之后传给agent.run内容是面向模型的操作手册helium_instructions You can use helium to access websites. Dont bother about the helium driver, its already managed. Weve already ran from helium import * Then you can go to pages! Code: py go_to(github.com/trending) end_code You can directly click clickable elements by inputting the text that appears on them. Code: py click(Top products) end_code If its a link: Code: py click(Link(Top products)) end_code If you try to interact with an element and its not found, youll get a LookupError. In general stop your action after each button click to see what happens on your screenshot. Never try to login in a page. To scroll up or down, use scroll_down or scroll_up with as an argument the number of pixels to scroll from. Code: py scroll_down(num_pixels1200) # This will scroll one viewport down end_code When you have pop-ups with a cross icon to close, dont try to click the close icon by finding its element or targeting an X element (this most often fails). Just use your built-in tool close_popups to close them: Code: py close_popups() end_code You can use .exists() to check for the existence of an element. For example: Code: py if Text(Accept cookies?).exists(): click(I accept) end_code 这份指令浓缩了若干实战经验值得逐条理解go_to(github.com/trending)导航只需域名加路径无需https://前缀。按可见文本点击click(Top products)直接以按钮上显示的文字定位元素若是链接则用click(Link(...))显式声明类型。这比让模型写 CSS 选择器稳定得多——页面上渲染出的文字就是最可靠的锚点。LookupError即反馈信号元素找不到时 Helium 抛LookupError模型会把它当观察结果修正下一步动作而不是直接终止。每次点击后停一步点击后停下来看截图确认结果是防止模型在盲操作中连点失控的关键纪律。滚动用像素值scroll_down(num_pixels1200)约等于一个视口高度。弹窗用close_popups而非找叉号文档直言点击 X 元素大多会失败统一交给 Escape 键工具处理而 cookie 横幅则用Text(Accept cookies?).exists()先探测再点击接受。仓库脚本版 src/smolagents/vision_web_browser.py 的helium_instructions是同一份手册的增强版额外补充了几条更完整的使用约束值得在自己的实现中一并吸收声明截图只在整个动作执行完毕后截取看不到中间状态the screenshot will only be taken at the end of the whole action避免模型基于不存在的中间帧做推理页面卡住时可import time; time.sleep(5.0)等待但不要滥用枚举页面元素时不要写find_all(S(ol li))这类代码式选择器搜索直接看最新截图或用search_item_ctrl_f工具明确Dont kill the browser、先清掉模态框/cookie 横幅再点击其他元素、分步推进而非一步到位最后才调用final_answer(YOUR_ANSWER_HERE)。七、运行任务维基百科与 GitHub Trending 两个案例7.1 维基百科信息检索search_request Please navigate to https://en.wikipedia.org/wiki/Chicago and give me a sentence containing the word 1992 that mentions a construction accident. agent_output agent.run(search_request helium_instructions) print(Final output:) print(agent_output)任务描述与helium_instructions直接拼接后传给agent.run。Agent 的典型执行轨迹是go_to打开页面 → 用search_item_ctrl_f(1992)逐处跳转定位 → 结合截图确认哪一处涉及施工事故 → 用final_answer提交答案。max_steps20为该过程提供了预算上限。7.2 更复杂的多跳导航任务github_request Im trying to find how hard I have to work to get a repo in github.com/trending. Can you navigate to the profile for the top author of the top trending repo, and give me their total number of commits over the last year? agent_output agent.run(github_request helium_instructions) print(Final output:) print(agent_output)这个任务要求连续多次页面跳转trending 首页 → 仓库 → 作者主页 → 统计 commit 数是检验 Agent 多步规划能力的更好案例同时也如前所述对模型能力要求更高建议搭配强多模态模型运行。7.3 以脚本方式运行如果不想用 notebook 形态仓库提供了等价的命令行入口。pyproject.toml 中注册了webagent smolagents.vision_web_browser:main因此安装 smolagents 后可直接webagent your prompt here --model-type InferenceClientModel --model-id your-vlm-model该入口支持--model-type、--model-id、--provider、--api-base、--api-key等参数见 src/smolagents/vision_web_browser.py#L27-L63 的argparse定义默认提示词即为上面的维基百科任务。脚本版还额外挂载了WebSearchTool()并用更完整的helium_instructions可作为文档示例的加强参考实现。八、适用场景与使用边界文档总结了该系统的优势场景从网站提取数据Data extraction from websites网页研究自动化Web research automation用户界面测试与验证UI testing and verification内容监控Content monitoring结合实现细节还有几条使用边界需要明确模型必须是 VLM。截图回灌是系统的核心感知通道纯文本模型只能盲操作复杂任务的完成率会显著下降仓库脚本注释指出 GitHub trending 任务需要 GPT-4o / Claude-3.5-sonnet 级别的能力。不要尝试登录。指令中明确 Never try to login in a page涉及登录态的页面不在该方案覆盖范围内。cookie 横幅需特判。close_popups对 cookie 同意横幅无效需用Text(...).exists()探测后显式点击。headlessFalse需要可用显示环境无显示器的服务器环境需要自行调整启动方式。每步截图带来 token 开销淘汰两步前旧图 的策略step_number current_step - 2时置空已做了缓解但长任务仍需关注max_steps与上下文预算的配合。小结本文完整复现了 smolagents 官方 web browser 示例的搭建路径三个tool浏览器工具 Chrome/Helium 驱动 save_screenshot步骤回调 携带 Helium 操作手册的CodeAgent。源码层面step_callbacks在 src/smolagents/agents.py 按记忆步类型注册截图经 src/smolagents/memory.py 的ActionStep.observations_images字段进入下一步多模态输入白名单 import 由additional_authorized_imports控制——理解这条链路后你可以把同样的截图回灌 代码执行模式扩展到其他 GUI 自动化场景。完整的可运行参考实现见 src/smolagents/vision_web_browser.pyAgent 行为相关的测试位于 tests/test_agents.py可进一步对照阅读。【免费下载链接】smolagents smolagents: a barebones library for agents that think in code.项目地址: https://gitcode.com/gh_mirrors/smo/smolagents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考