返回博客

TikTok活动报告与公共帖子指标

Daniel Kim
Daniel Kim

Lead Scraping Automation Engineer

02-Sep-2026

TL;DR:

  • TikTok活动报告以用户定义的名单开始。 在匹配任何收集到的记录之前,列出活动账户和帖子ID。
  • 活动帖子必须在收集的样本中存在。 保持未匹配的名单条目可见,而不是将缺失的帖子转化为零绩效。
  • 带时间戳的快照将累积计数转为增量。 仅当两个记录共享相同的帖子ID和指标时,才能从后期观察值中减去先前观察值。
  • 公共参与不是归因。 播放、点赞、评论、分享、收集和转发计数无法证明独特的覆盖、销售或投资回报。
  • 分布显示活动形态。 报告中位数、范围和顶级帖子份额以及总数。
  • 免费开始。 新的Scrapeless账户包括免费额度;在Scrapeless仪表板中创建账户。

引言:活动成员资格必须明确

公共帖子指标回答一个狭窄的问题:在记录的时间里,已知帖子有哪些计数是可见的?它们并不识别谁看到了帖子,谁购买了产品,或是哪种互动导致了转化。

本指南围绕这一界限构建TikTok活动报告。用户提供参与的账户和帖子ID,管道将这些ID与收集到的公共帖子样本匹配,并重复快照生成指标增量。最终报告分离匹配的帖子、未匹配的名单条目、累积值和区间变化。

有关帖子收集之前的账户解析步骤,请参见TikTok个人资料抓取指南

管道概述

公共帖子活动报告有六个阶段:

  1. 定义活动名单和报告边界。
  2. 将每个列出的公共账户解析为 sec_uid
  3. 收集每个账户的边界帖子样本。
  4. 将收集的项目与提供的活动帖子ID匹配。
  5. 保存带时间戳的指标快照,并计算可比较的增量。
  6. 总结匹配的覆盖范围、分布和显著帖子。

名单定义了此报告的归因成员资格。抓取器不会发现哪些帖子属于活动,仅举例或标签不应添加帖子,除非报告规则另有说明。

前提条件

  • 来自Scrapeless仪表板的Scrapeless账户和API令牌
  • 包含账户用户名和精确帖子ID的活动名单
  • 固定的收集政策和至少两个时间戳观察以获取增量
  • 导出为 SCRAPELESS_API_KEY 的实时令牌,用于下面的代码

示例有一个前提条件差距,因为它依赖于读者的API凭据、活动名单和实时公共帖子。没有提供作为真实活动结果的示例输出。

阶段 1: 构建活动名单

名单是报告的控制表。每一行应包含活动ID、公共用户名、帖子ID、已知时的预期帖子URL、如果活动团队提供的计划发布日期,以及一个人类可读的标签。

campaign_id username post_id asset_label
autumn_launch creator_a 1234567890123456789 产品演示
autumn_launch creator_b 2345678901234567890 教程

保持帖子ID为字符串。大的标识符在电子表格或分析工具将它们转为数字时可能会失去精度。

名单还应区分所需帖子和可选帖子。未出现在收集样本中的所需帖子需要 unmatched 状态和审查注释;其指标未知,而不是零。

阶段 2: 收集列出账户的公共帖子

收集路径使用 scraper.tiktok.user.detailunique_id 解析为 sec_uid,接着使用 scraper.tiktok.user.work 请求公共帖子。帖子请求支持 cursorcount,其响应包含一个 items 数组。

对于可比较的账户,使用相同的请求计数,但报告每个账户返回的计数。可用的文档确认了光标输入,但没有建立通用的完整历史循环。如果活动帖子在收集的样本之外,则标记为未匹配,并且仅通过当前响应和文档中验证的继续规则扩展收集。

每次收集运行需要其自己的UTC时间戳。将原始参与者响应存储在该运行下,以便在报告逻辑更改时可以重建帖子级指标。

使用Scrapeless开始抓取

使用Scrapeless增强您的网络抓取和自动化工作流程!
今天注册并获得5美元的免费额度无需信用卡
立即在 Scrapeless Dashboard 领取您的免费信用。

阶段 3:匹配帖子而不隐藏差距

尽可能在确切字符串的帖子 ID 上匹配。URL 可以帮助审核者,但当两者都可用时,URL 解析不应替代稳定标识符。

匹配表应保留每个名册行:

