从关停公告到 24342 条数据:AI 时代的逆向工程实录
2026 年 4 月 2 日,M 平台宣布永久关停。
DNS 指向
0.0.0.0,网站变成一封告别信,看似一切都结束了。但我不信。昨天才关站,不可能那么彻底。没有不透风的墙。
接下来的 5 个小时里,我和 Claude Code 从存档站、企业官网、新站 API、关联 CloudFront 域名四条线索层层深入,破解 HMAC-SHA1 签名和 AES-256-CBC 加密,最终从零恢复出 24,342 条完整视频数据。
这个过程让我深刻体会到一件事:在 AI 时代,技术能力固然重要,但真正决定成败的,是思维的灵活性。
写在前面:AI 时代,思维比技术更重要
这篇文章记录的不仅是一次技术逆向,更是一次人机协作的思维实验。
整个过程中,Claude 负责了几乎全部的技术执行——下载、分析 JS、破解签名、解密数据、写入数据库。但每一次关键突破,都来自人的判断和直觉:
- 当 AI 说"只有 49 条数据",我说"不够,换个方向试试"
- 当 AI 说"只有一个公开接口",我说"不信,昨天才关站不可能这么干净"
- 当 AI 说"到头了",我说"回去翻翻存档页面里的域名"
AI 是你手中最锋利的刀,但往哪里切,切多深,什么时候该换把刀——这些决策永远是人做的。
传统逆向工程需要精通汇编、密码学、协议分析,门槛极高。但在 AI 时代,这些技术细节可以交给 AI 处理。真正稀缺的能力变成了:
- 不满足于表面答案的追问精神 —— 每次"到头了"都可能只是视角不够
- 跨领域连接线索的能力 —— 存档 HTML 里的一个广告域名,最终指向了完整的内容库
- 知道什么时候该相信直觉 —— "昨天才关站不可能那么彻底"这个判断,价值 24000 条数据
所以,如果你读完这篇文章只记住一件事,我希望是这个:
AI 时代,思维和想法的灵活性至关重要。工具会越来越强,但驾驭工具的人,需要的是敏锐的嗅觉、不服输的韧劲、以及"再试一下"的勇气。
好了,进入正文。
目录
- 对话实录:从镜像到破解的完整对话
- 数据总览
- 第一阶段:存档站镜像——先把尸体保存下来
- 第二阶段:mod.run 企业官网——从门面里扒数据
- 第三阶段:madou.com 新站——DNS 已死,Cloudflare 犹存
- 第四阶段:CloudFront 金矿——一个域名引发的 24000 条数据
- 技术总结
- 最终成果与感悟
对话实录:从镜像到破解的完整对话
以下是整个过程中的真实对话。你会看到一个有趣的模式:AI 反复得出"到此为止"的结论,而人反复用直觉和追问推翻这个结论。 四次"到头了",四次被打脸,每一次都打开了新世界的大门。
第 1 轮:起点——"帮我复刻这个存档站"
我: 我想快速复刻一个网页 是存档站 web.archive.org/web/2026020… 有啥好方案,我想到的是反向代理的方式
一开始的想法很朴素:站要关了,先把页面存下来。Claude 对比了 wget、反向代理、wayback_machine_downloader、monolith 四种方案。
我: 你推荐哪个
我: 那你试一下
Claude 自动检查 Ruby 环境、安装 gem、执行下载。8 分半后,196 个文件落地。
我: 帮我起来 我看看 端口搞个冷门的
本地服务跑起来,打开一看——满屏 404,CSS/JS/SVG 全丢了。wayback_machine_downloader 只下载了 HTML,没拉静态资源。
我: 没有css样式 css svg 全是404的
Claude 从 HTML 里 grep 出 54 个静态资源路径,批量补全。又发现 CSS 里嵌着 Wayback 的 URL 前缀(/web/20260219094859im_/https://madou.com/...),修了 33 处。又补下载了 23 张图片。来来回回折腾了三轮。
我: 完美
到这里,本地镜像算是完整了。但我不满足于静态页面——
我: 他这个存档的都是静态的吧 但是实际是有接口的吧 你看看
这是第一次追问。 存档站只有 HTML,但原站肯定有 API。数据在哪?
Claude 分析了 JS 文件,发现原站是 SSR 直出的,客户端几乎没有 API 调用。视频播放用 DPlayer + HLS,但 m3u8 链接带时效 token,早就失效了。
第一条路,走到头了。
第 2 轮:另辟蹊径——"我在另一个站发现了接口"
我: 因为这个是没有api的 然后我在另一个站发现的api接口
curl 'https://mod.run/api/app/media/detail' --data-raw '{"mediaId":1184759}'你看看能不能分析一下类似的接口 有没有list之类的
这就是思维灵活性的第一个体现:原站没有 API?那换个站找。 mod.run 是 M 平台的企业官网,也许有数据接口。
Claude 下载 Nuxt.js bundle,从 minified JS 中硬扒出 6 个 API 定义。逐个测试:navi/infoV2 返回首页数据,config 暴露了 CDN 地址 https://cdnimg.v21c.com/。但没有 list 接口,只能通过 media/detail 按 ID 逐个查。
我: 你试试这个里面的id是否一样呢 /Users/haose/Movies/tdl/madou/channel.json
我手里还有一张牌——官方 TG 频道的消息记录。629 条消息,296 个编号。但一比对,TG 频道的编号 ID、madou.com 的存档 ID、mod.run 的 mediaId,三套体系完全不兼容。
第 3 轮:暴力扫描——用蛮力换数据
我: mod.run 的数据不全,如果暴力扫描可以吗 head请求不是会快吗 而且不用全量扫描吧 目前已知的mediaId在他们的上下多少范围内去扫描呢 比如每个mediaId的上下1000个
既然没有 list,那就暴力枚举。Claude 算出 4 个 ID 集群、13124 个待扫描 ID。
先用我自研的 hs-net 库开 30 并发——秒被 403。降到 5 并发加延迟——还是被封连接。最后老老实实用 Python urllib 单线程、每个请求间隔 0.5 秒,像蚂蚁搬家一样逐个验证。
结果出来了:49 条有效视频。 百万级 ID 范围里只有 49 条。mod.run 就是个企业展示站,放了几十条精选片段而已。
我: 保存的文件里面 图片的域名写进去 cdnimg.v21c.com
我: 域名视频的域名是 mod.run/api/app/med…...
数据虽然少,但每一条都得存完整。逐步补全字段。
第 4 轮:浏览器抓包——用户主动出击
我: 你看看 madou.com/assets/inde… 我发现是有 madou.com 的api的 madou.com/api/stat/la… 触发页面是 madou.com/mobile/vide…
我:
curl 'https://madou.com/api/stat/landPageConfig/getByType' --data-raw '{"appId":888,"pageNum":1,"pageSize":10,"type":2}'
这是人机协作的经典场景:AI 负责分析代码,人负责在浏览器里观察行为。 我在 Chrome DevTools 里抓到了新站的 API 请求,连 appId=888 这个关键参数都直接给了。
返回 68 条视频。Claude 从 Wayback Machine 获取 JS chunk,确认整个新站只导出了这一个 API 调用。
我: 你对比一下 两个加一起去重后是多少个
mod.run 48 + madou.com 68 = 116 个编号,零重叠。两个站的内容库完全互补——mod.run 偏老片,madou.com 偏新片。但 TG 频道有 212 个编号,API 只覆盖了 38.7%。
还有 61.3% 的数据不知道在哪。
第 5 轮:到头了?——"我不信"
我: 你在翻翻新站的js看看是否有其他的接口
Claude 下载了所有 Vite chunk,确认只有一个 API。
Claude 的结论: "madou.com 新站就这一个数据接口,68 条就是全部了。"
我: 真的没办法了吗 我不信,没有不透风的墙,昨天才关站不可能那么彻底 肯定还是我们没有找到的线索
这句话是整篇文章的转折点。 也是我想传达的核心理念的最好注脚——AI 给出的"结论",往往只是当前视角下的最优解。换一个视角,整个局面可能完全不同。
AI 说到头了。但我的直觉告诉我:一个运营了多年的平台,昨天才关站,不可能只留下 116 条数据。数据一定还在某个地方,只是我们没找到入口。
Claude 被这句话"激活"了,开始重新审视所有线索:回到 mod.run 的 config 接口,提取出一串关联域名——mdapp12.com、mdbba02.com、ge.dfg3t534.cc、admin.qsxon.com,以及多个 CloudFront 域名。
第 6 轮:DNS 已死,但 Cloudflare 没死
我: 你顺着 madou.com/pc/video 往下找 不要找 madou.com/ 的
Claude 发现 madou.com DNS 已指向 0.0.0.0——站确实关了。但灵机一动,试了 --resolve madou.com:443:104.21.0.0 绕过 DNS,直连 Cloudflare 边缘节点——居然还在响应!
更刺激的发现:扫描后端路由,30+ 个 API 接口全部存在,只是返回 {"msg":"no token"}。这是一个完整的 Go CMS 系统——media、actor、category、tag、banner,应有尽有。数据就在里面,只是锁着。
我: 有注册吗
没有。注册接口也在 token 中间件后面。
我: 你试一下登陆呢
我: 试一下 试一下
Claude 探测到 admin/login 字段是 account + password,还发现接口会告诉你"该账号不存在"(用户枚举漏洞)。但 admin、test、demo、madou 全部不存在。管理员用的是自定义账号名。
这条路,又卡住了。
第 7 轮:回头看——存档 HTML 里的宝藏
我: 应该会有公开的接口的啊
又一次追问。 这次 Claude 换了个方向——回到最初下载的 196 个存档 HTML 页面,grep 出所有外部域名。
在一堆广告链接和 CDN 地址中间,藏着 7 个 CloudFront 域名。其中一个 de1j8jm5ajr3l.cloudfront.net——返回了一个活着的站点。
标题叫 "B站点"。
这不是 M 平台,但下载它的 JS bundle(487KB)后发现——160+ 个 API 接口,跟 mod.run 同一套后端系统! 而且包含了完整的签名密钥和加密配置:
const Vn = {
http_request_key: "jR6dO6fT1yD9zY7u", // 就这样明文写在前端 JS 里
http_response_key: "vEukA&w15z4VAD3kAY#fkL#rBnU!WDhN",
guest_skey: "wM5wK1jP3lK7pS2t",
};
一个存档页面里的广告域名,最终指向了 24000 条数据。 这就是为什么说"存档 HTML 是线索金矿"。
接下来是纯技术活:破解 HMAC-SHA1 签名让请求通过验证,破解 AES-256-CBC 把加密的响应解开。签名算法从 JS 里直接抄,解密算法最大的坑是 JS 的 Array.splice() 会修改原数组——密钥派生过程中 6 次 splice,必须精确追踪每一步的数组状态。
游客登录被禁了("账户禁止登陆"),但 Claude 逐个测试接口权限,发现 media/home 不需要登录就能访问:
api_call("/api/app/media/home", {"id": 1}) # → 2707 条!
api_call("/api/app/media/home", {"id": 2}) # → 12327 条!! 原创影视!
从 116 条到 24726 条。翻了 213 倍。
第 8 轮:全量入库——"我全都要"
我: 可以都要吗 我全都要 保存的时候不混在一起就行,如果不好存的话 我本地有redis 你可以存 不存0 1库就行
我: docker 里面的
6 个分类全量拉取,Redis db=2 存原始 JSON。
我: 这会你看看 M 平台的视频一共有多少个 或者你存数据库也行 docker里面有个tidb 127.0.0.1 4000 你新建个库
TiDB 建库建表,24,342 条入库。其中 M 平台编号 194 条。
我: 还是宝贝厉害
对话数据统计
| 指标 | 数值 |
|---|---|
| 人类发送的消息 | ~30 条 |
| 关键转折性指令 | 5 条 |
| Claude 读取的文件 | 200+ 个 |
| Claude 执行的命令 | 300+ 条 |
| Claude 下载的 JS bundle | 8 个 |
| 被限流/封禁次数 | 3 次 |
| 说"到头了"被打脸次数 | 4 次 |
5 条改变走向的关键指令
| # | 指令 | 背后的思维 | 效果 |
|---|---|---|---|
| 1 | "我在另一个站发现的api接口" + curl | 原站没数据?换个入口 | 打开 mod.run 数据源 |
| 2 | appId=888 的 curl 命令 | 浏览器抓包,人机配合 | 直接拿到新站 API |
| 3 | "我不信,没有不透风的墙" | 拒绝接受"到头了" | 数据量翻 213 倍 |
| 4 | "应该会有公开的接口的啊" | 不死心,继续推 | 找到 CloudFront 金矿 |
| 5 | "我全都要...本地有redis...docker里的tidb" | 明确需求 + 提供基础设施 | 快速入库 |
注意第 3 条:这不是一条技术指令,而是一个信念。 它没有告诉 AI 该做什么,但它改变了 AI 的搜索方向。这就是人在 AI 协作中最核心的价值——判断和决策。
数据总览
| 指标 | 数值 |
|---|---|
| 对话总时长 | 约 4-5 小时 |
| 数据来源 | 5 个(Wayback Machine、mod.run、madou.com、CloudFront、TG 频道) |
| 破解的加密算法 | 2 个(HMAC-SHA1 签名、AES-256-CBC 响应加密) |
| 发现的 API 接口 | 160+ 个 |
| 最终获取的视频数据 | 24,342 条 |
| 提取的M 平台编号 | 179 个 |
| 存储 | Redis + TiDB |
数据量的戏剧性变化
存档站 HTML 页面 : 196 条
mod.run API : 49 条 ← AI:"这就是全部了"
madou.com 新站 API : 68 条 ← AI:"确实只有这一个接口"
三源合计去重 : 116 个编号 ← AI:"公开能拿的到头了"
↓
"我不信,没有不透风的墙"
↓
CloudFront 域名发现 :24,342 条 ← !!!
每一次说"到头了",都被打脸。 但说到底,不是 AI 错了——在当时的信息下,它的判断是合理的。是人的"不合理的坚持"打开了新的可能性。
第一阶段:存档站镜像——先把尸体保存下来
站要关了,第一反应是保存。就像火灾现场,先抢救能抢救的。
方案选择
| 方案 | 优点 | 缺点 |
|---|---|---|
| wget mirror | 简单粗暴 | Wayback URL 重写混乱 |
| 反向代理 | 动态,不用下载 | 依赖 archive.org |
| wayback_machine_downloader | 专为 Wayback 设计,自动还原 URL | 需要 Ruby |
一条命令搞定:
wayback_machine_downloader http://madou.com/ --from 20260209 --to 20260210 -d ./site
踩坑与修复
下载的 196 个 HTML 页面只是骨架。补全经历了三轮:
- 静态资源缺失 → grep 出 54 个路径,批量从 Wayback Machine 下载
- Wayback 注入代码 → JS/CSS 被包了一层
wombat运行时,Python 脚本批量清理 - CSS 中的 URL 前缀 →
/web/20260219094859im_/https://madou.com/static/...正则替换为/static/...
成果
本地可完整浏览的静态站点。但没有 API 数据——原站是 SSR 直出,客户端几乎没有数据接口。视频 m3u8 链接带时效 token,早已失效。
收获:196 个 HTML 页面。 当时觉得只是存个档,没想到后来正是这些 HTML 里嵌入的一个广告域名,最终指向了 24000 条数据。
第二阶段:mod.run 企业官网——从门面里扒数据
从 JS Bundle 里扒接口
mod.run 是 M 平台的企业官网(Nuxt.js),下载其前端 bundle,从 minified JS 中提取到 API 路由定义:
var lr = {
SITEINFO: "/api/app/navi/infoV2",
CONFIG: "/api/app/config",
VIDEO_DETAIL: "/api/app/media/detail",
// ... 一共 6 个
};
关键发现:
- 图片 CDN:
https://cdnimg.v21c.com/ - 视频流:
https://mod.run/api/app/media/m3u8/{path} - 没有 list 接口 —— 只能按 ID 逐个查
暴力枚举 ID
从 Nuxt SSR 的 __NUXT__ 数据中提取已知 ID,发现分布在 3 个集群(242640~242648, 666865~667142, 1184741~1184779)。
30 并发扫描→秒被 403。5 并发→还是封。最后单线程 0.5s 间隔逐个跑。
结果:49 条。 百万级 ID 范围里只有 49 条。mod.run 就是个门面。
三套 ID 体系的碰撞
| 来源 | ID 体系 | 示例 |
|---|---|---|
| TG 频道 | 编号(文件名) | MD-0332.mp4 |
| madou.com 存档 | 文章 ID(超长) | 2006372122030268417 |
| mod.run | 自增数字 | 1184759 |
三套系统完全不兼容。 不同的团队、不同的数据库、不同的时代。
第三阶段:madou.com 新站——DNS 已死,Cloudflare 犹存
用户抓包驱动
madou.com 不再是 SSR 站,变成了 Vue SPA。我在浏览器 Network 面板里抓到了一个 POST 请求:
curl 'https://madou.com/api/stat/landPageConfig/getByType' \
--data-raw '{"appId":888,"pageNum":1,"pageSize":10,"type":2}'
返回 68 条视频。人看浏览器,AI 分析代码,配合得刚好。
DNS 死亡与 Cloudflare 存活
分析过程中发现 madou.com DNS 已指向 0.0.0.0。但 Cloudflare 边缘节点还没清理缓存!
# DNS 已死
$ dig madou.com +short
0.0.0.0
# 但直连 Cloudflare 还活着
$ curl --resolve "madou.com:443:104.21.0.0" 'https://madou.com/api/stat/...'
# → {"code":200, "data":[...]}
经验:DNS 死亡 ≠ 服务死亡。 CDN 边缘节点的缓存清理有延迟,这个时间窗口就是机会。
完整 CMS 后端的发现
用 --resolve 绕过 DNS 后,扫描后端路由:
/api/stat/media/list → {"msg":"no token"}
/api/stat/media/detail → {"msg":"no token"}
/api/stat/actor/list → {"msg":"no token"}
/api/stat/admin/login → {"code":10000, "msg":"Param error"} ← 公开!
30+ 个接口全部存在,只是锁在 token 后面。 这是一个完整的 Go CMS——后端根本没关,只是前端 DNS 断了。
但没有 token 就是没有 token。admin/login 试了常见账号全部不存在。
此时的总分:116 个编号。 Claude 说到头了。
第四阶段:CloudFront 金矿——一个域名引发的 24000 条数据
"我不信,没有不透风的墙,昨天才关站不可能那么彻底,肯定还有我们没找到的线索。"
线索回溯
Claude 被这句话推动,重新审视所有已有材料。回到最初下载的 196 个 HTML 页面,提取所有外部域名。
在广告链接、CDN 地址、统计脚本中间,找到了 7 个 CloudFront 域名。逐个探测,de1j8jm5ajr3l.cloudfront.net 返回了一个活着的站——标题叫 "B站点"。
一个存档页面里的广告位域名,指向了一个活跃的视频站。 这个站跟 M 平台用同一套技术体系。
JS Bundle 分析:160+ 个 API
下载其 index-BY9lizwW.js(487KB),提取到完整的 API 列表和加密配置:
// 签名密钥、解密密钥、游客登录密钥——全部明文写在前端 JS 里
const Vn = {
http_request_key: "jR6dO6fT1yD9zY7u",
http_response_key: "vEukA&w15z4VAD3kAY#fkL#rBnU!WDhN",
guest_skey: "wM5wK1jP3lK7pS2t",
};
破解签名算法
直接调用返回 非法请求。从 JS 提取签名函数 N2():
# HMAC-SHA1 签名
msg = f"{token}&{api_path}&{x_user_agent}&{timestamp}&{nonce}"
sign = hmac.new("jR6dO6fT1yD9zY7u".encode(), msg.encode(), hashlib.sha1).hexdigest()
header = f"timestamp={ts};sign={sign};nonce={nonce}"
破解 AES-CBC 响应加密
签名通过了,但响应是加密的:{"data":"vA32vSvstudnfQfwmTn0U+...","hash":true}
从 JS 提取解密函数 ib(),核心是 3 轮 SHA-256 哈希从 response_key + 12 字节 salt 派生 AES key 和 IV。
最大的坑:JS 的 Array.splice() 会修改原数组。 密钥派生过程中有 6 次 splice 操作,每次都改变了数组的内容和长度。必须像 debugger 一样逐步追踪每个变量的状态。
第一次解密成功时返回的内容是:"DevID can not be null!" —— 虽然是个错误信息,但解密本身是对的! 那一刻的成就感难以描述。
从"禁止登陆"到"不需要登录"
游客登录返回 code=6004, "账户禁止登陆"。看似又要卡住了。
但 Claude 逐个测试 160+ 个接口的权限,发现好几个不需要 token:
/api/app/search/hot/words → 200 ✅
/api/app/publish/contents → 200 ✅ 有视频数据!
/api/app/media/home → 需要 id 参数...
# 试试 id=1
api_call("/api/app/media/home", {"id": 1})
# → code=200, mediaList: 2707 items!
# id=2?!
api_call("/api/app/media/home", {"id": 2})
# → code=200, mediaList: 12327 items!!! 原创影视!!
24726 条。不需要登录。签名对了就行。
全量入库
| 分类 | 视频数 |
|---|---|
| 用户原创 | 2,707 |
| 原创影视 | 12,327 |
| 海外影视 | 5,501 |
| 社交实录 | 3,199 |
| 吃瓜社会 | 821 |
| 动漫 | 171 |
| 合计 | 24,726 |
Redis db=2 存原始 JSON,TiDB madou 库存结构化数据。最终入库 24,342 条(去重后)。
技术总结
完整的攻击链
Wayback Machine 存档
↓ wayback_machine_downloader
存档站 HTML (196 页)
↓ grep 提取外部域名 ← 关键线索就藏在这里
发现 mod.run、CloudFront、CDN 域名
↓ Nuxt.js bundle 分析
mod.run API (6 个接口, 49 条)
↓ 用户浏览器抓包
madou.com 新站 API (1 个接口, 68 条)
↓ --resolve 绕过 DNS 死亡
发现 30+ 隐藏接口(需 token)
↓ 存档 HTML 中的 CloudFront 域名
de1j8jm5ajr3l.cloudfront.net ("B站点")
↓ JS bundle (487KB) → 160+ API + 加密配置
破解 HMAC-SHA1 签名
↓ 签名通过
破解 AES-256-CBC 响应加密
↓ 解密成功
发现 media/home 不需要登录
↓ id=1~9 逐个拉取
24,342 条视频数据 → Redis + TiDB
加密体系
请求签名 (x-api-key):
HMAC-SHA1(
key = "jR6dO6fT1yD9zY7u",
msg = "{token}&{apiPath}&{X-User-Agent}&{timestamp}&{nonce}"
)
响应解密:
Base64(data) → salt(12B) + ciphertext
→ 3轮 SHA-256 派生 AES key(32B) + IV(16B)
→ AES-256-CBC 解密 → PKCS7 unpad → JSON
工具清单
| 工具 | 用途 |
|---|---|
| wayback_machine_downloader | Wayback Machine 整站镜像 |
curl + --resolve | 绕过 DNS 死亡直连 Cloudflare |
| Python (Cryptodome) | AES-256-CBC 解密 |
| Python (hmac) | HMAC-SHA1 签名 |
| Chrome DevTools | 抓包发现 API |
| Redis | 中间数据存储 |
| TiDB | 结构化数据入库 |
| hs-net (自研) | HTTP 并发扫描(被限流了) |
| hssp (自研) | 爬虫框架,提供 Cryptodome 环境 |
最终成果与感悟
成果
| 成果 | 数量 |
|---|---|
| 存档站静态页面 | 196 页 + 全部静态资源 |
| mod.run 视频数据 | 49 条 |
| madou.com 新站数据 | 68 条 |
| CloudFront 完整内容库 | 24,342 条 |
| M 平台编号视频 | 194 条 / 179 个编号 |
| TG 频道编号 | 212 个 |
| 破解的加密算法 | HMAC-SHA1 + AES-256-CBC |
| 发现的 API 接口 | 160+ 个 |
回头看这个过程
整个过程中有 4 次 AI 认为"到头了"的时刻:
- "存档站没有 API 数据" → 换到 mod.run
- "mod.run 只有 49 条" → 找到 madou.com 新站
- "新站只有一个接口,68 条" → 绕过 DNS 发现完整后端
- "后端需要 token,进不去" → 从存档 HTML 找到 CloudFront 域名
每一次突破,都不是靠更强的技术力量,而是靠换一个角度重新审视问题:
- 这个站没数据?→ 有没有别的站?
- 这个 API 到头了?→ 有没有别的 API?
- DNS 挂了?→ CDN 挂了吗?
- 登录被禁?→ 有没有不需要登录的接口?
- 正面进不去?→ 旁边有没有门?
这就是我说的"思维灵活性"。 工具可以学,算法可以查,但面对"看似无路可走"时选择"再试一个方向"的思维模式——这是 AI 暂时还不具备的。
AI 时代,每个人手里都有一把足够锋利的刀。区别在于,你是对着一堵墙反复砍,还是退后一步,发现旁边有扇没关严的窗。
经验清单
- 永远不要说"到头了"。 每次以为数据拉完了,换个角度都能找到新入口
- DNS 死亡 ≠ 服务死亡。 Cloudflare/CloudFront 边缘节点可能仍在响应
- 存档 HTML 是线索金矿。 外部域名、CDN 地址、广告链接都可能指向活跃服务
- JS Bundle 是 API 说明书。 接口列表、签名算法、加密密钥全在里面
- 关联站点共享后端。 看似不同的站,可能用同一套系统
- 人机协作的最佳姿势: 人负责判断和方向,AI 负责执行和分析
- "再试一下"三个字,价值 24000 条数据
本文记录于 2026-04-03,madou.com 于前一日(4月2日)宣布永久关停,本文为关停次日的数据抢救全过程。 使用工具:Claude Code (Claude Opus 4.6) + wayback_machine_downloader + curl + Python + Redis + TiDB 整个过程中,人类提供方向和判断,AI 提供技术执行力。这就是 AI 时代的逆向工程。