jsonscraper

如何分析 TikTok 创作者主题:Python 实用流程

通过 TikTok Scraper API 获取公开动态,保存原始响应,并对发布内容进行可复现的分析。

编辑政策 报告错误

当团队为下一次营销活动寻找主题时,手动浏览几十个账号很快就会变成一堆缺乏统一方法的笔记。一位分析师记录播放量,另一位记录视频文案,而措辞相近的帖子却被放进不同的表格。一周后,很难判断反复出现的究竟是某个主题、呈现方式,还是仅仅一条表现出色的视频。

文章:如何分析 TikTok 创作者主题:Python 实用流程
摘要:了解如何用 Python 监测公开 TikTok 账号:在 Postman 中检查接口和参数、保存 API 响应、规范化已确认字段,并比较不同时期的发布内容。
图片用途:封面——核心概念
章节:
视觉主题:编辑风格照片,匿名短视频卡片与带时间戳的数据卡和主题标签摆放在研究桌上,展现……
© jsonscraper · AI 生成的插图

一种实用做法是维护一份规模不大的公开账号列表,定期以结构化形式获取其视频信息,并将每次采集保存为独立快照。随后,可以比较不同时间的帖子和可用指标,并用语言模型对文案进行初步归类。下面介绍一个基于 Python 和 jsonscraper 的 TikTok Scraper API 研究流程。

采集数据前先明确研究问题

假设某个小型运动营养品牌的营销团队想了解,选定的公开 TikTok 创作者经常发布哪些主题,以及哪些视频值得人工查看。目标是在观察期内比较预先选定账号的帖子,而不是建立一个通用的 TikTok 人气排行榜。

这也划定了分析范围。采集所选账号的动态,有助于研究这些账号发布的内容和频率。可用的公开计数指标可以在请求时记录。若要评估自有广告的效果,则还需要单独的数据,例如广告系统或网站分析工具中的支出和转化数据。

接入 API 前,先记录研究方案:账号列表、开始日期、采集频率、分析字段以及帖子纳入标准。记录每次请求的时间,便于区分单条视频指标的变化与两组观测结果之间的差异。

采集什么,以及如何衡量

小型项目需要三层数据。第一层是账号标识和采集启动时间。第二层是保存下来、供后续核验的 API 原始响应。第三层是便于查询和报告的规范化字段:视频 ID、文案、发布时间以及可用的互动计数。

应根据具体接口的样例来确认字段名称和嵌套结构。不要预先假定列表一定叫作 videos,或播放量字段一定叫作 views。先执行文档所述的请求并检查实际返回的 JSON,再设置转换逻辑,映射到自己的数据结构。

有用的指标包括某个时间段内新增帖子的数量、帖子主题分布,以及同一视频在不同快照中的公开计数变化。比较最后一项时,应匹配视频 ID。这样一来,已发布视频的动态变化就能与新帖子的指标区分开来。

接入 TikTok Scraper API

TikTok Scraper API 说明列出了基础地址 https://tiktok.evelode.com;路由参考文档确认了 GET /getUserFeed 以及参数 query、max_cursor、count、region、with_pinned_posts、sort_type 和 cache_timeout。首次请求只需在 query 中指定账号,并通过 count 等参数设置返回条目数。license_key 通过 query string 传递;API 参考文档也说明了如何配置该密钥。集成前,可以在 Postman 集合中核对接口并检查响应。

将密钥存放在环境变量中。不要把它写进源代码、代码库、表格或客户端应用。执行请求后,保存一份成功返回的 JSON 样例,并注明日期和路由名称,将其作为规范化适配器和测试的依据。

可直接使用的 Python 最小请求示例

参考文档指出,用户动态的响应包含外层状态和 tiktok 对象,帖子列表位于 aweme_list 中。记录中可能包含 ID、文案、发布时间、作者和统计数据。具体字段及取值应以实际响应为准:部分数据可能缺失。

import json
import os
from datetime import datetime, timezone
from pathlib import Path

import requests

API_KEY = os.environ["JSONSCRAPER_TIKTOK_LICENSE_KEY"]
ENDPOINT_URL = "https://tiktok.evelode.com/getUserFeed"


