返回博客

TikTok 竞争对手分析:建立每周内容报告

Isabella Garcia
Isabella Garcia

Web Data Collection Specialist

02-Sep-2026

TL;DR:

  • 抖音竞争对手分析以固定账号集开始。 在收集任何帖子之前,记录哪些公共品牌账号属于报告中。
  • 可比样本比无标签总数更重要。 对每个账号使用相同的请求计数和收集时间窗口,然后披露返回的项目计数。
  • 内容类别需要可审查的规则。 在每个主题标签旁边存储匹配的短语和标签,以便审核者可以纠正分类。
  • 中位数减少一个病毒帖子的影响。 报告分布和观察到的样本频率以及总数。
  • 每周报告描述观察到的样本。 在没有验证的完整周期覆盖的情况下,它无法声称一个账号的确切总体发布频率。
  • 免费开始。 新的Scrapeless账户包括免费信用;在Scrapeless仪表板中创建一个账户。

引言:竞争对手报告在抽样步骤中失败

公共品牌供稿容易比较得不佳。一个账号可能贡献30个观察到的帖子,而另一个只贡献8个,并且一个单独的异常值可以主导平均参与度。一张精美的图表并不能修复这种不匹配。

此工作流程从选定的公共账号构建每周抖音竞争对手内容报告。它收集有限的帖子样本,用简单的可审查规则对内容进行标记,并用中位数和范围总结参与度,同时使收集范围在最终报告中可见。

在账号集由创作者而非品牌竞争者构成时,请使用TikTok影响者分析指南

一览管道

一个实用的抖音竞争对手分析管道有五个阶段:

  1. 定义竞争对手名单和报告周期。
  2. 将每个公共用户名解析为sec_uid
  3. 为每个账号收集相同的有限帖子样本。
  4. 用透明的规则对描述和标签进行分类。
  5. 将观察到的样本汇总成每周报告。

该管道在计算任何汇总之前存储原始响应和规范化行。这个分离确保报告更改不会迫使再进行一次收集。

先决条件

  • 来自Scrapeless仪表板的Scrapeless账户和API令牌
  • 带有标准库的Python 3
  • 审查过的公共品牌用户名列表
  • 固定请求的帖子数和收集时间戳
  • 人工可检查的小类别字典
  • 作为SCRAPELESS_API_KEY导出的实时令牌,用于下面的代码

组装的示例被标记为先决条件缺口,因为它需要读者的API凭证和选定账户。转化逻辑已包含,但文章不包含私人凭证或虚构的演员输出。

阶段1:定义可比的竞争对手集

竞争对手名单是报告规范的一部分。给每个账号一个稳定的内部标签,一个公共用户名,包含的原因,以及名单批准的日期。避免在一组相似规模的品牌账户中默默添加大型发布者或个人创作者,因为它的内容量会扭曲比较。

一个紧凑的名单可以像这样:

account_label username inclusion_reason
Brand A brand_a 直接类别竞争者
Brand B brand_b 相同的受众和价格层次
Brand C brand_c 邻近类别基准

保持名单由用户提供。这里使用的演员并没有发现完整的竞争市场,也没有证明两个账号在商业上竞争。

阶段2:收集相同的有限帖子样本

收集阶段通过scraper.tiktok.user.detail解析每个用户名,然后将返回的sec_uid提供给scraper.tiktok.user.work。帖子请求接受cursorcount;此工作流程从文档光标"0"开始,为每个账号请求相同的计数。

单独存储请求计数和返回计数。如果一个账号返回的可用项目较少,请勿用零值行填充其指标。在每周报告中披露差异。

帖子响应可以包括描述、标签、创建时间、公共播放和参与计数、URLs、置顶状态、语言、音乐、字幕和媒体字段。可选值可能为空。缺失的值应保留为空,直到源语义证明了另一种解释的合理性。

使用Scrapeless开始抓取

用Scrapeless为您的网络抓取和自动化工作流程加油!
今天注册并获得**$5的免费信用**——无需信用卡
立即在 Scrapeless Dashboard 领取您的免费信用。

第3阶段:使用可审核规则对内容进行分类

内容分类应保留每个标签背后的证据。一个简单的规则表通常足以用于每周操作报告:

主题 描述短语 话题标签
产品教育 how to, tips, explained tutorial, howto
启动 new, introducing, available now launch, newproduct
促销 sale, discount, limited offer sale, deal
社区 duet, challenge, your turn challenge, community

这些标签是编辑规则,而不是由演员提供的事实。保存匹配的术语并在没有规则适用时允许 uncategorized。审稿人可以区分分类错误和收集错误。

