批量导出数据
需要离线分析或一次性取走大量内容时,用导出代替逐条调用读取接口。导出是异步任务:你创建任务,Whale 在后台按 UTC 天或小时分区生成文件,完成后你逐个下载。
导出只包含每条内容的当前版本。需要历史版本或指标快照时,使用读取内容与历史;需要持续获取新增和变化的数据时,使用增量同步数据。
使用前提
- 已按获取与使用 API Key配置
WHALE_BASE_URL和WHALE_API_KEY,本机有 curl 和 jq。 - 你的应用订阅开启了导出权限(
export_allowed)。没有开启时创建任务返回403 export_forbidden,请联系你的组织管理员向 Whale 申请。 - 如果你的订阅限定了数据集或平台,请求里必须显式传
dataset_ids和source_platforms,且不能超出订阅范围。
创建导出任务
Bash
export_response="$(curl -sS --fail-with-body -X POST "$WHALE_BASE_URL/v1/exports" \
-H "Authorization: Bearer $WHALE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"dataset_ids": ["social_media_raw"],
"source_platforms": ["reddit"],
"published_from": "2026-10-01T00:00:00Z",
"published_to": "2026-10-08T00:00:00Z",
"format": "jsonl",
"partition_by": "hour"
}')"
printf '%s' "$export_response" | jq .
EXPORT_ID="$(printf '%s' "$export_response" | jq -er '.export_id')"| 字段 | 必填 | 说明 |
|---|---|---|
dataset_ids | 条件 | 要导出的数据集;订阅限定了数据集时必填 |
source_platforms | 条件 | 要导出的平台;订阅限定了平台时必填 |
published_from / published_to | 否 | 按发布时间筛选,RFC 3339;from 必须早于 to |
format | 否 | jsonl(默认)或 parquet |
compression | 否 | 由格式决定:jsonl 只能用 gzip,parquet 只能用 zstd;可省略 |
fields | 否 | 只对 jsonl 有效,可包含 platform_payload;parquet 固定使用完整跨平台字段,不包含 platform_payload |
partition_by | 否 | day(默认)或 hour;Reddit 等高吞吐平台建议使用 hour |
max_rows | 否 | 每个分区的安全上限,1–100000,默认 100000 |
max_bytes | 否 | 每个分区的安全上限,最大 1073741824(1 GiB),默认最大值 |
请求成功返回 202:
JSON
{
"export_id": "exp_01K...",
"status": "queued",
"format": "jsonl",
"compression": "gzip",
"rows": 0,
"bytes": 0,
"file_count": 0,
"partitions": 7,
"created_at": "2026-10-14T08:00:00Z",
"expires_at": "2026-10-21T08:00:00Z"
}分区与行数上限
带时间范围的任务默认按 UTC 日期拆分;partition_by=hour 时按 UTC 小时拆分。max_rows 和 max_bytes 是每个分区的安全边界。分区达到边界后如果仍有数据,任务会明确失败,不会再以成功状态静默截断。
Reddit 等每日百万级数据应使用小时分区;如果单小时仍超过边界,再缩小时间范围或按平台拆分。持续同步仍优先使用增量同步数据。
查询进度
Bash
curl -sS --fail-with-body "$WHALE_BASE_URL/v1/exports/$EXPORT_ID" \
-H "Authorization: Bearer $WHALE_API_KEY" | jq '{status, rows, bytes, file_count, partitions, error}'status 依次为 queued、running,最终为 succeeded、failed、cancelled 或 expired。从 5 秒间隔开始轮询并逐步退避。failed 时 error 说明原因;分区失败会自动重试,并从已完成的位置继续。
下载文件
任务为 succeeded 后列出文件:
Bash
curl -sS --fail-with-body "$WHALE_BASE_URL/v1/exports/$EXPORT_ID/files" \
-H "Authorization: Bearer $WHALE_API_KEY" | jq .JSON
{
"files": [
{"sequence": 0, "format": "manifest", "rows": 18234, "bytes": 2048, "download_url": "/v1/exports/exp_01K.../files/0", "expires_at": "2026-10-21T08:00:00Z"},
{"sequence": 1000001, "format": "jsonl", "rows": 5000, "bytes": 3145728, "download_url": "/v1/exports/exp_01K.../files/1000001", "expires_at": "2026-10-21T08:00:00Z"}
]
}逐个下载。download_url 是相对路径,需要拼上 WHALE_BASE_URL 并携带同一个 API Key:
Bash
curl -sS --fail-with-body "$WHALE_BASE_URL/v1/exports/$EXPORT_ID/files" \
-H "Authorization: Bearer $WHALE_API_KEY" |
jq -r '.files[] | "\(.sequence) \(.format)"' |
while read -r sequence format; do
case "$format" in
jsonl) extension="jsonl.gz" ;;
parquet) extension="parquet" ;;
*) extension="json" ;;
esac
curl -sS --fail-with-body -o "export-$EXPORT_ID-$sequence.$extension" \
"$WHALE_BASE_URL/v1/exports/$EXPORT_ID/files/$sequence" \
-H "Authorization: Bearer $WHALE_API_KEY"
donesequence为0的文件是清单(manifest.json),列出格式、总行数、各分区的时间范围、行数和文件。- 其余是数据分片,
sequence为“分区序号 × 1000000 + 分片序号”,例如第 1 个分区的第 1 片是1000001。按files返回的值下载,不要自行推算。 - 数据分片格式:
jsonl为 GZIP 压缩的 JSON Lines,每行一条内容;parquet为 ZSTD 压缩的 Parquet。 - 文件和任务在创建后 7 天过期,过期后无法下载,需要重新创建任务。
导出字段
| 字段 | 说明 |
|---|---|
document_id / version_id | Whale 内容 ID 与当前版本 ID,可用于读取内容与历史 |
external_content_id / canonical_url | 平台原始内容 ID 与规范链接 |
dataset_id / source_platform / content_type | 数据集、平台与内容类型 |
title / body / body_format | 标题、完整正文与正文格式 |
language / region / country_code | 语言与地域 |
published_at | 平台发布时间 |
content_hash / size_bytes / char_count | 正文哈希、字节数与字符数 |
author / subreddit / score / external_parent_id / external_thread_id | 作者、社区、评分与回复关系;jsonl 需在 fields 中显式选择,parquet 默认包含 |
platform_payload | 完整平台原始字段;仅 JSONL 支持,需显式选择并获得对应字段授权 |
请求的字段必须都在你的订阅字段授权内,否则返回 403 export_forbidden。
取消任务
Bash
curl -sS --fail-with-body -X POST "$WHALE_BASE_URL/v1/exports/$EXPORT_ID/cancel" \
-H "Authorization: Bearer $WHALE_API_KEY"已生成的文件在过期前仍可下载。
计费、限额与错误
每次创建导出按一次请求计量,按你的组织定价扣减积分;创建失败会退回。订阅可能设置每日导出任务数上限(daily_export_limit),达到上限后当天无法再创建。
| HTTP | code | 含义与处理 |
|---|---|---|
| 400 | invalid_export_request | 请求体格式不合法 |
| 400 | export_create_failed | 校验未通过,例如格式与压缩不匹配、published_from 晚于 published_to、parquet 传了部分字段,或已达每日导出上限;按 message 修正 |
| 400 | invalid_export_file | sequence 不是非负整数 |
| 401 | unauthorized | API Key 无效 |
| 402 | credit_insufficient | 组织积分不足 |
| 403 | export_forbidden | 订阅未开启导出,或数据集、平台、字段超出授权 |
| 404 | export_not_found / export_file_not_found | 任务或文件不存在、不属于你的应用,或已过期 |
| 429 | rate_limit_exceeded | 超过限流,按 Retry-After 退避 |
完整字段见公开 API Reference。