def fetch_user_feed(handle: str, count: int = 20) -> dict:
    response = requests.get(
        ENDPOINT_URL,
        params={
            "license_key": API_KEY,
            "query": handle,
            "count": count,
            "region": "US",
        },
        timeout=45,
    )
    response.raise_for_status()
    payload = response.json()
    if not isinstance(payload, dict):
        raise ValueError("预期得到 JSON 对象")
    if payload.get("status") != "ok":
        raise RuntimeError(f"API 返回状态:{payload.get('status')!r}")
    tiktok = payload.get("tiktok")
    if not isinstance(tiktok, dict):
        raise ValueError("响应中缺少 tiktok 对象")
    return payload


def save_raw(payload: dict, account: str, output_dir: str = "data/raw") -> Path:
    collected_at = datetime.now(timezone.utc).isoformat()
    safe_account = "".join(c for c in account if c.isalnum() or c in "-_@")
    path = Path(output_dir) / f"{safe_account}_{collected_at.replace(':', '-')}.json"
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(
        json.dumps(
            {"collected_at": collected_at, "account": account, "payload": payload},
            ensure_ascii=False,
            indent=2,
        ),
        encoding="utf-8",
    )
    return path


def normalize_items(payload: dict, account: str, collected_at: str) -> list:
    items = payload["tiktok"].get("aweme_list", [])
    if not isinstance(items, list):
        raise ValueError("字段 tiktok.aweme_list 不是列表")

    observations = []
    for item in items:
        if not isinstance(item, dict):
            continue
        stats = item.get("statistics")
        stats = stats if isinstance(stats, dict) else {}
        author = item.get("author")
        author = author if isinstance(author, dict) else {}
        observations.append({
            "account_handle": account,
            "collected_at": collected_at,
            "video_id": item.get("aweme_id"),
            "caption": item.get("desc"),
            "published_at_epoch": item.get("create_time"),
            "author_handle": author.get("unique_id"),
            "views": stats.get("play_count"),
            "likes": stats.get("digg_count"),
            "comments": stats.get("comment_count"),
            "shares": stats.get("share_count"),
        })
    return observations


if __name__ == "__main__":
    account = "creator_handle"
    payload = fetch_user_feed(account, count=20)
    collected_at = datetime.now(timezone.utc).isoformat()
    raw_path = save_raw(payload, account)
    observations = normalize_items(payload, account, collected_at)
    print(f"已保存:{raw_path};记录数:{len(observations)}")

运行前,在环境中设置 JSONSCRAPER_TIKTOK_LICENSE_KEY,并安装 requests 库。代码会检查 HTTP 响应、外层状态以及 tiktok 对象是否存在,随后读取 aweme_list。它会保存原始 JSON,并提取参考文档确认过的字段;缺失值则留空。返回的动态只是 API 本次返回的一组结果,因此报告应关联请求时间和所选账号。

保存快照并比较帖子

小型项目可以使用 SQLite 或 PostgreSQL。原始响应应与规范化记录分开保存。观测数据表可以采用以下结构:

CREATE TABLE IF NOT EXISTS video_observations (
    account_handle TEXT NOT NULL,
    video_id TEXT NOT NULL,
    collected_at TEXT NOT NULL,
    published_at_epoch INTEGER,
    caption TEXT,
    views INTEGER,
    likes INTEGER,
    comments INTEGER,
    shares INTEGER,
    raw_file TEXT,
    PRIMARY KEY (account_handle, video_id, collected_at)
);

每次运行都新增一个快照,而不是覆盖旧数据。比较计数时,仅在同一视频的两个快照都存在相应数值的情况下计算差值。报告中应包含两次请求的间隔和观测时间,以说明指标变化是在多长时间内累积的。

进行主题分类时,可以先从小型类别词表入手,之后再按需添加分类器或语言模型。向模型提供清理后的文案、帖子 ID 和预先定义的类别。与自由形式的概述相比,包含类别和简短依据的结构化结果更便于在不同轮次之间比较。

加入带可核验标注的语言模型

