返回博客

导出 TikTok 个人资料、帖子和商店数据到 CSV

Alex Johnson
Alex Johnson

Senior Web Scraping Engineer

03-Sep-2026

TL;DR:

  • 将 TikTok 数据导出为 CSV 需要每个实体层级一个表。 个人资料、帖子、产品和 SKU 不共享安全的扁平架构。
  • 标识符应保持文本格式。 帐户、帖子、产品、卖家和 SKU ID 在电子表格软件将其视为数字时可能会丢失精度。
  • 数值指标需要明确转换。 在将有效计数和价格转换为预期类型时,保留缺失值。
  • 嵌套列表需要有意序列化。 主题标签和选项对可以使用可读的分隔文本或单独的子表。
  • CSV 由调用者创建。 文档化的参与者返回 JSON,而不是原生的 Excel 工作簿。
  • 免费开始。 新的 Scrapeless 账户通过 Scrapeless Dashboard 包括免费的信用。

引言:扁平化 JSON 是数据模型决策

JSON 可以表示嵌套的统计数据、数组、产品选项和 SKU 对象。CSV 文件则不能。因此,有用的导出需要首先决定每一行哪个实体属于哪个层级,以及如何处理空值、字符串和嵌套集合。

本教程将 Scrapeless TikTok 个人资料、帖子和商店响应映射到四个 CSV 文件:个人资料、帖子、产品和 SKU。该转换保留标识符精度,保持原始响应可用,并避免在 URL 足够时复制媒体文件。

TikTok 数据参与者概述 映射生成这些 JSON 对象的请求输入。

概览

JSON 对象 CSV 粒度 主键候选
用户详细信息 一条观察到的个人资料 帐户 ID + 收集时间
用户工作项 一条观察到的帖子 帖子 ID + 收集时间
商店页面产品 一条观察到的产品 产品 ID + 区域 + 收集时间
商店页面 SKU 一条观察到的变体 产品 ID + 区域 + SKU ID + 收集时间

该导出是应用程序端的转换。它并不声称参与者直接返回 CSV 或 Excel 文件。

前提条件

  • 来自 scraper.tiktok.user.detailscraper.tiktok.user.workscraper.tiktok.shop.page 的保存 JSON 响应
  • 调用应用程序记录的收集时间戳
  • 定义类型和空值处理的字段字典
  • 可用于检查的 UTF-8 兼容电子表格或分析软件

以下转换可以在本地运行,使用读者提供的 JSON 文件。在响应保存后,不需要 Scrapeless 凭证。

第 1 阶段:定义四种导出模式

个人资料和帖子通过帐户标识符连接,而产品和 SKU 通过产品 ID 和区域连接。保持这些实体层级的独立:

文件 选择的字段
profiles.csv 帐户 ID、用户名、sec_uid、公共统计、标记、收集时间
posts.csv 帖子 ID、帐户 ID、URL、描述、主题标签、公共指标、收集时间
products.csv 产品 ID、区域、卖家 ID、名称、价格、货币、库存、评分、计数、收集时间
skus.csv 产品 ID、区域、SKU ID、选项、SKU 价格、可用性、收集时间

RFC 4180 定义了一种常见的 CSV 格式和引用规则;CSV 格式规范 在导出在系统之间移动时非常有用。Python 的 CSV 模块文档 解释了为什么文件应使用 newline="" 打开。

第 2 阶段:保留 ID 和空值

每个看起来像数字的标识符在导出前应转换为字符串。这适用于帐户、帖子、产品、卖家、音乐和 SKU ID。否则,电子表格可能会显示科学计数法或四舍五入的数字。

缺失值应保持为空或使用文档化的空标记。不要将缺失的关注者数量、价格、库存数量、评分或参与度指标变为零。

Python 的 Decimal 文档 描述了价格的精确十进制算术。对于普通的 CSV 导出,保留源价格文本通常比将其转换为二进制浮点更安全。

开始使用 Scrapeless 抓取

使用 Scrapeless 强化您的网络抓取和自动化工作流!
今天注册并获得 5 美元的免费信用无需信用卡

立即在 Scrapeless Dashboard 索取您的免费信用。

第 3 阶段:扁平化嵌套字段而不失意义

小型展示列表可以使用字段字典记录的分隔符。例如,主题标签可以用 | 连接,SKU 选项可以变成 Color=Black | Size=M。当列表元素需要自己的字段或分析时,保持一个单独的子表。

嵌套字典应该被明确映射。产品货币和价格位于 price 下;汇总数量和可用性位于 stock 下;配置文件计数位于 statistics 下。通用递归扁平化器往往会产生不稳定的列名并混合实体层级。

阶段 4:在 Python 中导出四个表

脚本期望当前目录中最多有三个保存的文件:profile.jsonposts.jsonshop-product.json。仅在相应源存在时写入 CSV。

python Copy
import csv
import json
from pathlib import Path

COLLECTED_AT = "reader-supplied-utc-timestamp"


def load_if_present(path):
    return json.loads(path.read_text(encoding="utf-8")) if path.exists() else None


def text_id(value):
    return "" if value is None else str(value)


def write_csv(path, rows):
    if not rows:
        return
    with path.open("w", newline="", encoding="utf-8") as output:
        writer = csv.DictWriter(output, fieldnames=list(rows[0]))
        writer.writeheader()
        writer.writerows(rows)


profile = load_if_present(Path("profile.json"))
posts_response = load_if_present(Path("posts.json"))
shop = load_if_present(Path("shop-product.json"))