基于规则的标签还暴露了重叠。一条帖子可能同时讨论产品发布和促销。要么允许多个标签,要么定义一个文档化的优先顺序;不要让字典顺序隐形决定。

第4阶段:总结参与度和观察到的节奏

公共参与计数是收集时捕获的累积观察。将它们在声明的样本内进行比较,而不是将其视为品牌表现的完整度量。

每个帐户的有用字段包括:

  • 返回的帖子数量
  • 观察样本中最早和最晚的创建时间
  • 中位播放、点赞、评论和分享计数
  • 显示分布的最小值和最大值
  • 在分类样本中的主题份额
  • 样本中的置顶帖子数量
  • 观察的相邻采样帖子日期间的间隔

Python的 统计模块文档 定义了在实现中使用的中位数操作。中位数给出了观察到的中间值,并限制一个异常大帖子的影响,但并不能消除采样偏差。

发帖节奏需要谨慎措辞。如果收集的样本无法证明对报告期的完整覆盖,请报告“在收集样本中观察到的帖子”及其最早和最晚项之间的日期范围。不要将该数字呈现为帐户的确切每周发帖频率。

第5阶段:组装Python管道

下面的脚本为每个提供的用户名收集固定初始样本,分配一个或多个内容主题,并写入帖子级行和帐户级摘要。Python的 CSV模块文档 涵盖了导出格式,而 NIST隐私框架 提供了用于访问、保留和数据最小化决策的有用结构。

注意:下面的代码需要 SCRAPELESS_API_KEY 中的实时Scrapeless API令牌和读者提供的真实公共用户名。

python Copy
import csv
import json
import os
from datetime import datetime, timezone
from statistics import median
from urllib.request import Request, urlopen

ENDPOINT = "https://api.scrapeless.com/api/v1/scraper/request"
TOKEN = os.environ["SCRAPELESS_API_KEY"]
ACCOUNTS = [name.strip().lstrip("@") for name in os.environ[
    "TIKTOK_COMPETITOR_USERNAMES"
].split(",") if name.strip()]
REQUESTED_COUNT = 20

THEMES = {
    "product_education": {"how to", "tips", "explained", "tutorial", "howto"},
    "launch": {"new", "introducing", "available now", "launch", "newproduct"},
    "promotion": {"sale", "discount", "limited offer", "deal"},
    "community": {"duet", "challenge", "your turn", "community"},
}


def run_actor(actor, actor_input):
    data = json.dumps({"actor": actor, "input": actor_input}).encode()
    request = Request(
        ENDPOINT,
        data=data,
        headers={"x-api-token": TOKEN, "content-type": "application/json"},
        method="POST",
    )
    with urlopen(request, timeout=60) as response:
        return json.load(response)


def labels_for(item):
    hashtag_values = []
    for tag in item.get("hashtags") or []:
        hashtag_values.append(
            str(tag.get("name", "")) if isinstance(tag, dict) else str(tag)
        )
    searchable = " ".join([
        str(item.get("description") or ""),
        " ".join(hashtag_values),
    ]).lower()
    labels = [
        theme for theme, terms in THEMES.items()
        if any(term in searchable for term in terms)
    ]
    return labels or ["uncategorized"]


def metric(item, name):
    value = item.get(name)
    return value if isinstance(value, (int, float)) else None


collected_at = datetime.now(timezone.utc).isoformat()
rows = []

for username in ACCOUNTS:
    profile = run_actor("scraper.tiktok.user.detail", {"unique_id": username})
    response = run_actor(
        "scraper.tiktok.user.work",
        {"sec_uid": profile["sec_uid"], "cursor": "0", "count": REQUESTED_COUNT},
    )
    with open(f"{username}-posts-raw.json", "w", encoding="utf-8") as raw_file:
        json.dump(response, raw_file, ensure_ascii=False, indent=2)
    for item in response.get("items") or []:
        rows.append({
            "account": username,
            "collected_at": collected_at,
            "requested_count": REQUESTED_COUNT,
            "post_id": str(item.get("id") or item.get("post_id") or ""),
            "post_url": item.get("url") or item.get("post_url") or "",
            "created_at": item.get("create_time") or item.get("date") or "",
            "themes": "|".join(labels_for(item)),
            "play_count": metric(item, "play_count"),
            "like_count": metric(item, "like_count"),
            "comment_count": metric(item, "comment_count"),
            "share_count": metric(item, "share_count"),
            "is_pinned": item.get("is_pinned"),
        })

