EveryInfra

Build in Public · LF-04

TikTok 达人数据 API:用主页与视频样本完成可复核的初筛

逐步接入 TikTok profile 与 user_videos,分开账号和视频快照,计算明确口径的互动指标,处理缺失值、取样偏差与趋势,避免把公开数据误当成交效果。

拿到一份 TikTok 达人名单后,最常见的做法是先按粉丝数排序。但粉丝多不等于近期视频表现稳定,一条热门视频也不等于每条内容都有同样的表现。如果数据表只剩用户名、粉丝数和一个来路不明的“互动率”,名单很难被复核,更难据此判断谁值得进一步沟通。

TikTok 达人数据 API 更适合做有依据的初筛:先确认账号身份和主页信息,再取一组口径明确的视频样本,最后结合内容适配性与人工审阅作判断。本文用 EveryInfra 的 profile 和 user_videos 完成这条流程,不把公开互动数据延伸成销售额、真实购买者画像或合作回报预测。

参数与字段依据 2026-09-04 的公开目录和源码核对。以下业务请求是供获准场景改写的模板,没有在本轮重新调用真实账号;计算示例全部使用合成数据。

先分清官方授权展示与本文的数据读取

TikTok 官方 Display API 用于展示创作者的主页和视频,包括用户信息、视频列表与按 ID 查询视频等接口;接入还需遵守相应应用与用户授权流程。官方说明列有 user.info.basic 与 video.list 权限。若你要让用户连接自己的 TikTok 账号,应先检查这条官方接入路径。

EveryInfra 的 platform/action/params 是另一份请求契约。它不等于官方 Display API,不复用官方访问令牌,也不会因本文引用了官方文档而获得平台背书。两条路径的权限、字段和覆盖范围要各自判断。

本篇只处理主页与账号视频样本。评论、话题、商品或商城达人能力应另查对应 action;不能从一个主页对象推导商品成交,不能把商品搜索的地区条件当成作者国籍。先把研究问题收窄,才能知道哪些字段是真正需要的。

第一步:把研究任务拆成两次明确的读取

profile 回答“这个账号目前公开了什么主页信息”,user_videos 回答“这次返回了该账号的哪些视频记录”。两者虽然都使用 username,但返回形态不同:前者为对象,后者为数组,解析代码不能只改 action 就原样复用。

分别核对主页与视频列表的当前契约
curl -fsS --max-time 30 \
  'https://api.everyinfra.com/api/v1/social/catalog?platform=tiktok' \
  | jq '.capabilities[]
    | select(.action == "profile" or .action == "user_videos")
    | {action, required_params, optional_params, param_meanings,
       mode, returns_list, default_limit, max_limit, response_fields}'

此次目录中,两项均要求 username,模式均为 sync。user_videos 默认 10 条,上限 50 条;profile 是单对象,没有理由给它附上列表 limit。这里的用户名指账号短名,不是显示昵称、完整主页 URL,也不是抖音的账号标识。示例统一使用不带 @ 的短名,与当前公开目录保持一致。

用户名用于请求,稳定账号 ID 用于长期关联。账号改名后,不应简单把新短名当成一个全新达人;但也不能只因头像或昵称相似就认定是原账号。已有 ID 时优先据此关联,缺少 ID 或身份冲突时保留待确认状态。

第二步:读取主页,先确认对象而不是立刻评分

假设服务端已配置 EVERYINFRA_API_KEY 与获准查询的 EVERYINFRA_TIKTOK_USERNAME。下面只发一次主页请求,保留 HTTP 状态和正文便于初次检查;不要把 Key 放进前端代码或公开的分析表。

读取一个账号的主页模板
: "${EVERYINFRA_API_KEY:?请先配置 API Key}"
: "${EVERYINFRA_TIKTOK_USERNAME:?请填入获准账号的短名}"
jq -cn --arg username "${EVERYINFRA_TIKTOK_USERNAME}" '{
  platform: "tiktok", action: "profile", params: {username: $username}
}' | curl --silent --show-error --include --max-time 180 \
  'https://api.everyinfra.com/api/v1/social' \
  -H "Authorization: Bearer ${EVERYINFRA_API_KEY}" \
  -H 'Content-Type: application/json' --data-binary @-

当前实现将主页对象放在 results 中,外层另有请求追踪与计费信息。先核对 username、user_id 和来源 URL 是否对应目标;没有拿到对象时,不能创建一行全零账号画像。内容不可访问、取数失败与真的没有公开数据,需要分别记录。

主页字段可用于理解账号自我介绍与当前规模,例如 bio、follower_count、following_count、video_count、is_verified 与 is_private。它们不证明受众年龄、真实购买行为或内容作者的敏感属性。is_private 为真时,也不能继续假设视频可读取,更不应寻找绕过方式。

