OpenClaw 网页抓取:数据采集实战中的 web_fetch 与 Browser 配置 1. 从一次抓取失败说起OpenClaw 网页抓取到底难在哪OpenClaw 网页抓取指的是用 OpenClaw 内置的 web_fetch 与 Browser 两条采集路径把目标页面的正文、列表、商品信息或评论抓下来再交给后续流程做结构化处理。它适合三类人需要批量采集公开数据做分析的数据同学、想给 Agent 喂实时网页内容的开发者、以及刚接触数据采集、不想一上来就写几百行爬虫的新手。我这次要复现的场景很具体从一批公开文章页和商品列表页里稳定拿到标题、正文、价格和发布时间并且能定位抓取失败的原因。真正上手后你会发现难点不在“抓一次”而在“抓得稳”。静态页面用 web_fetch 一把过动态渲染的页面直接返回空壳分页和无限滚动不处理只能拿到第一屏请求频率一高返回的就不是数据而是验证页。更麻烦的是报错信息往往很含糊你分不清是网络问题、参数写错还是页面结构变了。所以这篇不堆概念直接按“能跟做”的路线走先讲清 web_fetch 和 Browser 各自适合什么再给出可复制的配置片段然后跑一次完整验证最后把常见报错逐个对照排查。中间会穿插我踩过的坑比如 extractMode 选错导致正文丢失、wait 时间不够拿到半截 DOM、以及把 Browser 的 snapshot 当成最终数据直接存。需要说明的是OpenClaw 的采集能力本身是本地执行的它不替你绕过任何站点规则。你要做的是把请求参数、等待时机、去重逻辑配对让采集过程可控、可复现。下面从环境准备开始一步步把这条链路搭起来。2. TaoToken 前置准备给 OpenClaw 配好模型与 KeyOpenClaw 在采集流程里承担的是“理解与结构化”的角色web_fetch 或 Browser 把原始内容拿回来之后需要模型把非结构化文本整理成字段。所以第一步不是写抓取代码而是把模型接入配好。这里用 TaoToken 作为模型接入层它的 API 地址是 https://taotoken.net/api兼容常见的对话补全调用方式OpenClaw 里填 Base URL 和 Key 就能用。先拿到 Key。打开 https://taotoken.net/api-keys 创建一个新的 API Key复制保存。注意 Key 只在创建时完整显示一次丢了只能重建。接着确认你要用的模型 ID比如做结构化抽取时选一个指令跟随稳定的模型即可具体可用列表在模型对话页能看到https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。然后在 OpenClaw 的模型配置里填三件套Base URL 填 https://taotoken.net/api API Key 填刚才复制的Model ID 填你选定的模型。如果你用的是 Claude Code 这类需要 Anthropic 兼容端点的工具接入文档里有对应的 Base URL 写法参考 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。配置完成后先别急着抓网页用一次最简单的对话请求验证模型通不通通了再进入采集环节否则后面报错你分不清是模型问题还是抓取问题。这一步的产出是一个可用的模型端点。它不直接参与 HTTP 抓取但决定了你抓回来的内容能不能被正确解析成字段。很多人跳过这步直接写 web_fetch结果抓到了内容却抽不出结构化数据回头排查成本更高。3. 可复制配置web_fetch 与 Browser 两条采集路径这一节给可直接粘贴的配置。OpenClaw 的采集配置通常写在项目根目录的配置文件里我用 JSON 形式给出字段名和路径按你本地实际项目调整。核心是把 web_fetch 和 Browser 分开配置各自有独立的超时、重试和提取模式。先看 web_fetch 的配置片段适合静态页面和文章正文{ tools: { web_fetch: { enabled: true, timeoutMs: 15000, maxChars: 20000, extractMode: markdown, retry: { maxAttempts: 3, backoffMs: 1000 }, headers: { User-Agent: Mozilla/5.0 (compatible; OpenClaw/1.0) } } } }extractMode 选 markdown 会保留标题层级和链接选 text 只留纯文本。抓文章正文用 markdown抓纯字段用 text 更省 token。maxChars 别设太大否则一次请求塞进模型的内容过长反而影响抽取准确率。再看 Browser 的配置适合需要执行 JavaScript 的动态页面{ tools: { browser: { enabled: true, headless: true, defaultWaitMs: 3000, viewport: { width: 1440, height: 900 }, snapshot: { includeText: true, includeLinks: true, maxElements: 500 } } } }headless 设为 true 表示无界面运行本地调试时可以临时改成 false 看页面实际渲染情况。defaultWaitMs 是打开页面后的默认等待时间动态内容多的站点要调大。snapshot 的 maxElements 控制快照元素上限太小会漏掉列表项太大则快照体积膨胀。如果你用 Cline MCP 或 Codex 的 auth.json 方式接入同样要保证三件套齐全Base URL 指向 https://taotoken.net/api Key 用你在 api-keys 页创建的Model ID 填实际模型名。三者缺一调用就会在鉴权或路由阶段失败。配置写完后保存重启 OpenClaw 让配置生效。4. 逐步验证跑通一次完整采集请求配置就绪后按“先静态、后动态、再批量”的顺序验证每一步都有明确的成功标志。第一步验证 web_fetch 抓静态页。在 OpenClaw 里发起一次抓取目标选一个结构简单的文章页result web_fetch( urlhttps://example.com/article, extractModemarkdown, maxChars10000 ) print(result[:500])成功标志是返回内容里能看到文章标题和正文段落而不是一段 HTML 源码或空字符串。如果返回的是空先检查 URL 是否可公开访问再确认 extractMode 没写错。第二步验证 Browser 抓动态页。动态页面的特征是首屏 HTML 里没有目标数据数据靠 JS 渲染browser(actionopen, targetUrlhttps://example.com/list) browser(actionact, kindwait, timeMs3000) snapshot browser(actionsnapshot) print(len(snapshot[elements]))成功标志是 snapshot 的元素数量明显大于静态抓取的结果且能在元素里找到列表项文本。如果元素数很少把 wait 时间加到 5000 再试或者把 headless 关掉看页面是否真的加载出了内容。第三步验证模型结构化。把上一步拿到的内容交给模型抽取字段extracted model_chat( messages[ {role: system, content: 从给定文本中抽取标题、价格、发布时间输出 JSON。}, {role: user, content: snapshot_text} ] ) print(extracted)成功标志是返回合法 JSON字段齐全。如果模型返回的是解释性文字而不是 JSON在 system 里强调“只输出 JSON不要额外说明”。三步都通过说明采集链路是通的。接下来把单次抓取包成循环加上随机延迟和去重就能跑批量任务。批量时建议先小规模跑 5 条确认字段抽取稳定后再放大。5. 常见报错排查401、local proxy failed 与空 choices采集过程中最容易卡住的不是逻辑而是报错定位。下面按真实遇到的报错逐个对照。401 Unauthorized。这个几乎都是 Key 问题。检查三处Key 是否复制完整、Base URL 是否写成 https://taotoken.net/api 而不是带路径的地址、请求头里的 Authorization 格式是否为 Bearer 加空格加 Key。如果 Key 刚重建过旧 Key 会立即失效记得同步更新配置。local proxy failed。这个报错通常出现在本地网络层不是模型侧的问题。先确认本机没有残留的代理环境变量干扰请求再检查 OpenClaw 的 timeoutMs 是否设得太短导致连接被提前掐断。把 timeoutMs 调到 15000 以上重试一次。如果仍然失败换一个目标 URL 测试排除是单个站点不可达。reading choices 相关报错。这类报错说明请求发出去了但返回体里没有预期的 choices 字段。常见原因是模型 ID 写错或者请求体格式不符合接口要求。对照接入文档里的请求示例确认 messages 结构正确、model 字段是有效模型名。如果返回体里是错误信息而不是 choices先把完整返回打印出来看别只看异常摘要。OAuth 相关报错。如果你用的是需要 OAuth 的客户端报错往往指向 token 过期或 scope 不足。重新走一次授权流程确认授权范围包含模型调用。用 API Key 方式接入的话一般不会遇到这类问题所以能换 Key 就换 Key少一层授权就少一类故障。还有一个隐蔽的坑抓取成功但抽取为空。这通常不是报错而是页面结构变了或者 wait 时间不够导致快照里没有目标元素。排查方法是把 snapshot 的原始内容打印出来人工确认目标文本在不在里面。在就是抽取逻辑问题不在就是抓取时机问题。6. 把采集接进长期流程Coding Plan 与后续动作单次采集跑通只是起点。如果你要把网页抓取做成每天定时跑的任务或者接进 Agent 让它自主决定抓什么、怎么解析那模型调用量会明显上升这时候按量计费不如用 Coding Plan 更省心。Coding Plan 适合长期编码和 Agent 场景具体额度与用法在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 能看到。接入侧的统一入口还是 APIhttps://taotoken.net/api Key 在 https://taotoken.net/api-keys 管理配置细节查接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。需要临时验证某个模型对结构化抽取的效果直接去模型对话页试https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。最后给一个实用建议把每次采集的原始快照和抽取结果分开存。原始快照留档方便页面结构变化时回溯抽取结果入库供后续分析。两者用同一个任务 ID 关联出问题时能快速定位是抓取阶段还是解析阶段。采集任务的稳定性靠的不是一次写对而是每次失败都能快速归因。