批量导出数据

需要离线分析或一次性取走大量内容时,用导出代替逐条调用读取接口。导出是异步任务:你创建任务,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"
  done
  • sequence 为 0 的文件是清单(manifest.json),列出格式、总行数、各分区的时间范围、行数和文件。
  • 其余是数据分片,sequence 为“分区序号 × 1000000 + 分片序号”,例如第 1 个分区的第 1 片是 1000001。按 files 返回的值下载,不要自行推算。
  • 数据分片格式:jsonl 为 GZIP 压缩的 JSON Lines,每行一条内容;parquet 为 ZSTD 压缩的 Parquet。
  • 文件和任务在创建后 7 天过期,过期后无法下载,需要重新创建任务。

导出字段

字段说明
document_id / version_idWhale 内容 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),达到上限后当天无法再创建。

HTTPcode含义与处理
400invalid_export_request请求体格式不合法
400export_create_failed校验未通过,例如格式与压缩不匹配、published_from 晚于 published_to、parquet 传了部分字段,或已达每日导出上限;按 message 修正
400invalid_export_filesequence 不是非负整数
401unauthorizedAPI Key 无效
402credit_insufficient组织积分不足
403export_forbidden订阅未开启导出,或数据集、平台、字段超出授权
404export_not_found / export_file_not_found任务或文件不存在、不属于你的应用,或已过期
429rate_limit_exceeded超过限流,按 Retry-After 退避

完整字段见公开 API Reference。