if profile:
    statistics = profile.get("statistics") or {}
    write_csv(Path("profiles.csv"), [{
        "collected_at": COLLECTED_AT,
        "account_id": text_id(profile.get("account_id")),
        "unique_id": profile.get("unique_id"),
        "sec_uid": profile.get("sec_uid"),
        "followers": statistics.get("followers"),
        "following": statistics.get("following"),
        "likes": statistics.get("likes"),
        "videos": statistics.get("videos"),
        "is_verified": profile.get("is_verified"),
        "is_private": profile.get("is_private"),
    }])

if posts_response:
    post_rows = []
    for item in posts_response.get("items") or []:
        post_rows.append({
            "collected_at": COLLECTED_AT,
            "post_id": text_id(item.get("post_id")),
            "author_id": text_id(item.get("author_id")),
            "post_url": item.get("post_url"),
            "description": item.get("description"),
            "create_time": item.get("create_time"),
            "hashtags": "|".join(str(v) for v in (item.get("hashtags") or [])),
            "play_count": item.get("play_count"),
            "like_count": item.get("like_count"),
            "comment_count": item.get("comment_count"),
            "share_count": item.get("share_count"),
            "collect_count": item.get("collect_count"),
            "is_pinned": item.get("is_pinned"),
        })
    write_csv(Path("posts.csv"), post_rows)

if shop:
    price = shop.get("price") or {}
    stock = shop.get("stock") or {}
    product_id = text_id(shop.get("product_id"))
    region = shop.get("region")
    write_csv(Path("products.csv"), [{
        "collected_at": COLLECTED_AT,
        "product_id": product_id,
        "region": region,
        "seller_id": text_id(shop.get("seller_id")),
        "name": shop.get("name"),
        "currency": price.get("currency"),
        "sale_price": price.get("sale_price"),
        "original_price": price.get("original_price"),
        "available_quantity": stock.get("available_quantity"),
        "in_stock": stock.get("in_stock"),
        "rating": shop.get("rating"),
        "review_count": shop.get("review_count"),
        "sold_count": shop.get("sold_count"),
    }])

    sku_rows = []
    for sku in shop.get("skus") or []:
        sku_price = sku.get("price") or {}
        sku_rows.append({
            "collected_at": COLLECTED_AT,
            "product_id": product_id,
            "region": region,
            "sku_id": text_id(sku.get("sku_id")),
            "options": " | ".join(
                f"{v.get('name', '')}={v.get('value', '')}"
                for v in (sku.get("options") or [])
            ),
            "currency": sku_price.get("currency"),
            "sale_price": sku_price.get("sale_price"),
            "available_quantity": sku.get("available_quantity"),
            "in_stock": sku.get("in_stock"),
        })
    write_csv(Path("skus.csv"), sku_rows)

时间戳由读者故意提供,因为它属于集合事件,而不是导出运行。在执行之前用存储在源响应旁边的时间戳替换占位符。

阶段 5:验证 CSV 输出

验证应检查文件和分析意义:

  1. 以 UTF-8 打开每个 CSV,并确认描述和产品名称保持可读。
  2. 明确将标识符列导入为文本,并将其数字与源 JSON 进行比较。
  3. 在相同的粒度下计算源实体和导出行。
  4. 检查缺失值保持为空而不是零。
  5. 确认价格始终与货币和产品或 SKU 上下文一起传递。
  6. 检查包含逗号、引号或换行符的描述、主题标签和选项字符串。

在文件旁边保持一个较小的字段字典,记录源路径、CSV 列、类型、空值策略和实体粒度。这使得每次导出在选择字段或下游工具变化时可以重现。

保持媒体作为参考

头像、封面、产品和 SKU 图像字段可以包含 URL。仅导出分析所需的链接,避免将不相关的媒体下载到数据集中。URL 的有效期可能会有所不同,因此 CSV 链接不应被视为永久性媒体档案。

对于较大的管道,将原始 JSON 和集合元数据存储在耐用存储中,然后为每个分析师或工具重新生成 CSV 视图。Scrapeless 通过 Scraping API 提供参与者;在规划集合量时,请查看 当前定价页面

结论:按实体导出,而不是按响应形状导出

将 TikTok 数据导出为 CSV 时,如果转换保持实体粒度、标识符字符串、空值、嵌套字段意义、货币和集合时间,则有效。四个专注的文件比一个混合了配置文件、帖子、产品和变体的宽表更容易验证和连接。

准备构建分析就绪的 CSV 导出?

加入 Scrapeless DiscordTelegram 社区 以比较导出方案。当您准备收集源 JSON 时,请在 Scrapeless Dashboard 创建一个帐户。

常见问题解答

问:TikTok 参与者可以直接导出 CSV 或 Excel 文件吗?

记录的参与者返回 JSON。调用应用程序将响应转换为 CSV 或其他分析格式。

问:为什么 TikTok ID 应该作为文本导出?

文本保留每个数字,而电子表格和分析工具在其他情况下会强制转换长数字类型的标识符。

问:配置文件、帖子、产品和 SKU 应该共享一个 CSV 吗?

配置文件、帖子、产品和 SKU 应该使用单独的表,因为每个表的行粒度和关键各不相同。

问:缺失的 TikTok 指标在 CSV 中应该如何呈现?

缺失的指标应保持为空或使用文档中的空值标记。它们不应在没有源证据的情况下变为零。

问:导出是否需要下载图片和视频?

导出不需要下载媒体。仅存储分析所需的源 URL,并遵守项目的保留政策。

问:导出公共 TikTok 数据是否合法?

合法性取决于管辖区、目的、访问方法、数据和适用条款。尽量减少导出字段,并为预期用途获得法律建议。

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

最受欢迎的文章

目录