Files
JieXi/开发文档/抖音API接口文档.md
2025-11-28 21:20:40 +08:00

620 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 抖音视频解析 API 接口文档
## 概述
本文档描述了自部署的抖音视频解析 API 接口,用于从抖音分享链接中提取视频信息和下载视频文件。
**API 基础地址**: `https://dy.zoomcaronline.net`
---
## 接口列表
### 1. 提取视频 ID
从抖音分享链接中提取 `aweme_id`(视频唯一标识符)。
#### 请求信息
- **接口地址**: `/api/douyin/web/get_aweme_id`
- **请求方法**: `GET`
- **请求参数**:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| url | string | 是 | 抖音分享链接 | `https://v.douyin.com/FLNGa7kXvMY/` |
#### 请求示例
```bash
GET https://dy.zoomcaronline.net/api/douyin/web/get_aweme_id?url=https://v.douyin.com/FLNGa7kXvMY/
```
```javascript
// JavaScript 示例
const response = await fetch('https://dy.zoomcaronline.net/api/douyin/web/get_aweme_id?url=https://v.douyin.com/FLNGa7kXvMY/');
const data = await response.json();
```
```python
# Python 示例
import requests
url = "https://dy.zoomcaronline.net/api/douyin/web/get_aweme_id"
params = {"url": "https://v.douyin.com/FLNGa7kXvMY/"}
response = requests.get(url, params=params)
data = response.json()
```
#### 响应示例
```json
{
"code": 200,
"msg": "success",
"data": "7576474555553706981"
}
```
#### 响应字段说明
| 字段名 | 类型 | 说明 |
|--------|------|------|
| code | integer | 状态码200 表示成功 |
| msg | string | 响应消息 |
| data | string | 视频 ID (aweme_id) |
---
### 2. 获取视频详细信息
根据 `aweme_id` 获取视频的完整信息,包括作者、描述、封面图、视频地址等。
#### 请求信息
- **接口地址**: `/api/douyin/web/fetch_one_video`
- **请求方法**: `GET`
- **请求参数**:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| aweme_id | string | 是 | 视频 ID | `7576474555553706981` |
#### 请求示例
```bash
GET https://dy.zoomcaronline.net/api/douyin/web/fetch_one_video?aweme_id=7576474555553706981
```
```javascript
// JavaScript 示例
const awemeId = "7576474555553706981";
const response = await fetch(`https://dy.zoomcaronline.net/api/douyin/web/fetch_one_video?aweme_id=${awemeId}`);
const data = await response.json();
```
```python
# Python 示例
import requests
url = "https://dy.zoomcaronline.net/api/douyin/web/fetch_one_video"
params = {"aweme_id": "7576474555553706981"}
response = requests.get(url, params=params)
data = response.json()
```
#### 响应示例(精简版)
```json
{
"code": 200,
"router": "/api/douyin/web/fetch_one_video",
"data": {
"aweme_detail": {
"aweme_id": "7576474555553706981",
"desc": "#美女 #漫展 #cos #二次元 #正常穿搭无不良引导",
"create_time": 1764035452,
"duration": 7315,
"author": {
"uid": "7558808540429747259",
"nickname": "小鱼小鱼🐟",
"signature": "永做真我!\n点赞+关注 休闲娱乐不迷路",
"avatar_thumb": {
"url_list": ["https://p3-pc.douyinpic.com/aweme/100x100/..."]
},
"follower_count": 2325,
"total_favorited": 22399,
"sec_uid": "MS4wLjABAAAAdl73D1NlE1ws4rViqBn9A_RKcKl3Sa-2LNi_SnO4a3w...",
"short_id": "24435946694",
"unique_id": "24435946694"
},
"video": {
"cover_original_scale": {
"url_list": [
"https://p3-pc-sign.douyinpic.com/...",
"https://p9-pc-sign.douyinpic.com/..."
]
},
"play_addr": {
"url_list": [
"https://v5-hl-szyd-ov.zjcdn.com/...",
"https://v5-dy-o-abtest.zjcdn.com/...",
"https://www.douyin.com/aweme/v1/play/..."
]
},
"duration": 7315,
"width": 1080,
"height": 1920
},
"statistics": {
"digg_count": 12345,
"comment_count": 678,
"share_count": 90,
"play_count": 567890
},
"music": {
"id": "7123456789",
"title": "原声",
"author": "小鱼小鱼🐟",
"play_url": {
"url_list": ["https://..."]
}
}
}
}
}
```
#### 响应字段说明
##### 根字段
| 字段名 | 类型 | 说明 |
|--------|------|------|
| code | integer | 状态码200 表示成功 |
| router | string | 路由信息 |
| data | object | 视频详细数据 |
##### data.aweme_detail 核心字段
| 字段路径 | 类型 | 说明 | 示例值 |
|----------|------|------|--------|
| **基本信息** |
| aweme_id | string | 视频唯一 ID | "7576474555553706981" |
| desc | string | 视频描述/标题 | "#美女 #漫展 #cos" |
| create_time | integer | 创建时间Unix 时间戳) | 1764035452 |
| duration | integer | 视频时长(毫秒) | 7315 |
| **作者信息 (author)** |
| author.uid | string | 作者用户 ID | "7558808540429747259" |
| author.nickname | string | 作者昵称 | "小鱼小鱼🐟" |
| author.signature | string | 作者签名/简介 | "永做真我!" |
| author.avatar_thumb.url_list | array | 作者头像 URL 列表 | ["https://..."] |
| author.follower_count | integer | 粉丝数 | 2325 |
| author.total_favorited | integer | 获赞总数 | 22399 |
| author.sec_uid | string | 作者安全 ID用于分享 | "MS4wLjABAAAA..." |
| author.short_id | string | 作者短 ID | "24435946694" |
| author.unique_id | string | 作者唯一 ID抖音号 | "24435946694" |
| **视频信息 (video)** |
| video.play_addr.url_list | array | **视频播放地址列表(重要)** | ["https://v5-hl..."] |
| video.cover_original_scale.url_list | array | **封面图 URL 列表(原始尺寸)** | ["https://p3-pc..."] |
| video.duration | integer | 视频时长(毫秒) | 7315 |
| video.width | integer | 视频宽度(像素) | 1080 |
| video.height | integer | 视频高度(像素) | 1920 |
| **统计数据 (statistics)** |
| statistics.digg_count | integer | 点赞数 | 12345 |
| statistics.comment_count | integer | 评论数 | 678 |
| statistics.share_count | integer | 分享数 | 90 |
| statistics.play_count | integer | 播放数 | 567890 |
| **音乐信息 (music)** |
| music.id | string | 音乐 ID | "7123456789" |
| music.title | string | 音乐标题 | "原声" |
| music.author | string | 音乐作者 | "小鱼小鱼🐟" |
| music.play_url.url_list | array | 音乐播放地址列表 | ["https://..."] |
##### 关键字段提取路径
**最常用的字段提取代码**
```python
# 提取视频信息
aweme_detail = response.json()["data"]["aweme_detail"]
# 作者信息
author_name = aweme_detail["author"]["nickname"]
author_avatar = aweme_detail["author"]["avatar_thumb"]["url_list"][0]
author_uid = aweme_detail["author"]["uid"]
# 视频描述
video_desc = aweme_detail["desc"]
# 封面图(取第一个)
cover_url = aweme_detail["video"]["cover_original_scale"]["url_list"][0]
# 视频播放地址(取第一个,通常是最优质的)
video_url = aweme_detail["video"]["play_addr"]["url_list"][0]
# 视频时长(毫秒)
duration_ms = aweme_detail["duration"]
duration_sec = duration_ms / 1000 # 转换为秒
# 统计数据
likes = aweme_detail["statistics"]["digg_count"]
comments = aweme_detail["statistics"]["comment_count"]
shares = aweme_detail["statistics"]["share_count"]
```
---
### 3. 下载视频文件
直接从抖音分享链接下载视频文件(无水印)。
#### 请求信息
- **接口地址**: `/api/download`
- **请求方法**: `GET`
- **请求参数**:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| url | string | 是 | 抖音分享链接 | `https://v.douyin.com/FLNGa7kXvMY/` |
#### 请求示例
```bash
GET https://dy.zoomcaronline.net/api/download?url=https://v.douyin.com/FLNGa7kXvMY/
```
```javascript
// JavaScript 示例 - 下载视频
const response = await fetch('https://dy.zoomcaronline.net/api/download?url=https://v.douyin.com/FLNGa7kXvMY/');
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'douyin_video.mp4';
a.click();
```
```python
# Python 示例 - 下载视频
import requests
url = "https://dy.zoomcaronline.net/api/download"
params = {"url": "https://v.douyin.com/FLNGa7kXvMY/"}
response = requests.get(url, params=params)
# 保存视频文件
with open("douyin_video.mp4", "wb") as f:
f.write(response.content)
```
```php
// PHP 示例 - 下载视频
<?php
$url = "https://dy.zoomcaronline.net/api/download?url=" . urlencode("https://v.douyin.com/FLNGa7kXvMY/");
$videoData = file_get_contents($url);
file_put_contents("douyin_video.mp4", $videoData);
?>
```
#### 响应信息
- **Content-Type**: `video/mp4`
- **响应体**: 视频文件的二进制数据
- **文件格式**: MP4
- **特点**: 无水印
---
## 完整使用流程
### 方式一:两步获取(推荐用于需要视频信息的场景)
```python
import requests
# 步骤 1: 提取视频 ID
share_url = "https://v.douyin.com/FLNGa7kXvMY/"
response = requests.get(
"https://dy.zoomcaronline.net/api/douyin/web/get_aweme_id",
params={"url": share_url}
)
aweme_id = response.json()["data"]
# 步骤 2: 获取视频详细信息
response = requests.get(
"https://dy.zoomcaronline.net/api/douyin/web/fetch_one_video",
params={"aweme_id": aweme_id}
)
video_info = response.json()
# 提取关键信息
author_name = video_info["data"]["aweme_detail"]["author"]["nickname"]
video_desc = video_info["data"]["aweme_detail"]["desc"]
cover_url = video_info["data"]["aweme_detail"]["video"]["cover_original_scale"]["url_list"][0]
video_url = video_info["data"]["aweme_detail"]["video"]["play_addr"]["url_list"][0]
print(f"作者: {author_name}")
print(f"描述: {video_desc}")
print(f"封面: {cover_url}")
print(f"视频: {video_url}")
```
### 方式二:直接下载(推荐用于只需要视频文件的场景)
```python
import requests
# 直接下载视频
share_url = "https://v.douyin.com/FLNGa7kXvMY/"
response = requests.get(
"https://dy.zoomcaronline.net/api/download",
params={"url": share_url}
)
# 保存视频
with open("douyin_video.mp4", "wb") as f:
f.write(response.content)
print("视频下载完成")
```
---
## 抖音分享链接格式
抖音分享链接通常有以下几种格式:
1. **短链接格式**(最常见):
```
https://v.douyin.com/FLNGa7kXvMY/
```
2. **完整链接格式**:
```
https://www.douyin.com/video/7576474555553706981
```
3. **分享文本格式**(包含额外文字):
```
2.05 10/31 F@H.VY 错也行 错过也行 过去就行 # 明日方舟 https://v.douyin.com/FLNGa7kXvMY/ 复制此链接打开Dou音搜索直接观看视频
```
**提取建议**: 使用正则表达式提取链接部分:
```python
import re
text = "2.05 10/31 F@H.VY https://v.douyin.com/FLNGa7kXvMY/ 复制此链接"
pattern = r'https?://v\.douyin\.com/[A-Za-z0-9]+'
match = re.search(pattern, text)
if match:
url = match.group(0)
print(url) # https://v.douyin.com/FLNGa7kXvMY/
```
---
## 错误处理
### 常见错误码
| 错误码 | 说明 | 解决方案 |
|--------|------|----------|
| 200 | 成功 | - |
| 400 | 请求参数错误 | 检查 URL 参数是否正确 |
| 404 | 视频不存在 | 视频可能已被删除或链接无效 |
| 500 | 服务器错误 | 稍后重试 |
### 错误处理示例
```python
import requests
def get_douyin_video_info(share_url):
try:
# 提取视频 ID
response = requests.get(
"https://dy.zoomcaronline.net/api/douyin/web/get_aweme_id",
params={"url": share_url},
timeout=30
)
if response.status_code != 200:
return {"error": f"HTTP {response.status_code}"}
result = response.json()
if result.get("code") != 200:
return {"error": result.get("msg", "未知错误")}
aweme_id = result.get("data")
if not aweme_id:
return {"error": "未找到视频 ID"}
# 获取视频信息
response = requests.get(
"https://dy.zoomcaronline.net/api/douyin/web/fetch_one_video",
params={"aweme_id": aweme_id},
timeout=30
)
if response.status_code != 200:
return {"error": f"HTTP {response.status_code}"}
return response.json()
except requests.Timeout:
return {"error": "请求超时"}
except requests.RequestException as e:
return {"error": f"网络错误: {str(e)}"}
except Exception as e:
return {"error": f"未知错误: {str(e)}"}
# 使用示例
result = get_douyin_video_info("https://v.douyin.com/FLNGa7kXvMY/")
if "error" in result:
print(f"错误: {result['error']}")
else:
print("成功获取视频信息")
```
---
## 注意事项
1. **请求频率限制**: 建议控制请求频率,避免频繁请求导致 IP 被封禁
2. **超时设置**: 下载视频时建议设置较长的超时时间(建议 60-600 秒)
3. **视频大小**: 下载的视频文件大小通常在 500KB - 50MB 之间
4. **链接有效期**: 从 `play_addr.url_list` 获取的视频链接可能有时效性
5. **无水印**: 通过 `/api/download` 接口下载的视频为无水印版本
6. **SSL 证书**: 如果遇到 SSL 证书验证问题,可以临时禁用验证(不推荐生产环境)
---
## 应用场景
1. **视频下载工具**: 开发抖音视频下载器
2. **内容聚合平台**: 聚合抖音视频内容
3. **数据分析**: 分析视频数据、作者信息等
4. **自动化机器人**: 微信/QQ 机器人自动解析抖音链接
5. **视频备份**: 批量备份抖音视频
6. **内容审核**: 获取视频信息进行内容审核
---
## 技术支持
- **API 地址**: `https://dy.zoomcaronline.net`
- **更新日期**: 2025-11-26
- **版本**: v1.0
---
## 附录:完整代码示例
### Node.js 示例
```javascript
const axios = require('axios');
const fs = require('fs');
async function downloadDouyinVideo(shareUrl) {
try {
// 1. 提取视频 ID
const idResponse = await axios.get('https://dy.zoomcaronline.net/api/douyin/web/get_aweme_id', {
params: { url: shareUrl }
});
const awemeId = idResponse.data.data;
console.log('视频 ID:', awemeId);
// 2. 获取视频信息
const infoResponse = await axios.get('https://dy.zoomcaronline.net/api/douyin/web/fetch_one_video', {
params: { aweme_id: awemeId }
});
const videoInfo = infoResponse.data.data.aweme_detail;
console.log('作者:', videoInfo.author.nickname);
console.log('描述:', videoInfo.desc);
// 3. 下载视频
const videoResponse = await axios.get('https://dy.zoomcaronline.net/api/download', {
params: { url: shareUrl },
responseType: 'arraybuffer'
});
fs.writeFileSync('douyin_video.mp4', videoResponse.data);
console.log('视频下载完成');
} catch (error) {
console.error('错误:', error.message);
}
}
// 使用示例
downloadDouyinVideo('https://v.douyin.com/FLNGa7kXvMY/');
```
### Java 示例
```java
import java.io.*;
import java.net.*;
import org.json.*;
public class DouyinDownloader {
public static void main(String[] args) throws Exception {
String shareUrl = "https://v.douyin.com/FLNGa7kXvMY/";
downloadVideo(shareUrl);
}
public static void downloadVideo(String shareUrl) throws Exception {
// 1. 提取视频 ID
String idUrl = "https://dy.zoomcaronline.net/api/douyin/web/get_aweme_id?url=" +
URLEncoder.encode(shareUrl, "UTF-8");
String idResponse = sendGetRequest(idUrl);
JSONObject idJson = new JSONObject(idResponse);
String awemeId = idJson.getString("data");
System.out.println("视频 ID: " + awemeId);
// 2. 获取视频信息
String infoUrl = "https://dy.zoomcaronline.net/api/douyin/web/fetch_one_video?aweme_id=" + awemeId;
String infoResponse = sendGetRequest(infoUrl);
JSONObject infoJson = new JSONObject(infoResponse);
JSONObject videoInfo = infoJson.getJSONObject("data").getJSONObject("aweme_detail");
System.out.println("作者: " + videoInfo.getJSONObject("author").getString("nickname"));
System.out.println("描述: " + videoInfo.getString("desc"));
// 3. 下载视频
String downloadUrl = "https://dy.zoomcaronline.net/api/download?url=" +
URLEncoder.encode(shareUrl, "UTF-8");
downloadFile(downloadUrl, "douyin_video.mp4");
System.out.println("视频下载完成");
}
private static String sendGetRequest(String urlString) throws Exception {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
private static void downloadFile(String urlString, String fileName) throws Exception {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
InputStream in = conn.getInputStream();
FileOutputStream out = new FileOutputStream(fileName);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
out.close();
in.close();
}
}
```
---
**文档版本**: v1.0
**最后更新**: 2025-11-26
**维护者**: ShiHao