README 扫描 404,public-apis 维护者用 TaoToken 跑 Agent 清理

发布时间:2026/9/18 23:38:50
README 扫描 404,public-apis 维护者用 TaoToken 跑 Agent 清理 1. 从 README 扫描的 404/410 开始先复现再让 Agent 分类public-apis 的 README 链接扫描里出现 404/410 混着 403/429我先在本地复现扫描再把 TaoTokenhttps://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentreadme_scan_404_intro接入 Agent 工作流让它生成分类表和 Issue 草稿。这个流程不是一上来就删条目而是先把“哪些链接真的死了、哪些只是扫描环境误伤”拆清楚。作为公共 API 目录的维护者最怕两件事一是把还能用的服务误删二是把已经迁移的链接继续留在 README 里。前者影响贡献者信心后者会让使用者按旧入口踩坑。社区扫描报告里有一批链接返回 404 或 410同时又有 403、429、超时混在一起。404 通常代表资源不存在410 更明确表示资源被永久移除但 403 可能是 Cloudflare 或 WAF 拦截429 是频率限制超时可能只是网络抖动。如果把这些状态统一当成“死链”清理建议就会失真。所以我给自己定的顺序是本地复现扫描、按状态分层、让 Agent 读本地 CSV 做分类、人工复核后生成 Issue 草稿、最后才考虑替换或移除条目。这里的目标不是写一个一次性脚本而是产出一套可复核的证据链。最终至少要留下三类东西一张 404/410 分类表一份可以直接贴进 Issue 的草稿以及一组可重复执行的重试命令。Agent 在这条链路里只做重复的分类、摘要、草稿组织不直接改主分支也不直接对线上目录做写操作。2. 本地复现把 404/410 与 403/429/超时拆成两条队列第一步是复现 README 链接扫描。public-apis 的 README 里链接数量很多分类也多手工点不现实。我一般会用一个本地 Python 脚本先抓取 Markdown 链接再并发请求。关键点不是“并发越高越好”而是把 HEAD、GET、重定向、超时、UA、重试次数都记录下来方便后面判断。下面是一个可以按需修改的扫描脚本骨架。它只读取本地 README不会连接任何生产数据库也不会修改仓库文件。import csv import re import time import argparse from concurrent.futures import ThreadPoolExecutor, as_completed from urllib.parse import urljoin, urlparse import requests LINK_RE re.compile(r\[[^\]]\]\((https?://[^)\s])\)) def extract_links(readme_path): links [] with open(readme_path, r, encodingutf-8) as f: for line_no, line in enumerate(f, 1): for match in LINK_RE.finditer(line): url match.group(1).rstrip().,;) links.append({line: line_no, url: url}) return links def check_one(url, timeout15, retry1, uaNone): headers {User-Agent: ua or public-apis-link-audit/1.0} last_error redirect_chain [] for attempt in range(retry 1): try: resp requests.head( url, allow_redirectsTrue, timeouttimeout, headersheaders, ) if resp.status_code in (403, 405, 429) or resp.status_code 500: resp requests.get( url, allow_redirectsTrue, timeouttimeout, headersheaders, streamTrue, ) redirect_chain [r.url for r in resp.history] return { url: url, status: resp.status_code, final_url: resp.url, redirect_chain: - .join(redirect_chain), error: , } except requests.RequestException as exc: last_error str(exc) time.sleep(1 attempt) return { url: url, status: 0, final_url: , redirect_chain: , error: last_error, } def classify(row): status row[status] if status in (404, 410): return dead if status in (301, 302, 307, 308): return redirect if status in (403, 429) or status 0: return retry if status 200: return ok return other def main(): parser argparse.ArgumentParser() parser.add_argument(--readme, defaultREADME.md) parser.add_argument(--out, defaultlink_scan.csv) parser.add_argument(--timeout, typeint, default15) parser.add_argument(--retry, typeint, default1) args parser.parse_args() links extract_links(args.readme) rows [] with ThreadPoolExecutor(max_workers12) as pool: futures { pool.submit( check_one, item[url], args.timeout, args.retry, ): item for item in links } for future in as_completed(futures): item futures[future] result future.result() result[line] item[line] result[bucket] classify(result) rows.append(result) rows.sort(keylambda r: (r[bucket], r[url])) fields [line, bucket, status, url, final_url, redirect_chain, error] with open(args.out, w, newline, encodingutf-8) as f: writer csv.DictWriter(f, fieldnamesfields) writer.writeheader() writer.writerows(rows) print(fscanned{len(rows)} out{args.out}) if __name__ __main__: main()运行时我一般会分两轮第一轮快速扫描第二轮只重试可疑状态。python check_links.py \ --readme README.md \ --out link_scan_round1.csv \ --timeout 12 \ --retry 1 python check_links.py \ --readme README.md \ --out link_scan_round2.csv \ --timeout 25 \ --retry 3然后按 bucket 分层。404/410 进入死链队列403/429/超时进入重试队列301/302 进入跳转队列200 进入存活队列。这里不要急着下结论同一个 URL 在round1 返回 429在round2 返回 200说明它可能只是限流同一个 URL 两次都返回 404才更接近真实死链。分类规则可以固定成下面这张表后面让 Agent 读 CSV 时也按这个规则输出。bucket常见状态含义处理动作dead404、410资源不存在或永久移除进入清理建议人工确认替换或移除redirect301、302、307、308域名或路径迁移保留 final_url复核新地址内容retry403、429、0拦截、限流、超时单独重试不直接判死ok200当前可访问进入存活池后续复核字段other其他 4xx/5xx权限、服务端异常等人工打开文档确认这一轮做完至少能得到link_scan_round1.csv和link_scan_round2.csv。这两个文件是后面 Agent 分类的输入。没有这两份 CSVAgent 生成的清理建议就只能靠猜这对公共目录维护来说风险太高。3. 接入 TaoTokenKey、Base URL、Claude Code / Codex / CC Switch 配置扫描结果有了接下来才是让 Agent 介入。Agent 适合做重复的归类、去重、生成 Markdown 草稿但不适合在没有证据的情况下直接判断链接该不该删。所以我在生成清理建议前会先去 TaoToken 拿 Key再把工具侧配置改成 TaoToken 的 Base URL。入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentreadme_scan_404_key 创建 Key 的页面是 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentreadme_scan_404_key 。配置时记住两条工具配置里的 Base URL 用https://taotoken.net/api这个地址不加 UTMAPI Key 用占位符YOUR_API_KEY时记得替换成自己的真实 Key。不同工具的字段不一样不要把 Claude Code 的ANTHROPIC_*环境变量套到 Codex 上。Claude Code 可以用settings.json配置。下面是我常用的写法放在用户级或项目级配置里都可以按自己的使用范围选择。{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: YOUR_API_KEY, ANTHROPIC_MODEL: claude-sonnet-4-5 } }如果不喜欢写settings.json也可以在 shell 里临时导出环境变量。这个方式适合先验证链路。export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_AUTH_TOKENYOUR_API_KEY export ANTHROPIC_MODELclaude-sonnet-4-5 claudeCodex 不要用ANTHROPIC_*它走的是config.toml。下面是一个示例结构重点是base_url和env_key。model gpt-5 model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api responses对应的环境变量单独导出export TAOTOKEN_API_KEYYOUR_API_KEY如果你用 CC Switch 管理多个工具配置可以把它理解成三件套Provider 名称、Base URL、API Key。填成下面这样再在需要的时候切换 profile。{ provider: TaoToken, base_url: https://taotoken.net/api, api_key: YOUR_API_KEY }配置完成后不要急着跑大任务先用一个最小命令确认环境变量已加载test -n $TAOTOKEN_API_KEY echo TAOTOKEN_API_KEY is loaded test -n $ANTHROPIC_AUTH_TOKEN echo ANTHROPIC_AUTH_TOKEN is loaded如果是 Claude Code能正常启动并返回模型响应就说明ANTHROPIC_BASE_URL和ANTHROPIC_AUTH_TOKEN生效了。如果是 Codex就检查config.toml里的 provider 是否指向taotoken以及TAOTOKEN_API_KEY是否在当前 shell 可见。多工具并存时最容易出问题的不是 Key而是 profile 串了Claude Code 用 Claude Code 的变量Codex 用 Codex 的变量CC Switch 只做切换不要混写。4. Agent 分类表404、410、跳转、软 404、Cloudflare 干扰Agent 介入的第一步不是“给我清理建议”而是“先按本地 CSV 生成分类表”。这一步我会把输出限定成三个文件triage.md、issue_draft.md、retry_commands.sh。Prompt 也要写清楚边界只读本地文件不访问线上生产库不直接改 README 主分支不删除条目。下面是我常用的 Prompt 模板可以直接改成你自己的工作目录结构。你是 public-apis 的链接维护助手。只读取本地 link_scan_round1.csv 和 link_scan_round2.csv。 不要访问线上生产数据库不要直接修改 README 主分支。 按以下规则生成 Markdown 分类表 1. 404/410 且两轮一致dead_confirmed 2. 404/410 但两轮不一致dead_need_retry 3. 301/302/307/308redirect_need_review 4. 403/429/timeoutretry_queue 5. 200alive 输出三个文件 - triage.md分类表包含 line、bucket、status、url、final_url、redirect_chain、error、suggested_action - issue_draft.mdIssue 草稿包含扫描环境、命令、统计、404/410 明细、建议动作 - retry_commands.sh只包含可本地执行的重试命令 不要编造未在 CSV 中出现的 URL。 不要直接给出“删除”结论统一写成“建议移除 / 建议替换 / 需要人工确认”。Agent 输出分类表时我要求它至少覆盖下面这些类别。这样人工复核时能快速看到哪些是确定死链哪些只是扫描环境造成的假阳性。分类判定依据建议动作是否可自动修复dead_confirmed两轮均为 404/410且无有效跳转建议替换或移除否需人工确认dead_need_retry一轮 404/410另一轮超时或 429进入重试队列否redirect_need_review301/302 到新地址复核新页面后替换可能是retry_queue403/429/timeout换 UA、降并发、延长超时后重试否soft_404HTTP 200但页面出现 Not Found人工打开确认否alive两轮均 200保留复核 Auth/HTTPS/CORS不需要这里特别要提防软 404。有些站点迁移后没有正确返回 404而是返回 200 的错误页。只看状态码会误判为存活。解决办法是让 Agent 在分类时同时保留 HTML 标题或页面摘要但这一步只作为线索最终仍要人工打开确认。另一个干扰是 Cloudflare。403 和 429 经常出现在扫描器 UA 被拦截、请求过快、目标站点防护策略较严时这类链接不能和 404/410 一起处理。分类表生成后我一般会做一次抽查随机抽 10 条 dead_confirmed手动打开 final_url 和原始 URL看状态是否一致再抽 10 条 retry_queue用更长超时和普通浏览器 UA 重试。抽查通过后才进入 Issue 草稿阶段。5. Issue 草稿与重试命令让清理建议可复核Issue 草稿不是“结果通知”而是“可复核报告”。它要写清楚扫描时间、工具版本、命令、并发数、超时、UA、重试次数以及 404/410 的分类统计。这样其他维护者才能判断你的结论是否可信。下面是一个可以直接改的草稿模板。## README 链接扫描404/410 分类与清理建议 ### 扫描环境 - 工具本地 check_links.py - 输入README.md - 超时12s / 25s 两轮 - 并发12 - UApublic-apis-link-audit/1.0 - 重试第一轮 1 次第二轮 3 次 ### 扫描命令 bash python check_links.py --readme README.md --out link_scan_round1.csv --timeout 12 --retry 1 python check_links.py --readme README.md --out link_scan_round2.csv --timeout 25 --retry 3统计bucket数量处理建议dead_confirmed待填人工确认后替换或移除dead_need_retry待填进入重试队列redirect_need_review待填复核后替换 final_urlretry_queue待填换 UA、降并发后重试alive待填保留复核字段404/410 明细line条目状态原始 URLfinal_url建议待填待填404待填待填建议替换/移除重试命令python check_links.py --readme README.md --out retry_404_410.csv --timeout 30 --retry 2备注本结果来自本地扫描不代表目标服务永久不可用。403/429/超时未计入 404/410。替换链接前需复核 Auth、HTTPS、CORS 字段。注意草稿里的命令要能直接执行路径和文件名保持一致。重试命令建议单独放一个 retry_commands.sh不要和扫描脚本混在一起。下面这组命令适合对 404/410 和 retry_queue 做二次确认。 bash # 只重试第一轮中的 404/410拉长超时并降低并发 python check_links.py \ --readme README.md \ --out retry_404_410.csv \ --timeout 30 \ --retry 2 # 对单个可疑 URL 做 curl 复核保留响应头 curl -I -L \ --max-time 30 \ --retry 2 \ -A Mozilla/5.0 (compatible; public-apis-link-audit/1.0) \ https://example.com/old-path \ -o headers.txt \ -w status%{http_code} final%{url_effective}\n # 对 403/429 做温和重试避免把限流打成封禁 sleep 5 curl -I -L \ --max-time 30 \ -A Mozilla/5.0 (compatible; public-apis-link-audit/1.0) \ https://example.com/rate-limited \ -w status%{http_code}\n重试时不要并发太高尤其是目标站点已经有 429 的情况下。我的经验是404/410 可以并发稍高403/429/超时必须降速。重试结果也要回写 CSV合并成最终分类表。Agent 可以帮忙合并去重但不要让它替你决定“删不删”。最终建议统一写成“建议移除 / 建议替换 / 需要人工确认”留出人工复核空间。6. 链接修复后复核 Auth、HTTPS、CORS不要只看 200在 public-apis 这类目录里链接存活不等于条目可用。每个条目除了名称和说明还有 Auth、HTTPS、CORS 三列。404 链接被替换后新地址可能仍然可用但鉴权方式、加密支持、跨域策略可能已经变了。如果只把 URL 换成 final_url却不同步这三列目录质量还是会下降。比如一个原本标记为Auth: No的天气接口迁移后可能需要apiKey一个原本HTTPS: Yes的地图服务新文档站可能只提供 HTTP一个原本CORS: Yes的前端可用接口新域名可能返回CORS: No浏览器页面就会跨域失败。这些问题不会在 404 扫描里暴露但会在使用者真正接入时暴露。所以我的复核清单是字段复核问题处理方式Auth新地址是否仍免鉴权需要 Key 就改成 apiKeyOAuth 就改成 OAuthHTTPS新地址是否支持 HTTPS不支持则降级标记或更换候选CORS浏览器端是否可跨域No 表示只适合服务端Unknown 需实测文档新地址是否是官方文档营销页、登录页不能直接替代文档免费层是否仍有免费额度回到官方文档确认不凭旧印象这一步可以让 Agent 帮你生成复核清单从最终分类表里筛出redirect_need_review和dead_confirmed中“建议替换”的条目按分类分组输出需要人工打开的 URL 列表。但打开页面、确认字段、修改 README 仍然由维护者完成。Agent 的产出是待办列表和草稿不是最终结论。如果你在本地已经用 TaoToken 配好了 Agent可以让它把分类表、Issue 草稿、重试命令和字段复核清单合并成一个工作目录。这样下一次扫描时只需要替换 CSV 输入就能复用同一套 Prompt 和模板。对于公共目录维护来说可重复比一次性清理更重要。7. 从模型对话到 Claude Code 文档最小接入闭环如果你也想把这套 README 扫描、分类、Issue 草稿流程跑起来可以先从最小闭环开始用模型对话验证分类 Prompt再决定是否接入 Coding Plan然后创建 API Key最后按 Claude Code 文档把工具侧配置接好。这样每一步都有可验证的结果不会一上来就改一堆配置。模型对话入口 https://taotoken.net/models/detail/chat?utm_sourcetaotoken_aicg_blog_endutm_contentreadme_scan_404Coding Plan 入口 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentreadme_scan_404创建 API Key https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentreadme_scan_404Claude Code 文档 https://taotoken.net/doc/ClaudeCodeAnthropic?utm_sourcetaotoken_aicg_blog_endutm_contentreadme_scan_404官网入口 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentreadme_scan_404_cta配置时再提醒一次Base URL 用https://taotoken.net/api这个地址不要加 UTMKey 用YOUR_API_KEY占位真实 Key 不要提交到仓库Claude Code、Codex、CC Switch 的字段分开写不要混用ANTHROPIC_*和 Codex 的config.toml。先把本地扫描跑通再让 Agent 读 CSV 生成分类表最后用人工复核后的结果去写 Issue 草稿。这样处理 README 里的 404/410既不会误伤可用条目也能让清理建议有据可查。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询