还要分清同名字段:主页的 like_count 是账号层的计数,视频行的 like_count 属于那条视频。它们不应在一张表里用同一个无范围的“点赞数”列混放,也不能把账号累计计数除以近期几条视频的播放量。

第三步:取得视频样本,记录选择条件

单独读取该账号的视频列表模板
: "${EVERYINFRA_API_KEY:?请先配置 API Key}"
: "${EVERYINFRA_TIKTOK_USERNAME:?请填入获准账号的短名}"
jq -cn --arg username "${EVERYINFRA_TIKTOK_USERNAME}" '{
  platform: "tiktok",
  action: "user_videos",
  params: {username: $username, limit: 5}
}' | curl --silent --show-error --include --max-time 180 \
  'https://api.everyinfra.com/api/v1/social' \
  -H "Authorization: Bearer ${EVERYINFRA_API_KEY}" \
  -H 'Content-Type: application/json' --data-binary @-

这里的五条用于检查字段,不是统计上有代表性的样本数量。请求会独立于主页读取执行与计费;主页成功也不保证视频列表成功。分别保存两次请求的 id、时间和 billing,避免把一个步骤的结果挪给另一个步骤。

需要明确排序时,当前 user_videos 目录列出 newest、oldest 和 popular;选择前先明确研究目的。热门样本适合研究表现突出的内容,却不适合直接估计日常表现;按时间选择则仍需核对置顶、缺失、实际发布时间与窗口是否匹配。

until 表达视频发布时间的上界,不是本次采集时间,也不是已验证的翻页游标。当前列表契约没有提供可据以遍历全部历史的分页保证;反复改日期并不断请求,不能自动证明无遗漏。最小示例先不附带筛选条件,需要时逐项加入并核对实际结果。

部分参数可能随多个 action 一起出现在目录中。一个参数被列出,不足以证明它适合所有研究对象;例如视频排序不能解释为按达人粉丝数排序。参数效果不能确认时,把它留在接入验证里,不写进研究结论。

作为接口边界的对照,TikTok 官方授权 video/list 明确说明 cursor、has_more 与每页 max_count。不能把这组官方分页参数直接填进 EveryInfra 的 user_videos:是否能够翻页,必须由实际调用入口自己的契约与结果证明。

第四步:账号、视频、观察记录分别存

可以把数据整理为三类对象。账号表记录身份与主页观察;视频表用视频 ID 关联内容与账号;观察表保存某次请求取得的指标值、条件和时间。这个划分让一条视频的播放量更新时,不必复制一份新达人资料。

  • 账号观察:user_id、请求短名、实际返回短名、主页引用、可得计数、观察时间与请求 id。
  • 视频观察:视频 id、URL、文本、作者短名、posted_at、互动/播放计数、观察时间与请求 id。
  • 派生分析:使用了哪些视频、排除了哪些记录、指标公式版本、计算时间与人工备注。
读取视频字段含义与未知字段清单
curl -fsS --max-time 30 \
  'https://api.everyinfra.com/api/v1/social/fields?platform=tiktok&action=user_videos' \
  | jq '{fields, undocumented}'

视频目录列出 like_count、comment_count、share_count 和 view_count 等字段。TikTok 官方视频对象文档也分别解释点赞、评论、分享和播放的含义;这有助于核对术语,但不能据此推断 EveryInfra 一定返回官方对象里的所有字段。每个接口仍按自身的真实结果解析。

null、缺字段与 0 要分开。未公开的播放量不能补成零,缺少分享量也不能在不说明的情况下当成零参与互动计算。posted_at 与 observed_at 同样不是一回事:前者说明内容发布时刻,后者说明你何时看到这些计数。

第五步:先写公式,再计算所谓互动率

“互动率”没有本文可以替所有团队规定的唯一口径。为了示范,下面定义一个样本指标:互动/播放比 = 合格样本中的点赞、评论、分享总和 ÷ 同一批样本的播放总和。分子是互动事件计数,分母是播放计数,不是独立人数,也不是购买转化率。

本文只让四个计数均为有效非负整数、且播放大于零的记录进入计算,缺项记录单独列出。这个规则偏保守,但能避免用填零掩盖缺失。如果你的研究另有定义,可以修改规则并记录版本,不能拿不同公式的结果直接排名。

