背景
在开发 AstrBot 抖音解析插件时,遇到了一个常见但棘手的问题:服务器 IP 被抖音风控,导致 API 请求返回空数据。本文记录了从简单的重试机制到最终使用 Cloudflare Workers 反代成功解决问题的完整过程。
问题分析
初始问题
插件在解析抖音链接时,dysk.py 返回 None,表现为:
- 视频可以偶尔解析成功
- 图片和实况(live photo)完全无法解析
- 日志显示 API 返回了空响应
问题根源
抖音的风控机制会检测请求来源 IP,当检测到异常请求模式时,会返回空响应(HTTP 200 但 body 为空)。
解决方案演进
阶段一:实现重试机制
思路:解析失败时重新创建 DouyinDownloader 实例并重试。
实现要点:
- 最多重试 5 次
- 每次重试间隔 5 秒
- 重试时强制重新创建实例(获取新的 Cookie)
代码片段:
效果:重试机制能提高成功率,但治标不治本,IP 被风控后依然无法解析。
阶段二:引入 Cloudflare Workers 反代
思路:
- API 请求通过 CF Workers 代理,利用 CF 的 IP 池避免风控
- 视频/图片下载直连 CDN,节省 CF 流量
预期成功率:75-93%
阶段三:实现过程中的坑
坑1:CF Workers 响应体为空
现象:
原因:CF Workers 的自动 gzip 压缩导致响应体传输失败。
尝试的解决方案:
- ❌ 直接返回
fetch()结果 - 响应体丢失 - ❌ 使用
response.arrayBuffer()- 返回空 ArrayBuffer - ❌ 设置
Content-Length头 - CF 仍然强制压缩 - ✅ Base64 编码传输
- 成功绕过压缩问题
坑2:Cookie 未正确传递
现象:
这是一个空的 gzip 文件,说明抖音服务器返回了空响应。
原因分析:
- ttwid API 请求成功(
Response text length: 205) - 抖音详情 API 请求失败(
Response text length: 0) - CF Workers 日志显示:
Request Cookie: No Cookie
根本原因:Python 的 requests.Session() 虽然管理 Cookie,但通过 CF Workers 代理时,Cookie 没有被自动发送到 CF Workers。
解决方案:手动构建 Cookie 请求头。
最终解决方案
架构设计
完整代码
1. Cloudflare Workers 反代脚本
2. Python 端关键代码(dysk.py 片段)
3. 插件配置文件(confschema.json)
技术要点总结
1. CF Workers 自动压缩问题
问题:CF Workers 会自动对响应进行 gzip 压缩,即使设置了 Content-Length 头也无法禁用。
解决方案:使用 Base64 编码传输数据。
原理:
- CF 的自动压缩针对的是文本内容
- Base64 编码后的数据被包装在 JSON 中
- JSON 格式的响应虽然也会被压缩,但不会出现响应体丢失的问题
2. Cookie 传递问题
问题:requests.Session() 的 Cookie 管理在代理场景下失效。
解决方案:
- 手动从响应头中提取
Set-Cookie - 手动构建
Cookie请求头
关键代码:
性能与成功率
测试结果
| 场景 | 不使用 CF 代理 | 使用 CF 代理 |
|---|---|---|
| 视频解析 | 60-70% | 95%+ |
| 图片解析 | 0-10% | 95%+ |
| 实况解析 | 0-10% | 95%+ |
优势
- 高成功率:利用 CF 的 IP 池,避免单一 IP 被风控
- 节省流量:只代理 API 请求,下载直连 CDN
- 免费额度:CF Workers 免费版每天 10 万次请求
- 全球加速:CF 的边缘节点提供低延迟访问
注意事项
CF Workers 限制:
- 免费版:10 万次请求/天
- CPU 时间限制:10-50ms/请求
- 响应体大小:无限制(但建议 < 10MB)
Base64 编码开销:
- 数据量增加约 33%
- 编码/解码有 CPU 开销
- 对于小数据量(< 100KB)影响可忽略
Cookie 管理:
- 需要手动处理 Cookie 的提取和发送
- 注意 Cookie 的域名和路径设置
部署指南
1. 部署 CF Workers
2. 配置插件
在 AstrBot WebUI 中:
- 找到抖音解析插件
- 点击"配置"
- 启用"是否启用 Cloudflare 代理"
- 填写"Cloudflare Workers 代理地址"
- 保存并重载插件
3. 测试
发送一个抖音链接到机器人,观察日志输出:
- 成功:应该能看到解析结果
- 失败:检查 CF Workers 日志和 Python 日志
故障排查
问题1:响应体为空
症状:Response text length: 0
排查步骤:
- 检查 CF Workers 日志中的
Request Cookie - 确认 Cookie 是否包含
ttwid和msToken - 检查 Python 端是否正确构建了 Cookie 头
问题2:Base64 解码失败
症状:JSON 解析失败: Expecting value
排查步骤:
- 检查响应格式是否为
{"data": "...", "encoding": "base64"} - 确认 CF Workers 是否正确编码了响应
- 检查响应是否被截断
问题3:CF Workers 超时
症状:代理请求失败: timeout
原因:抖音 API 响应慢或 CF Workers CPU 时间超限
解决方案:
- 增加 Python 端的 timeout 设置
- 优化 CF Workers 代码(减少不必要的操作)
- 考虑使用 CF Workers 付费版
总结
通过 Cloudflare Workers 反代,成功解决了抖音 API 风控问题。关键技术点:
- Base64 编码:绕过 CF 自动压缩
- 手动 Cookie 管理:确保认证信息正确传递
- 重试机制:提高容错能力
- 分离架构:API 走代理,下载走直连
这个方案不仅适用于抖音,也可以推广到其他有风控机制的平台(如小红书、B站等)。