模型可以先把文案归入“食谱”“训练”“产品评测”和“个人故事”等主题。开始时,人工标注几十条帖子。将自动标签与这些样例比较,调整类别定义,并在修改提示词或模型后重新评估。

新增帖子数量、计数指标的中位数以及快照之间的差值,都更适合用普通代码计算。模型则用于文本分类和生成简短说明。保留原始文案和数值观测,供后续核验。

同时保存帖子 ID、提示词版本、处理日期和所用模型。若分类有误,分析师便能找到对应文案并修正规则。建议将初始标签和人工修正分别存储。

自动化运行

手动运行并验证后,可将脚本迁移到 cron、GitHub Actions、n8n 或 Make。调度器按计划启动采集、传入账号列表、记录运行结果,并将报告发送到指定存储位置。将密钥保存在运行环境的机密配置中。先用一个账号验证流程,再逐步扩展列表。

将自动化拆分为几个阶段:账号队列、API 调用、保存原始响应、规范化、写入快照和生成报告。单个账号发生错误时,不应抹去其他账号的结果。可以通过运行 ID 和数据库唯一约束,让重复运行具备幂等性。

记录时间、账号、路由、HTTP 状态、运行时长、处理条目数和错误说明。不要将 API 密钥写入日志。cache_timeout 是 /getUserFeed 支持的参数;如果需要指定缓存时长,可以将其加入请求。API 参考文档将默认值说明为 3600 秒。

发布报告前检查数据质量

将几条规范化记录与原始 JSON 对照。检查重复采集时是否通过 ID 识别同一视频、日期解析是否符合预期、数值字段类型是否恰当,以及缺失数据的比例是否明确。然后再次运行,并确认数据库保留了旧观测且新增了新观测。

不要混淆不同账号和采集时段。比较主题时,应使用相同的时间段长度,或在报告中明确标注。分析计数指标的变化时,应记录两次快照间隔,让读者了解比较区间的时长。

保留原始文案,并将清理后的版本单独存储。表情符号、话题标签、链接和语言特征都可能影响分类;分别保存这些字段,有助于检查清理操作的影响,并在不重新请求 API 的情况下重新计算类别。

流程能带来什么结果

经过几个周期后,团队将得到帖子和快照表、按主题初步归类的文案,以及所选时段内新视频的报告。这有助于筛选值得专家审看的视频,发现所选账号反复讨论的主题,并检查不同观测日期之间公开计数指标的变化。

基于这些数据,可以为编辑日历提出假设:比较同一问题的不同呈现方式,或找出适合在自有内容中测试的主题。若要评估商业效果,则应将观测结果与内部营销活动数据进行对照。

要开始使用,可选择一小批公开账号,并在 Postman 请求集合中测试 GET /getUserFeed。只有路由文档和实际响应确认过的参数及字段路径,才应写入代码。

负责任地采集公开数据

根据研究目标限制账号列表,只采集必要字段,并设定原始响应的保留期限。将数据用于商业目的前,请检查适用的平台条款以及所在司法辖区的个人数据要求。设置访问控制并删除过期快照,有助于确保流程不超出任务范围。

向 AI 服务发送数据前,删除模型不需要的字段。在报告中注明帖子 ID 和观测日期,方便员工打开记录并核实结论依据。

启动简明清单

  1. 明确细分领域、账号列表、时间段和分析问题。
  2. 在参考文档中核对 GET /getUserFeed 的参数,并在 Postman 中检查实际响应。
  3. 保存 JSON 样例,并针对已确认字段设置规范化程序。
  4. 保存原始响应,并单独记录带有采集时间的快照。
  5. 用代码计算数值指标;使用 AI 对文本进行初步归类。
  6. 添加运行计划、日志记录、重试处理和数据保留期限。

这样,监测流程就成为一项可复现的研究:每个结论都关联到具体帖子和观测时间,代码也以所选路由的实际结构为依据。

People

No people listed for this article yet.

Keep reading如何用 Python 归档 TikTok 搜索结果
Read the next article

将阅读内容转化为可用的集成

探索 jsonscraper 社交数据 API、测试请求并构建下一个工作流。

查看 API