离线 JavaScript:显式处理缺失和零分母
function interactionPerView(rows) {
  const seen = new Set();
  let events = 0, views = 0, used = 0;
  const excluded = [];
  for (const row of rows) {
    if (typeof row.id !== "string" || !row.id || seen.has(row.id)) {
      throw new Error("missing or duplicate video id");
    }
    seen.add(row.id);
    const counts = [row.like_count, row.comment_count,
                    row.share_count, row.view_count];
    if (!counts.every(x => Number.isSafeInteger(x) && x >= 0)
        || row.view_count === 0) {
      excluded.push(row.id);
      continue;
    }
    events += row.like_count + row.comment_count + row.share_count;
    views += row.view_count;
    if (!Number.isSafeInteger(events) || !Number.isSafeInteger(views)) {
      throw new Error("aggregate exceeds safe integer range");
    }
    used++;
  }
  return {used, excluded, events, views,
          ratio: views > 0 ? events / views : null};
}

console.log(interactionPerView([
  {id: "synthetic-a", like_count: 8, comment_count: 1,
   share_count: 1, view_count: 100},
  {id: "synthetic-b", like_count: 7, comment_count: 1,
   share_count: 1, view_count: 10},
  {id: "synthetic-c", like_count: null, comment_count: 1,
   share_count: 0, view_count: 20}
]));

这组三条合成记录中,前两条进入计算,第三条因点赞数缺失被排除。总互动为 19,总播放为 110,互动/播放比约为 17.27%。若先算每条的比例再平均,会得到 50%;两者回答的不是同一个问题。前者按播放规模汇总,后者给每条视频相同权重,报告里应写明选择。

这个例子不是达人评分基准,也没有行业“优秀线”。同一个账号可以在少量视频上表现突出,在其他视频上表现平常;不同内容时长、发布时间和选择条件也影响可比性。比单独呈现一个百分比更有用的,是同时列出使用样本数、排除项、总播放和所选窗口。

第六步:初筛结果要允许人工解释

公开数据能帮助你决定先看哪些账号,但不应替代内容审阅。读一组视频时,可以检查主题是否与产品相关、表达是否适合目标受众,以及是否有足够的近期内容供判断。涉及内容是否合适的结论,应附上具体依据,不只留下一个黑箱分数。

也别从简介、姓名、头像或语言推断敏感个人属性。需要商业合作中的真实受众、转化或履约信息时,应通过适当的授权与合作流程取得材料。没有这类证据,就将字段标为未知,不用模型补成看似完整的画像。

商品研究要另起清晰口径。视频提到产品、主页挂有链接、账号具备某类商城信息,与确切销量、净成交和投放回报之间还有证据缺口。本文的两个 action 没有证明这些商业结果,不应在输出表中自行新增“预估 GMV”并伪装成平台事实。

第七步:重复观察才能讨论变化

一次主页或视频调用是一张快照。要讨论增长,至少需要可比较的多次观察:账号身份一致、字段定义一致、观察间隔清楚,且两次都取得了可用数据。后一轮失败,不能把它当成粉丝数或播放量降到零。

还应区分固定视频集合与滚动视频集合。一直跟踪同一组视频,看到的是这些视频的计数变化;每次取一组近期视频,看到的则同时包含内容集合变化。把两种序列接成一条曲线,却不记录视频成员,会让曲线难以解释。

某条视频从列表中消失,也不直接证明删除;它可能不在本次样本内。更名、置顶变化、发布时间解析失败和字段缺失都应留在质量备注。不要因为数据变少,就自动给达人贴上异常或不可信标签。

追溯“为什么这次初筛不同”时,可借用 W3C PROV 的实体、处理活动与派生关系:把视频样本、规则版本和生成的名单关联起来。这里借用的是记录思路,不要求改用 RDF,也不声称名单已符合 PROV 交换规范。

出现错误时,保留可恢复的记录

401、403 与额度问题分别检查鉴权、能力权限和账号条件;参数错误按响应提示修正,不反复发送同一个错误请求。未知响应形状进入待核对区,不把 profile 的空对象与 user_videos 的空列表揉成同一个成功状态。

网络超时后,服务端可能已经执行请求,不能直接重发并假设没有重复费用。保留请求起止时间、action、非敏感参数摘要和已取得的追踪标识,再核对调用记录。实际费用依据 billing 与账单,不能按研究表最终保留了几行来倒算。

交付一份能被复核的初筛名单

一份可用的达人初筛记录,应同时包含选择理由和证据边界:账号身份、样本来源、观察时间、计算规则、排除项、内容审阅备注,以及还需要从合作方确认的信息。不要把一次接口返回包装成完整尽调,也不要把公开数据可读当成保存与再展示的无限许可。

先用一个获准账号走完主页、视频和指标核对,再增加账号数量。数据 API 帮你减少重复取数工作;初筛质量取决于你是否把指标解释清楚,并让每个判断都能回到实际样本。