状态 意义 报告处理
matched 收集的项目中出现确切的帖子 ID 保存带时间戳的快照
unmatched 帖子 ID 在名册中但在样本中缺失 显示为缺少覆盖,而非零
unexpected 收集的帖子不在活动名册中 保留在活动总计之外
duplicate 相同的帖子 ID 在输入或存储中出现多次 聚合前解决

此对账步骤是活动操作和公共数据收集之间的审计轨迹。它防止仪表板静默丢弃必需的帖子或添加不相关的帖子,因为它使用了相似的标签。

阶段 4:存储带时间戳的度量快照

快照行应包括活动 ID、帖子 ID、账户、帖子 URL、收集时间、创建时间以及响应中存在的每个公共计数器。将缺失字段存储为 null 而非零。

SQLite 非常适合紧凑的本地历史,因为复合键可以防止重复观察。SQLite CREATE TABLE 文档 描述了可以强制每个帖子和收集时间一行的主键和表约束。

sql Copy
CREATE TABLE IF NOT EXISTS campaign_post_snapshots (
    campaign_id TEXT NOT NULL,
    post_id TEXT NOT NULL,
    collected_at TEXT NOT NULL,
    account TEXT NOT NULL,
    post_url TEXT,
    play_count INTEGER,
    like_count INTEGER,
    comment_count INTEGER,
    share_count INTEGER,
    collect_count INTEGER,
    repost_count INTEGER,
    PRIMARY KEY (campaign_id, post_id, collected_at)
);

此本地架构没有外部先决条件,并且可以在 API 凭证可用之前进行测试。下面的收集代码创建相同的表并插入匹配记录。

阶段 5:计算增量和性能分布

度量增量是后期观察到的值减去早期观察到的值,适用于相同的帖子和字段。仅在这两个值均存在时计算。如果平台修正或字段重置产生负结果,则保留以供审查,而不是将其重写为零。

比较帖子时使用一对共享的快照时间。观察 72 小时的帖子不应直接与观察 6 小时的帖子排名,而没有明确的年龄或间隔标签。

活动摘要从多个视图中受益:

  • 匹配的帖子与名册帖子划分
  • 最新的累计度量总计
  • 在共同快照区间内每个帖子的增量
  • 每个度量的中位数和范围
  • 顶部帖子的总观察播放或互动份额
  • 空度量和未匹配名册条目的计数

Python 的statistics 模块文档 定义了中位数计算。分布视图有助于显示性能是广泛还是集中,但它仍然是公共计数器的描述。

TikTok 广告管理器为付费活动报告提供了一个单独的第一方环境。其活动性能指导不应与此公共帖子工作流程混淆:数据源、访问权限和可用度量不同。

阶段 6:在 Python 中组装报告管道

以下脚本读取名册 CSV,收集每个列出账户的有限初步样本,核对确切的帖子 ID,将匹配的快照插入 SQLite,并写入供审核的覆盖文件。

注意:下面的代码需要在 SCRAPELESS_API_KEY 中获得实时 Scrapeless API 令牌,读者提供的 campaign-roster.csv 和出现在收集样本中的公共活动帖子。

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

ENDPOINT = "https://api.scrapeless.com/api/v1/scraper/request"
TOKEN = os.environ["SCRAPELESS_API_KEY"]
REQUESTED_COUNT = 35


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)


with open("campaign-roster.csv", newline="", encoding="utf-8") as roster_file:
    roster = list(csv.DictReader(roster_file))

for row in roster:
    row["username"] = row["username"].lstrip("@")
    row["post_id"] = str(row["post_id"])

collected_at = datetime.now(timezone.utc).isoformat()
items_by_account = {}

for username in sorted({row["username"] for row in roster}):
    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}-{collected_at[:10]}-raw.json", "w", encoding="utf-8") as raw_file:
        json.dump(response, raw_file, ensure_ascii=False, indent=2)
    items_by_account[username] = {
        str(item.get("id") or item.get("post_id") or ""): item
        for item in response.get("items") or []
    }

connection = sqlite3.connect("campaign-reporting.db")
connection.execute("""
CREATE TABLE IF NOT EXISTS campaign_post_snapshots (
    campaign_id TEXT NOT NULL,
    post_id TEXT NOT NULL,
    collected_at TEXT NOT NULL,
    account TEXT NOT NULL,
    post_url TEXT,
    play_count INTEGER,
    like_count INTEGER,
    comment_count INTEGER,
    share_count INTEGER,
    collect_count INTEGER,
    repost_count INTEGER,
    PRIMARY KEY (campaign_id, post_id, collected_at)
)
""")

