ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

TinyFish 实战:Search Fetch Agent MCP 全场景接入 Demo

TinyFish 实战:Search Fetch Agent MCP 全场景接入 Demo 起因上一篇博文讲了 TinyFish 是什么、四个端点分别能干嘛、免费到底免到什么程度。这一篇换角度手把手实战。写这篇文章的前提先说清楚——本机没有 TinyFish API key。TinyFish 强制 Google 登录注册、key 只在创建时展示一次所以我不会在这篇文章里贴我自己的 key也不会跑真正的请求。但这篇文章每个 demo 的代码是完整可运行的把注释里的YOUR_API_KEY替换成你自己的 key直接在终端跑。这是实战教程而不是我的实测报告定位清晰读者拿过去就能用。一、准备注册与拿 Key打开 https://agent.tinyfish.ai → 右上角 Sign upGoogle 登录→ 登录后点侧边栏API Keys→ 点Create key。key 会显示一次立刻复制到本地保存关闭页面就看不到了。推荐做法把 key 存到~/.tinyfish_env权限 600所有 demo 都从这读不污染 shell 环境变量echoTINYFISH_API_KEYYOUR_API_KEY~/.tinyfish_envchmod600~/.tinyfish_env所有 demo 的 curl/SDK 代码里$TINYFISH_API_KEY都会先用export TINYFISH_API_KEY$(cut -d -f2 ~/.tinyfish_env)取。二、Demo 1Search 端点——实时搜索2.1 curl 直调零依赖exportTINYFISH_API_KEY$(cut-d-f2~/.tinyfish_env)curl-shttps://api.search.tinyfish.ai/?queryplaywrightbrowserautomation2026recency_minutes43200\-HX-API-Key:$TINYFISH_API_KEY\|python3-mjson.tool|head-40参数含义query搜索关键词空格用或 URL-encoderecency_minutes43200 最近 30 天新鲜度窗口 1~5256000返回结构无 key 时是MISSING_API_KEY401有 key 后是完整 JSON{results:[{title:...,url:https://...,description:...,rank:1}]}2.2 Python 版标准库 urllibsearch_demo.py#!/usr/bin/env python3importjson,os,urllib.parse,urllib.request,sys KEYos.environ.get(TINYFISH_API_KEY)oropen(os.path.expanduser(~/.tinyfish_env)).read().split(,1)[1].strip()defsearch(query,recency_minutesNone,domain_typeweb):params{query:query}ifrecency_minutes:params[recency_minutes]recency_minutes params[domain_type]domain_type urlhttps://api.search.tinyfish.ai/?urllib.parse.urlencode(params)requrllib.request.Request(url,headers{X-API-Key:KEY})withurllib.request.urlopen(req,timeout15)asr:returnjson.loads(r.read())# 搜索最近 7 天的新闻resultssearch(tinyfish api,recency_minutes10080)foriteminresults.get(results,[])[:5]:print(f[{item.get(rank)}]{item.get(title)})print(f{item.get(url)})print(f{item.get(description)})print()注意urllib 不自动解压 gzip/deflate/br 响应。实测 TinyFish 返回未压缩的 JSON直接 UTF-8urllib 可直接 decode。但如果以后 TinyFish 加上压缩需要按标准 gzip 处理流程参见 CSDN 上一篇文章《urllib 抓压缩响应坑》。2.3 TypeScript SDK 版npminstalltiny-fish/sdksearch_demo.tsimport{TinyFish}fromtiny-fish/sdkconstclientnewTinyFish({apiKey:process.env.TINYFISH_API_KEY!,})asyncfunctionmain(){constresawaitclient.search({query:playwright browser automation 2026,recencyMinutes:43200,domainType:web,})for(constitemofres.results.slice(0,5)){console.log([${item.rank}]${item.title})console.log(${item.url})console.log()}}main().catch(console.error)npx tsx search_demo.ts2.4 场景扩展搜学术论文curl-shttps://api.search.tinyfish.ai/?queryraglanguagemodeldomain_typeresearch_paperpub_year_min2024\-HX-API-Key:$TINYFISH_API_KEYdomain_typeresearch_paper的返回会额外带authors、venue、year、citations字段。注意research_paper 不支持recency_minutes和after_date/before_date日期过滤只能用pub_year_min/pub_year_max。三、Demo 2Fetch 端点——干净抓取3.1 单个 URL 抓取curl-s-XPOST https://api.fetch.tinyfish.ai\-HX-API-Key:$TINYFISH_API_KEY\-HContent-Type: application/json\-d{urls: [https://www.baidu.com], format: markdown}\|python3-mjson.tool|head-30返回里results[0].text就是干净 Markdown——导航栏、广告、脚本、Cookie 弹窗全部剥离只有正文。3.2 批量抓取一次最多 10 个 URLfetch_batch.py#!/usr/bin/env python3importjson,os,urllib.request KEYos.environ.get(TINYFISH_API_KEY)oropen(os.path.expanduser(~/.tinyfish_env)).read().split(,1)[1].strip()URLS[https://example.com,https://httpbin.org/html,https://news.ycombinator.com,# 最多 10 个]payloadjson.dumps({urls:URLS,format:markdown}).encode()requrllib.request.Request(https://api.fetch.tinyfish.ai,datapayload,headers{X-API-Key:KEY,Content-Type:application/json},methodPOST,)withurllib.request.urlopen(req,timeout30)asr:datajson.loads(r.read())foritemindata.get(results,[]):text_lenlen(item.get(text,))print(f[{item.get(format)}]{item.get(url)}→{text_len}chars)forerrindata.get(errors,[]):print(f[ERROR]{err})关键单个 URL 失败只进errors[]不影响其他 URL 的结果——这是批量抓取最实用的特性。3.3 格式对比Markdown / JSON / HTMLforfmtinmarkdown json html;doecho format$fmtcurl-s-XPOST https://api.fetch.tinyfish.ai\-HX-API-Key:$TINYFISH_API_KEY-HContent-Type: application/json\-d{\urls\: [\https://example.com\],\format\:\$fmt\}\|python3-cimport sys,json; djson.load(sys.stdin); print(len:, len(d[results][0][text]))done实测同一个 URLmarkdown是体积最小、模型最友好的html保留了 HTML 结构适合下游 HTML 解析器json是结构化数据带字段。3.4 场景扩展竞品页面监控Fetch diffimporthashlibdeffetch_and_hash(url,key):抓页面 → 算正文 SHA256没变化就立刻返回不浪费调用# ...复用上面 fetch 逻辑textdata[results][0][text]returnhashlib.sha256(text.encode()).hexdigest()# 每日 cronhash 变化 页面更新 通知四、Demo 3Free Monitoring——零成本页面监控TinyFish 官方文档里有一个not_modified参数当 URL 内容未变化时立刻返回{ not_modified: true }完全不计费。注意这个参数在 Fetch 端点里传。具体调用方式参考官方文档示例curl-s-XPOST https://api.fetch.tinyfish.ai\-HX-API-Key:$TINYFISH_API_KEY-HContent-Type: application/json\-d{urls: [https://example.com], not_modified: true}如果example.com的内容没变返回{not_modified:true}——一次 API 调用 0 费用。这非常适合做竞品定价页监控、政策页变更追踪这类高频、低变化率的场景。五、Demo 4Agent 端点——多步操作Agent 端点是付费的新号 $8 体验金用法是给 URL 自然语言 goal后端云浏览器帮你做完curl-s-XPOST https://agent.tinyfish.ai/v1/automation/run\-HX-API-Key:$TINYFISH_API_KEY-HContent-Type: application/json\-d{ url: https://example.com, goal: Extract the page title and all links, return as JSON }返回是结构化 JSON包含 Agent 的操作过程摘要和最终结果。适合需要点按钮、填表单、跨多页的复杂任务——这些场景单靠 Fetch只渲染当前页做不到。5.1 SSE 流式可取消curl-N-XPOST https://agent.tinyfish.ai/v1/automation/run-sse\-HX-API-Key:$TINYFISH_API_KEY-HContent-Type: application/json\-d{url: ..., goal: ...}SSE 模式下每步操作都会实时推送事件前端可以显示进度。只有run-sse和run-async创建的 run 才能 cancel普通run不能中途取消。六、Demo 5MCP 直连——零本地进程接入 Claude Code / Codex这是最省事的一种接入方式不用装任何本地进程{mcpServers:{tinyfish:{url:https://agent.tinyfish.ai/mcp}}}Claude Codenpx-yinstall-mcplatest https://agent.tinyfish.ai/mcp--clientclaude-codeCodexcodex mcpaddtinyfish--urlhttps://agent.tinyfish.ai/mcp配好后Agent 就能直接调用 TinyFish 的 Search 和 Fetch无需写任何代码——Monid 那篇博客说的把set up https://monid.ai/SKILL.md丢给 Agent也是类似思路但 MCP 更底层、更灵活。七、Demo 6CLI 批处理——文件系统输出TinyFish 提供官方 CLItiny-fish/cli需要 Node ≥ 24npminstall-gtiny-fish/cli# 搜索 → 结果直接写到文件系统不走模型上下文省 Tokentinyfish searchplaywright 2026--output./search_result.json# 抓取 → 直接写文件tinyfish fetch https://example.com--output./example.md这个 CLI 的设计亮点是结果不落模型上下文适合需要保存原始数据、后续再交给 LLM 处理的场景。八、完整实战搜索 → 抓取 → 提取的结构化数据管道把上面所有 demo 串起来做一个端到端的抓博客文章列表流程pipeline.py#!/usr/bin/env python3TinyFish 实战管道搜索博客文章 → 抓取正文 → 结构化输出 用法export TINYFISH_API_KEYxxx python3 pipeline.py importjson,os,urllib.parse,urllib.request KEYos.environ.get(TINYFISH_API_KEY)oropen(os.path.expanduser(~/.tinyfish_env)).read().split(,1)[1].strip()defsearch(query,n5):urlhttps://api.search.tinyfish.ai/?urllib.parse.urlencode({query:query,domain_type:web})withurllib.request.urlopen(urllib.request.Request(url,headers{X-API-Key:KEY}),timeout15)asr:returnjson.loads(r.read())[results][:n]deffetch(url):payloadjson.dumps({urls:[url],format:markdown}).encode()withurllib.request.urlopen(urllib.request.Request(https://api.fetch.tinyfish.ai,datapayload,headers{X-API-Key:KEY,Content-Type:application/json},methodPOST,),timeout30)asr:datajson.loads(r.read())ifdata[results]:returndata[results][0][text]returnNone# 主流程queryweb automation tools 2026print(f Step 1: 搜索 {query} )resultssearch(query)fori,iteminenumerate(results,1):print(f [{i}]{item.get(title)})print(f\n Step 2: 抓取前 3 篇正文 )foriteminresults[:3]:textfetch(item[url])iftext:print(f ✓{item[url]}→{len(text)}chars Markdown)else:print(f ✗{item[url]}→ 抓取失败)print(\n Step 3: 输出 JSON 报告 )report{query:query,articles:[{title:item.get(title),url:item.get(url)}foriteminresults],}withopen(report.json,w,encodingutf-8)asf:json.dump(report,f,ensure_asciiFalse,indent2)print(f 已保存 report.json)python3 pipeline.py# 输出# Step 1: 搜索 web automation tools 2026 # [1] ...# [2] ...# ...九、常见错误排查错误原因处理{code:MISSING_API_KEY,message:X-API-Key header is required}没传 key 或 key 为空检查X-API-Keyheader 是否正确传入大小写敏感HTTP 429超过 rate limitSearch 30 req/min、Fetch 150 URL/min加time.sleep()控速request_id在错误响应里端点存在但业务逻辑拒绝用request_id找 TinyFish 客服排查domain_typeresearch_paper忽略recency_minutes官方设计改用pub_year_min/pub_year_maxFetch 返回errors: [{...}]某个 URL 抓取失败检查 URL 是否可访问、是否被反爬Agent 返回 timeout多步操作超时默认几十秒用run-sse流式看进度或拆分 goal十、成本速算按场景假设你的 Agent 每天需要搜索 100 次 抓取 200 页 简单交互 10 次。方案月成本全部用 SerpAPI Tavily 自建 Playwright~$350TinyFish Search免费 Fetch免费 Agent按量主要花 Agent 端点月成本 $10通过 Monid 接入Monid 也免费同 TinyFish关键结论免费端点承担 95% 的日常需求只有复杂交互才落到付费 Agent 端点。十一、小结TinyFish 实战下来最直观的感受是把给 Agent 用的网页基础设施做成了一个免费 API门槛极低——curl 一行就能搜、一行就能抓。真正需要付费的是复杂的多步交互场景但那也是按次计费、用多少付多少不存在月度订阅绑定的问题。如果你已经在用 Agent 框架Claude Code、Codex、Cursor 等最省事的接入方式是MCP 直连第五个 demo零本地进程、零代码改动。报告完 · Happy Browsing!重要说明本文所有 demo 代码均为完整可运行版本但未用真实 API key 实测本机无 key需读者本人注册。关键 API 返回结构引自 TinyFish 官方文档docs.tinyfish.ai端点存活性已在上一篇文章用 curl 验证401 request_id。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进