问答

TikTokApi 一直报 EmptyResponseException,有没有更稳的 TikTok 数据获取方式?

简短回答

EmptyResponseException 说明 TikTok 把你的自动化浏览器当成了机器人,直接返回空内容。如果只需要公开数据,用托管接口可以省掉浏览器、ms_token 和代理:okdata 查一条视频 $0.002,查一个账号 $0.002,搜索一页约 30 条视频 $0.002,失败的调用不收费。

上周五脚本在自己电脑上跑得好好的,周一部署到服务器,每次调用 video.info()、user.info() 都报 EmptyResponseException: TikTok returned an empty response。代码本身没问题。TikTokApi 是通过 Playwright 开一个无头浏览器去访问 TikTok,TikTok 的风控认定这个浏览器背后不是真人,于是回了一个空响应。

换方案之前可以先试试

库自带的报错信息里就列了几条,小规模用确实有效:

  1. 从已登录浏览器的 Cookie 里复制一个新的 ms_token 传进去。
  2. 用 headless=False 运行,或者换成 browser="webkit"。
  3. 把机房 IP 换成住宅代理,请求放慢。

麻烦在于维护。token 会过期,代理要花钱,TikTok 前端一改版又可能全部失效。如果你的目的只是读取公开数据,用不着操作账号,那浏览器这一层可以整个拿掉。

不开浏览器的同等调用

TikTokApi 里的写法 对应接口 价格
api.video(url=...).info() TikTok 视频详情 $0.002
api.user(username).info() TikTok 账号信息 $0.002
按关键词搜视频(社区里呼声很高的需求) TikTok 视频搜索 每页 $0.002
video.comments() TikTok 视频评论 每页 $0.002

也有对应不上的:某个账号的全部作品列表、话题页、推荐流和视频下载,这里都没有。

import os, requests

API = "https://api.okdata.online/v1"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}

def call(path, **params):
    body = requests.get(f"{API}/{path}", headers=H, params=params, timeout=60).json()
    if body["code"] != "ok":
        # 每个错误都会说明是否扣费、要不要重试
        raise RuntimeError(f"{body['code']} charged={body['charged']} retry={body['retry']}")
    return body["data"]

video = call("tiktok/videos/get", url="https://www.tiktok.com/@scout2015/video/6718335390845095173")["item"]
author = call("tiktok/users/get", username=video["author"]["username"])["item"]
print(video["metrics"]["views"], video["metrics"]["likes"], author["followers"])

代码里要改的地方

  • 返回的是普通 JSON,所有平台同一种结构:单个对象在 data.item,列表在 data.items,翻页看 page.next_cursor。不用写异步,也不用管浏览器的启动和关闭。
  • 出错时返回错误码。upstream_busy、upstream_failed 值得重试,not_found 说明视频或账号已经没了。这些都不扣费,完整列表见错误说明。
  • 字段名和 TikTok 原始 JSON 不一样:playCount 对应 metrics.views,diggCount 对应 metrics.likes。

什么时候继续用 TikTokApi

你需要这里没有的东西,比如某个账号的完整作品列表;或者一个月只跑几百次请求,而且在家里的网络下还能正常用,那就留着它,开源免费。有学术身份、要做大规模研究的,官方的 Research API 才是正路。

更新于