coverage = []
for row in roster:
    item = items_by_account.get(row["username"], {}).get(row["post_id"])
    status = "matched" if item else "unmatched"
    coverage.append({**row, "status": status, "collected_at": collected_at})
    if not item:
        continue
    connection.execute(
        """INSERT OR REPLACE INTO campaign_post_snapshots VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
        (
            row["campaign_id"], row["post_id"], collected_at, row["username"],
            item.get("url") or item.get("post_url"), item.get("play_count"),
            item.get("like_count"), item.get("comment_count"), item.get("share_count"),
            item.get("collect_count"), item.get("repost_count"),
        ),
    )

connection.commit()
connection.close()

with open("campaign-coverage.csv", "w", newline="", encoding="utf-8") as output:
    writer = csv.DictWriter(output, fieldnames=coverage[0].keys())
    writer.writeheader()
    writer.writerows(coverage)

在下一个计划的观察时间运行相同的收集,然后按活动 ID 和帖子 ID 连接连续的快照行。仅在两个度量值均非空的地方计算每个增量,并在结果中保留两个收集时间戳。

活动报告模板

报告应将覆盖与性能分开:

部分 所需字段 解释边界
名册覆盖 所需帖子、匹配帖子、未匹配帖子 衡量收集覆盖,而非活动成功
快照时间 首次和最新收集时间、间隔 使增量窗口可比较
最新度量 按帖子划分的公共计数器 累计观察,而非独特用户
度量变化 常见间隔的每个帖子的增量 两个快照之间的变化
分布 中位数、范围、顶级帖子份额 显示匹配帖子中的集中度
审核队列 缺失字段、负增量、未匹配 ID 需要人工调查
如果活动包含付费媒体、联盟销售、跟踪链接或转化事件,请在清晰标记的层中加入这些第一方数据集。请勿用公共参与计数替代这些衡量标准。

负责任地处理活动数据

活动报告可能将公共创作者内容与合同、内部标签或商业决策相连接。限制对名单和内部注释的访问,最小化保留的个人数据,并定义谁可以纠正归因错误。

对于影响者项目,FTC 的披露指南 是美国披露责任的重要参考。它不替代法律建议或适用于其他司法管辖区的规则。

Scrapeless 通过 Scraping API 提供个人资料和帖子演员。在选择账户数量和快照频率之前,查看 当前定价页面

结论:报告快照所证明的内容

TikTok 活动报告需要明确的名单、精确的帖子 ID 匹配、时间戳观察和可见的覆盖差距。这些控制将公共计数器转变为可审计的匹配帖子和指标变化的记录,同时保持覆盖范围、销售和归因声明在其适当的数据源中。

准备好建立活动指标报告了吗?

加入 Scrapeless DiscordTelegram 社区 来比较数据建模模式。当活动名单准备好时,请在 Scrapeless Dashboard 中创建一个账户。

常见问题

问:什么是具有公共帖子指标的 TikTok 活动报告?

具有公共帖子指标的 TikTok 活动报告跟踪在记录时间内针对用户定义的一组活动帖子可见计数器。它测量这些观察和其变化,而不是独特的覆盖范围、销售或因果归因。

问:工作流程如何决定哪些帖子属于活动?

用户提供的名单决定活动成员资格。管道匹配精确的帖子 ID,并保持丢失或意外的帖子在性能总数之外,直到审核。

问:指标快照和增量之间有什么区别?

快照是一次观察的累积公共计数器。增量是针对同一帖子、指标和定义间隔的两个有效快照之间的差异。

问:播放计数可以作为活动曝光量报告吗?

播放计数不应作为独特的活动曝光量报告。它是一个公共帖子计数器,并未确定有多少独特的人看到了内容。

问:未匹配的活动帖子应该获得零指标吗?

未匹配的活动帖子应获得 unmatched 状态和空指标。零将会断言一个集合未产生的观察值。

问:该工作流程是否取代 TikTok Ads Manager?

公共帖子工作流程不取代 TikTok Ads Manager 或其他第一方活动系统。它产生一个与支持的公共帖子字段分开的数据集。

问:公共活动数据收集合法吗?

合法性取决于司法管辖区、目的、数据、访问方式、合同和适用条款。将收集限制在必要的公共字段,保护内部名单数据,并针对特定项目获得法律建议。

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

最受欢迎的文章

目录