> Adapted from Panniantong/Agent-Reach agent_reach/skill/SKILL.md by Panniantong (MIT License). 路由思想等价,全文重写并本地化;去除其 CLI/OpenCLI 依赖,仅保留零 Key 免费通道,通道全部改为 curl/Python 标准库可直接执行的形式。
网络触达手册 · 零 Key 互联网取材路由
你的任务是把"网上的内容"变成"能读的文本"。每个平台优先走零成本、免登录、免 API Key 的通道;通道失效时按重试链降级,不要瞎猜。
常驻纪律
- 动手前声明通道:开头说一句「使用 XX 通道读取 XX」,便于失败后回溯。
- 临时文件只写
/tmp/或系统临时目录,不污染工作区;持久数据放用户指定位置。 - 取材只读不写:本手册只负责"读互联网",发帖/评论/登录态写操作一律不做。
- 失效降级,不硬重试:同一通道连续失败 2 次即切换重试链下一级。
- 多平台调研:并行收集(多个 curl/python 子任务),先取材后汇总,不要边读边下结论。
路由表
| 取材需求 | 首选通道 | 降级链 |
|---|---|---|
| 任意网页正文 | r.jina.ai | 直抓 HTML 剥标签 → 换 UA 重试 |
| 通用搜索 | DuckDuckGo HTML 版 | Bing 网页版 → 换关键词重试 |
| YouTube 字幕 | youtube-transcript 接口 | yt-dlp 自动字幕 |
| RSS/Atom | Python feedparser 或手写 XML 解析 | 原始 XML 正则提取 |
| GitHub 仓库/代码 | GitHub REST API(匿名 60 次/时) | raw.githubusercontent 直连 → ghfast.top 镜像 |
| V2EX | 官方 JSON API | HTML 页面 |
| Hacker News | Algolia HN API | 官方 Firebase API |
| arXiv 论文 | arXiv export API | 摘要页直抓 |
各通道速查
1. 任意网页 → 正文
# 首选:Jina Reader,返回干净 Markdown(限流宽松,免 Key)
curl -sL "https://r.jina.ai/https://example.com/article"
# 降级:直抓 HTML 剥标签(标准库,无依赖)
import urllib.request, re, html
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
raw = urllib.request.urlopen(req, timeout=30).read().decode("utf-8", "ignore")
raw = re.sub(r"<(script|style)[\s\S]*?</\1>", "", raw, flags=re.I)
text = html.unescape(re.sub(r"<[^>]+>", " ", raw))
print(re.sub(r"\s+", " ", text)[:5000])
2. 通用搜索
# DuckDuckGo HTML 版(免 Key,注意带 UA,否则 403)
curl -sL "https://html.duckduckgo.com/html/?q=关键词" \
-H "User-Agent: Mozilla/5.0" | grep -oE 'result__a[^>]*>[^<]+|uddg=[^"&]+'
要点:结果 URL 在 uddg= 参数里 URL 编码,需 urllib.parse.unquote 解码。
3. YouTube 字幕
# 首选:timedtext 接口(免 Key;video_id 从 watch?v= 或 youtu.be/ 提取)
import urllib.request, re
v = "VIDEO_ID"
xml = urllib.request.urlopen(
f"https://www.youtube.com/api/timedtext?lang=zh&v={v}", timeout=30
).read().decode("utf-8", "ignore")
if not xml.strip(): # 中文无字幕,试英文或自动生成
xml = urllib.request.urlopen(
f"https://www.youtube.com/api/timedtext?lang=en&v={v}", timeout=30
).read().decode("utf-8", "ignore")
text = re.sub(r"<[^>]+>", "", xml)
降级:yt-dlp --write-auto-sub --skip-download --sub-lang zh,en "URL"。
注意:timedtext 接口偶发空响应——先试 lang=zh 再 lang=en,都空则直接切 yt-dlp,不要原地重试。
4. RSS / Atom
# 标准库解析(无 feedparser 时)
import urllib.request, re
xml = urllib.request.urlopen(rss_url, timeout=30).read().decode("utf-8", "ignore")
items = re.findall(r"<item[\s\S]*?</item>|<entry[\s\S]*?</entry>", xml)
for it in items[:10]:
title = re.search(r"<title>(?:<!\[CDATA\[)?([\s\S]*?)(?:\]\]>)?</title>", it)
link = re.search(r"<link[^>]*href=\"([^\"]+)\"|<link>([^<]+)</link>", it)
print(title.group(1) if title else "?", "->", (link.group(1) or link.group(2)) if link else "?")
5. GitHub
# 仓库信息 / 文件树 / raw 文件(匿名限 60 请求/小时,够用)
curl -s "https://api.github.com/repos/<owner>/<repo>"
curl -s "https://api.github.com/repos/<owner>/<repo>/git/trees/main?recursive=1"
curl -sL "https://raw.githubusercontent.com/<owner>/<repo>/main/<path>"
# raw 直连失败时走镜像(国内网络常用)
curl -sL "https://ghfast.top/https://raw.githubusercontent.com/<owner>/<repo>/main/<path>"
# 代码搜索必须带认证或用 gh CLI
gh search repos "query" --sort stars --limit 10
6. V2EX
curl -s "https://www.v2ex.com/api/topics/hot.json" -H "User-Agent: agent-reach/1.0"
curl -s "https://www.v2ex.com/api/topics/show.json?node_name=python" -H "User-Agent: agent-reach/1.0"
7. Hacker News
curl -s "https://hn.algolia.com/api/v1/search?query=关键词&tags=story" # 按相关度
curl -s "https://hn.algolia.com/api/v1/search_by_date?query=关键词&tags=story" # 按时间
curl -s "https://hacker-news.firebaseio.com/v0/item/<id>.json" # 单条详情
curl -s "https://hacker-news.firebaseio.com/v0/topstories.json" # 热榜 ID 列表
8. arXiv
curl -s "http://export.arxiv.org/api/query?search_query=all:关键词&max_results=10"
返回 Atom XML,<summary> 为摘要、<id> 为论文页。
平台边界
- 登录态平台(Twitter/X、Reddit、小红书、B站风控内容、微信公众号文章):零 Key 通道基本不可用。有专门 skill 或浏览器自动化工具(如 agent-browser)时优先用它们;没有就明确告知用户"该平台需登录态,本通道不可达",不要伪造结果。
- 付费 API 平台:不引入任何需要付费 Key 的通道。用户自有 Key 时由用户明确提供,本手册不默认假设。
- 反爬站:先换 UA,再降级到搜索引擎 site: 查询取快照,不要高频重试。
失败自检清单
取材失败时按顺序检查:① 通道是否需要 UA / Referer;② 是否被限流(换通道而非等待);③ URL 是否需要编码(中文关键词用 urllib.parse.quote);④ 国内网络下 raw/api 域名是否被断连(切镜像);⑤ 内容是否本来就是 JS 渲染(改用浏览器自动化或 Jina Reader)。