with open("competitor-posts.csv", "w", newline="", encoding="utf-8") as output:
    writer = csv.DictWriter(output, fieldnames=rows[0].keys() if rows else ["account"])
    writer.writeheader()
    writer.writerows(rows)

with open("competitor-weekly-summary.csv", "w", newline="", encoding="utf-8") as output:
    fields = ["account", "observed_posts", "median_plays", "median_likes"]
    writer = csv.DictWriter(output, fieldnames=fields)
    writer.writeheader()
    for username in ACCOUNTS:
        account_rows = [row for row in rows if row["account"] == username]
        plays = [row["play_count"] for row in account_rows if row["play_count"] is not None]
        likes = [row["like_count"] for row in account_rows if row["like_count"] is not None]
        writer.writerow({
            "account": username,
            "observed_posts": len(account_rows),
            "median_plays": median(plays) if plays else "",
            "median_likes": median(likes) if likes else "",
        })

摘要有意写为 observed_posts。在确认实时响应中的确切时间戳表示后,使用主题计数、值范围和采样日期范围进行扩展。

每周竞争者内容报告模板

一个有用的报告可以在附录之前适合一页:

部分 包括 范围说明
收集摘要 帐户名册、收集时间、请求和返回计数 说明结果覆盖所收集的样本
内容组合 主题计数和份额、未分类率 附上当前规则字典
参与度 按指标和帐户的中位数和范围 收集时的公共累积计数
节奏 观察到的帖子日期和间隔 无法以覆盖声明完整周期频率
显著帖子 帖子URL、主题、指标上下文、审稿人备注 将观察与解释分开
行动 下一次报告中待测试的问题 避免复制受保护的创意资产

将帖子级行放在附录或链接的CSV中。主要报告应让读者能够追溯每个结论到一个采样的帐户、帖子URL、收集时间和分类规则。

负责任地处理公众账户数据

公共资料仍然可能包含个人数据。将帐户集限于报告目的,限制对原始响应的访问,定义删除时间表,并避免从标题、语言或视觉内容推断敏感特征。

竞争者分析应描述可观察到的内容模式。它不应重新发布媒体、模仿受保护的创意作品,或对品牌或创作者赋予隐藏的意图。确保人类审查在可能影响商业决策的标签中保持在环中。
Scrapeless通过抓取API提供集合演员。查看当前定价页面,以便将请求的帐户和样本数量转换为生产计划。

结论:使比较可审核

当每个数字都有其范围时,TikTok竞争对手分析变得有用。修正帐户名单,请求可比较的样本,保存原始响应,公开分类规则,并报告返回计数的中位数。结果是一个每周的内容报告,支持审查而不假装样本是每个帐户的完整视图。

准备构建每周竞争对手报告吗?

加入Scrapeless DiscordTelegram社区讨论收集和报告模式。当名单和样本政策准备好时,在Scrapeless仪表板上创建一个帐户。

常见问题

问:什么是TikTok竞争对手分析?

TikTok竞争对手分析比较可观察的公共内容和跨用户定义的一组帐户的参与模式。一个有据可依的报告还会说明其收集时间、样本大小和分类规则。

问:每周竞争对手报告应包含哪些指标?

每周竞争对手报告可以包括观察到的帖子数量、采样日期跨度、内容主题组合、中位公共参与计数、范围以及显著帖子的链接。每个指标应标记为样本观察。

问:样本可以显示精确的发布频率吗?

只有在收集已验证覆盖所述期间的完整性时,样本才显示精确的发布频率。否则,报告观察到的日期和收集样本中的间隙。

问:为什么使用中位数参与而不是平均参与?

中位数参与减少了一个异常大观察值的影响。它仍然依赖于样本质量,因此在旁边发布样本计数和范围。

问:工作流程需要浏览器解析器或代理设置吗?

API返回所提供标识符的支持公共帐户和帖子字段。报告管道仍然定义帐户、样本限制、存储、分类和审查。

问:收集公共竞争对手内容是否合法?

合法性取决于管辖权、目的、数据、访问方法和适用条款。仅收集必要的公共字段,尊重知识产权,限制保留,并为特定用途获得法律建议。

在Scrapeless,我们仅访问公开可用的数据,并严格遵循适用的法律、法规和网站隐私政策。本博客中的内容仅供演示之用,不涉及任何非法或侵权活动。我们对使用本博客或第三方链接中的信息不做任何保证,并免除所有责任。在进行任何抓取活动之前,请咨询您的法律顾问,并审查目标网站的服务条款或获取必要的许可。

最受欢迎的文章

目录