用 Python 学会抓取 TikTok 视频

最后更新于 April 14, 2026

TikTok 目前每月活跃用户大约有 ,创作者每天还会上传约 2300 万条视频。就算你只想从这股数据洪流里捞出一小部分,也足够让人头大。

通常情况是这样的:你搜索“scrape TikTok videos with Python”,从教程里复制一段代码(或者直接让 ChatGPT 帮你写),跑起来以后却发现……什么都没有。要么是空白 HTML,要么报 403 错误,或者更糟的是看到“Process finished with exit code 0”,但完全没有输出。我在无数 GitHub issue 和 Reddit 讨论串里都见过这种反复踩坑的过程,所以才写了这篇指南。我们会介绍 2025 年真正可用的 3 种 Python 方法,完整演示如何下载真正的 .mp4 视频文件(不是只拿到元数据——大多数教程到这里就结束了),并附上对比表,帮你选出最适合自己场景的方案。如果你根本不想用 Python,我也会介绍像 这样的无代码方案,基本两下点击就能拿到同样的数据。

“抓取 TikTok 视频”到底是什么意思?

在开始写代码之前,先弄清楚“抓取 TikTok 视频”这句话到底指什么,因为它其实包含两种完全不同的需求:

  1. 提取视频元数据:文案、话题标签、点赞数、评论数、分享数、播放量、发布时间、作者信息。大多数教程讲的就是这个。
  2. 下载真正的视频文件(.mp4):把视频本身保存到本地。其实大多数人搜索“scrape TikTok videos”时真正想要的就是这个——但偏偏几乎没人讲。

这篇指南两种都覆盖。下面的每种方法都既能提取元数据,也能给你下载 .mp4 文件所需的链接。

为什么要用 Python 抓取 TikTok 视频?

TikTok 的用户平均每天会观看约 ,再加上 TikTok Shop 在全球广告收入中贡献了 ,从 TikTok 数据里挖掘商业价值的空间非常大。以下是我最常见的使用场景:

| 使用场景 | 你要抓取什么 | 适合谁 | |---|---|---| | 网红与营销调研 | 互动率、粉丝数、内容形式、话题标签表现 | 营销团队、代理商 | | 内容策略 | 热门话题标签、爆款视频形式、发布频率 | 内容创作者、社媒运营 | | 品牌监测 | 品牌提及、活动覆盖范围、受众情绪 | 品牌经理、公关团队 | | 竞品分析 | 竞品视频表现、广告素材、TikTok Shop 商品列表 | 电商团队、产品团队 | | 市场研究 | 新兴趋势、用户行为、产品发现 | 分析师、对冲基金、研究机构 | | 归档与合规 | 供内部审查或留档的视频文件 | 法务、合规、代理商 |

商业价值是实打实的:预计到 2026 年,美国 TikTok 广告收入将达到 234 亿美元,而在 TikTok Shop 的头部类目里,联盟创作者贡献了 。如果你在做电商或网红营销,这些数据就是直接能变现的资产。

为什么你写的基础 Python 代码在 TikTok 上会失效

如果你已经试过下面这种写法但还是没结果,那你并不孤单:

1import requests
2from bs4 import BeautifulSoup
3resp = requests.get("https://www.tiktok.com/@someuser")
4soup = BeautifulSoup(resp.text, "html.parser")
5# ...然后 HTML 里并没有任何有用内容

原因很直接:TikTok 是最难抓取的平台之一。普通的 requests.get() 只会拿到一个几乎空白的 HTML 外壳,因为真正的内容是由浏览器里的 JavaScript 渲染出来的。除此之外,TikTok 还有一整套强力反爬机制,包括行为检测、TLS 指纹识别、生成请求签名,以及会随时变化的动态 CSS 选择器。

tiktok-anti-bot-wall.webp

根据 Imperva 2025 年《Bad Bot Report》,2024 年自动化流量首次超过人类流量——如今机器人已经占到 。TikTok 对这一点心知肚明,所以它的防御也做得非常严。

下面这张快速诊断表可以帮你判断问题出在哪,以及该用哪种方法修复:

| 症状 | 可能原因 | 解决方法 | |---|---|---| | HTML 为空 / 没数据 | 内容由 JS 渲染;requests 不能执行 JavaScript | 方法 1(隐藏 JSON)或方法 3(Playwright) | | 403 / Access Denied | 缺少或错误的请求头;触发反爬检测 | 带正确请求头的方式 1 | | 第一次正常,后面失效 | 频率限制 / IP 被封 | 代理轮换(所有方法都需要) | | 出现登录墙 | 需要会话 / Cookie | 方法 3(使用已保存会话的浏览器) | | ChatGPT 生成的代码没输出 | TikTok 结构自模型训练后已变化 | 3 种方法都要用(保持更新的方案) |

大致上,每个 IP 每分钟发出 30–60 次请求后,就可能开始遇到软封禁或验证码。数据中心 IP 往往几分钟内就会被标记;如果想稳定跑量,住宅代理或移动代理几乎是必需品。

总览:3 种用 Python 抓取 TikTok 视频的方法

下面先给你路线图。每种方法都有不同的优缺点,我会逐一给出可运行代码:

  1. 隐藏 JSON 提取 —— 解析 TikTok 页面中嵌入的 __UNIVERSAL_DATA_FOR_REHYDRATION__ 脚本标签。速度最快、最简单,也不需要浏览器。
  2. 调用 TikTok 内部 API —— 直接请求未公开的 /api/post/item_list/ 接口,支持基于游标的分页,适合批量数据。
  3. 使用 Playwright 做浏览器自动化 —— 在无头浏览器里渲染页面,处理无限滚动、动态内容和登录墙。

这三种方法都可以用来下载真正的 .mp4 视频文件——我会在方法讲解后专门介绍这一部分。最后还有一张完整对比表,帮你做决定。

方法 1:利用隐藏 JSON 抓取 TikTok 视频(新手友好)

我最推荐从这个方法开始。TikTok 几乎每次页面加载都会在一个 id 为 __UNIVERSAL_DATA_FOR_REHYDRATION__<script> 标签里嵌入一大段 JSON。这个 JSON 包含前端本来要渲染出来的所有个人主页和视频数据,所以你只需要一次 HTTP 请求就能拿到,完全不需要浏览器。

你需要准备什么

  • Python 3.8+
  • requests(或 httpx
  • beautifulsoup4(或 parsel
  • 正确的请求头:User-AgentRefererAccept-Language

安装依赖:

1pip install requests beautifulsoup4

逐步操作:从脚本标签提取 TikTok 视频数据

步骤 1:使用像浏览器一样的请求头发送 GET 请求。

这一步是很多新手最容易翻车的地方。如果你直接发一个不带请求头的 requests.get(),TikTok 往往会返回 403 或验证码页面。至少要带上当前浏览器的 User-AgentReferer

1import requests
2from bs4 import BeautifulSoup
3import json
4url = "https://www.tiktok.com/@charlidamelio"
5headers = {
6    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
7    "Referer": "https://www.tiktok.com/",
8    "Accept-Language": "en-US,en;q=0.9",
9}
10resp = requests.get(url, headers=headers)

步骤 2:解析 HTML 并找到 hydration 脚本标签。

1soup = BeautifulSoup(resp.text, "html.parser")
2script_tag = soup.find("script", id="__UNIVERSAL_DATA_FOR_REHYDRATION__")

如果 script_tagNone,说明 TikTok 可能拦截了你(先检查状态码),也可能是它改了标签 ID(虽然少见,但确实会发生)。

步骤 3:把脚本内容解析成 JSON。

1data = json.loads(script_tag.string)

步骤 4:顺着 JSON 结构提取视频元数据。

结构会嵌套在 __DEFAULT_SCOPE__ 下。对于用户主页页面来说:

1user_detail = data["__DEFAULT_SCOPE__"]["webapp.user-detail"]
2user_info = user_detail["userInfo"]
3# 主页统计数据
4stats = user_info["stats"]
5print(f"Followers: {stats['followerCount']}, Likes: {stats['heartCount']}")
6# 视频列表(第一页)
7item_list = user_detail.get("itemList", [])
8for video in item_list:
9    print(video["desc"])  # 文案
10    print(video["stats"]["playCount"])  # 播放量
11    print(video["video"]["playAddr"])  # 视频下载链接(无水印)
12    print(video["video"]["downloadAddr"])  # 视频下载链接(带水印)

步骤 5:提取视频下载链接。

playAddr 字段通常会给你一个更干净的版本(一般没有 TikTok 水印叠加),而 downloadAddr 则包含标准水印。它们都是指向 .mp4 文件的直接链接,但下载时需要特定请求头(下面的下载部分会讲)。

到这里,你应该已经拿到一组视频元数据对象,每个对象都包含文案、统计信息、发布时间、话题标签(在 challenges[]textExtra 中)以及视频直链。

隐藏 JSON 方法的局限

  • 只能抓取首次页面加载时的数据——通常也就是主页上的前 30 条视频左右
  • 不能处理无限滚动或分页(没有“下一页”可请求)
  • 如果 TikTok 改了脚本标签 ID 或 JSON 结构,解析器就会失效(这种情况会周期性发生——可以帮你更早发现问题)
  • 适合:快速抓取个人主页、一次性数据提取,或者只需要最新几条视频的时候

方法 2:通过 TikTok 内部 API 抓取视频

TikTok 前端不会一次性加载所有视频——你往下滚动时,它会向内部 API 端点发起 XHR 请求。抓取用户视频最主要的接口是 /api/post/item_list/。你可以直接在 Python 里调用它,这样就能拿到基于 cursor 的分页,并访问主页上的全部视频,而不仅仅是第一页。

如何找到内部 API 端点

打开 TikTok 主页的 Chrome DevTools,进入 Network 面板,按 XHR 过滤,然后向下滚动。你会看到类似下面的请求:

1https://www.tiktok.com/api/post/item_list/?WebIdLastTime=...&aid=1988&count=35&cursor=0&secUid=...

关键参数是:

  • secUid —— 主页的唯一 ID(可以从方法 1 的 JSON 中提取,路径是 userInfo.user.secUid
  • cursor —— 分页偏移量(从 0 开始,每次响应会返回下一页游标)
  • count —— 每页数量(通常 30–35 条)

逐步操作:用 Python 查询 TikTok 内部 API

步骤 1:拿到目标主页的 secUid

你可以从隐藏 JSON(方法 1)里拿,也可以从主页 HTML 中提取。

步骤 2:构造并发送 API 请求。

1import requests
2import json
3sec_uid = "MS4wLjABAAAA..."  # 来自方法 1
4api_url = "https://www.tiktok.com/api/post/item_list/"
5params = {
6    "aid": "1988",
7    "secUid": sec_uid,
8    "count": 35,
9    "cursor": 0,
10}
11headers = {
12    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
13    "Referer": "https://www.tiktok.com/",
14}
15resp = requests.get(api_url, params=params, headers=headers)
16data = resp.json()

步骤 3:解析响应。

data["itemList"] 中的每个条目都包含和方法 1 相同的视频结构——descstatsvideo.playAddrvideo.downloadAddr 等。

步骤 4:遍历所有视频分页。

1all_videos = []
2cursor = 0
3has_more = True
4while has_more:
5    params["cursor"] = cursor
6    resp = requests.get(api_url, params=params, headers=headers)
7    data = resp.json()
8    items = data.get("itemList", [])
9    all_videos.extend(items)
10    has_more = data.get("hasMore", False)
11    cursor = data.get("cursor", 0)
12    print(f"Fetched {len(items)} videos, total: {len(all_videos)}, hasMore: {has_more}")
13print(f"Total videos scraped: {len(all_videos)}")

每次循环都会返回下一批数据和新的 cursor,直到 hasMore 变成 False 为止。

内部 API 方法的局限

  • TikTok 会频繁调整这些端点和所需参数,所以这是维护成本最高的方法。最近几个月里,一些请求开始要求 msTokenX-Bogus 或其他签名参数,而这些通常由 TikTok 的生成(简单说,用纯 Python 复现并不轻松)。
  • 某些数据类型可能还需要会话 Cookie 或额外 token
  • 依然会受到基于 IP 的限流——建议使用代理轮换
  • 如果你开始拿到空的 itemList 数组,通常说明你的 msToken 已经过期(它在浏览器里大约每 10 秒轮换一次)
  • 适合:需要批量提取、想拿到主页所有视频,而方法 1 只能拿第一页时

方法 3:使用 Playwright 抓取 TikTok 视频(浏览器自动化)

当前两种方法都卡住时——比如登录要求、验证码,或者你没法复现的签名参数——Playwright 就是备用方案。它会启动一个真实的(无头)浏览器,像普通用户一样浏览 TikTok,并且能处理 JavaScript 渲染、无限滚动,甚至已登录会话。

为 TikTok 抓取配置 Playwright

先安装 Playwright 及其浏览器二进制文件:

1pip install playwright
2playwright install firefox

如果是抓 TikTok,我更推荐 Firefox 而不是 Chromium。社区测试表明,Firefox 的 ,而且 TikTok 对基于 Chromium 的无头浏览器反爬尤其凶。

如果你还想提升隐身效果,可以把 Playwright 和 (Playwright 的补丁分支)或 (在 C++ 层修改过、专门用于反检测的 Firefox)搭配使用。根据 ,Camoufox 在面对主流反机器人检测服务时,隐身评分几乎接近满分。

逐步操作:用 Playwright 抓取 TikTok 主页视频

步骤 1:启动无头 Firefox 浏览器并进入主页。

1import asyncio
2from playwright.async_api import async_playwright
3import json
4async def scrape_tiktok_profile(username):
5    async with async_playwright() as p:
6        browser = await p.firefox.launch(headless=True)
7        context = await browser.new_context(
8            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0",
9            viewport={"width": 1280, "height": 720},
10        )
11        page = await context.new_page()
12        await page.goto(f"https://www.tiktok.com/@{username}", wait_until="networkidle")

步骤 2:等待视频网格加载完成。

1        # 等待视频条目出现
2        await page.wait_for_selector('[data-e2e="user-post-item"]', timeout=15000)

如果 TikTok 弹出“Something went wrong”之类的错误层,你可能需要点击重试按钮:

1        retry_btn = page.locator('button:has-text("Retry")')
2        if await retry_btn.count() &gt; 0:
3            await retry_btn.click()
4            await page.wait_for_selector('[data-e2e="user-post-item"]', timeout=15000)

步骤 3:提取隐藏 JSON(即使用浏览器也建议这样做)。

即使使用浏览器,最稳妥的方法依然是直接拿 hydration JSON:

1        script_el = page.locator("#__UNIVERSAL_DATA_FOR_REHYDRATION__")
2        raw_json = await script_el.inner_text()
3        data = json.loads(raw_json)
4        # 与方法 1 相同的 JSON 解析方式
5        user_detail = data["__DEFAULT_SCOPE__"]["webapp.user-detail"]
6        videos = user_detail.get("itemList", [])

步骤 4:通过滚动处理无限加载。

如果你需要超过最初那 30 条视频,可以向下滚动并捕获更多 XHR 响应:

1        all_videos = list(videos)
2        # 滚动时拦截 API 响应
3        api_responses = []
4        async def capture_response(response):
5            if "/api/post/item_list" in response.url:
6                try:
7                    body = await response.json()
8                    api_responses.append(body)
9                except:
10                    pass
11        page.on("response", capture_response)
12        # 向下滚动触发更多加载
13        for _ in range(5):  # 可按需调整滚动次数
14            await page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
15            await asyncio.sleep(2)
16        # 从拦截到的响应里收集视频
17        for api_resp in api_responses:
18            items = api_resp.get("itemList", [])
19            all_videos.extend(items)
20        print(f"Total videos: {len(all_videos)}")
21        await browser.close()
22        return all_videos
23# 运行
24videos = asyncio.run(scrape_tiktok_profile("charlidamelio"))

这样你就能拿到主页初始加载和滚动加载得到的全部视频对象列表了。

Playwright 方法的局限

  • 速度最慢(要完整渲染页面、等待网络往返、以及滚动延迟)
  • 资源消耗更高——每个浏览器实例都会占用不少内存和 CPU
  • 在大规模场景下仍然可能被 IP 封锁——最好配合代理轮换
  • 适合:复杂交互、登录墙内容、验证码处理,或者方法 1 和 2 被拦截时

如何用 Python 下载 TikTok 视频(.mp4)

这一部分正好补上了几乎所有 TikTok 抓取教程里最大的缺口。提取元数据当然有用,但大多数搜索“scrape TikTok videos”的人,想要的其实是视频文件本身。

TikTok 会把下载链接嵌入视频数据对象中:

  • playAddr —— 通常是无水印或低水印版本
  • downloadAddr —— TikTok 设计为应用内下载使用的版本(包含 TikTok 水印)

这两个链接都有时效性,通常几个小时后就会过期,所以拿到后要尽快下载。

逐步操作:下载一个 TikTok 视频文件

步骤 1:从上面三种方法中的任一种提取视频 URL。

1video_url = video["video"]["playAddr"]  # 无水印版本
2# 或者
3video_url = video["video"]["downloadAddr"]  # 带水印版本

步骤 2:用正确的请求头发起 GET 请求。

这一步最容易让人踩坑。如果你直接 requests.get(video_url),大概率会得到 403。TikTok 会检查 Referer 请求头,并且期待一个像浏览器的 User-Agent

1import requests
2headers = {
3    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
4    "Referer": "https://www.tiktok.com/",
5}
6resp = requests.get(video_url, headers=headers, stream=True)

步骤 3:把响应内容写入 .mp4 文件。

使用 stream=True 并分块写入——TikTok 视频可能比较大,不要一次性把整个文件读进内存:

1video_id = video["id"]
2filename = f"tiktok_{video_id}.mp4"
3with open(filename, "wb") as f:
4    for chunk in resp.iter_content(chunk_size=1024 * 1024):  # 1MB 分块
5        if chunk:
6            f.write(chunk)
7print(f"Downloaded: {filename}")

这样你就能在本地得到一个可播放的 .mp4 文件了。

带水印 vs. 无水印下载

TikTok 会同时保存每个视频的带水印版本和无水印版本。playAddr 往往会给你一个更干净的版本(也就是播放器实际使用的那份),而 downloadAddr 则会包含 TikTok 水印以及作者用户名。

这里提醒一下伦理问题:水印的存在本来就是为了标注创作者归属。如果你是为了研究、分析或内部审查而下载视频,用 playAddr 一般没问题;但如果你打算重新分发或转发内容,去掉创作者标识就会涉及伦理和版权问题。下面的法律部分会进一步说明。

如果你想要更稳健的下载流程,可以考虑 ——它的 TikTok 提取器可以自动处理签名计算和 URL 解析,你就不用自己管理请求头和 token 过期问题了。

横向对比:你到底该用哪种 Python 方法?

下面这张对比表,是我当初开始做 TikTok 抓取项目时最希望有人给我的:

| 对比项 | 方法 1:隐藏 JSON | 方法 2:内部 API | 方法 3:Playwright | |---|---|---|---| | 难度 | 新手 | 中级 | 中级 | | 速度 | 快(每页 1 次请求) | 快(JSON API) | 慢(完整页面渲染) | | 反爬抗性 | 中等 | 低(端点经常变化) | 高(模拟真实浏览器) | | 能下载视频 .mp4 吗? | 能(提取 playAddr) | 能(响应里有 URL) | 能(拦截网络请求) | | 支持无限滚动吗? | 不能(只有第一页) | 能(cursor 分页) | 能(模拟滚动) | | 大规模时需要代理吗? | 需要 | 需要 | 需要 | | 维护成本 | 中等(JSON 结构会变) | 高(端点和签名经常变) | 低到中等(浏览器会自动适应) | | 最适合 | 快速一次性抓主页 | 批量提取、抓全部视频 | 登录墙或复杂内容 |

我的建议是:

  • 只想快速看一条主页快照? 从方法 1 开始。配置大概 30 秒,每页不到 1 秒就能出数据。
  • 需要带分页的主页全部视频? 用方法 2,但要做好 TikTok 改 API 参数后频繁维护的准备。
  • 要面对登录墙、验证码,或者追求最高稳定性? 用方法 3 的 Playwright。它更慢、更重,但也最难被 TikTok 挡住。

实际操作里,我通常会先从方法 1 开始,只有遇到限制时才升级到方法 2 或 3。这样基础设施最简单,成本也最低。

不想写 Python?也可以用无代码工具抓取 TikTok 视频

很多搜索“scrape TikTok videos with Python”的人,其实并不是真的需要 Python,他们只是需要数据而已。如果你是营销分析师,只想从几个竞品主页提取视频元数据,或者你是品牌经理,想监控品牌提及,那就没必要折腾 Python 环境、代理轮换和签名处理了。

python-vs-nocode-ai-comparison.webp

下面是几种方案的诚实对比:

| 方案 | 技能要求 | 成本 | 维护成本 | 适合谁 | |---|---|---|---|---| | Python(自己搭建) | 中级及以上 | 免费(另加代理费用) | 高(脚本容易坏) | 完全控制、自定义流程 | | (Chrome 扩展) | 新手 | 有免费额度 | 几乎没有(AI 每次都会重新识别页面) | 快速提取视频数据,导出到 Sheets/Excel | | Apify TikTok Scraper | 新手 | 付费(按次计费) | 低(由 Apify 维护) | 批量自动化定时运行 | | TikAPI | 开发者 | 订阅付费 | 中等 | 基于 TikTok 数据开发应用 |

Thunderbit 如何处理 TikTok 抓取

是我们在 Thunderbit 团队开发的 AI 网页爬虫,它的工作方式和传统爬虫工具不太一样。它不是依赖预设的 CSS 选择器或 XPath 规则(因为 TikTok 的页面结构一变这些规则就会失效),而是让 AI 每次重新读取页面结构,并自动推荐相关列,比如文案、点赞数、话题标签、视频 URL、作者等。

整个流程真的只要两步:

  1. 在 Chrome 中打开 TikTok 主页,点击 Thunderbit 扩展,然后选择“AI Suggest Fields”。Thunderbit 会扫描页面并自动生成表格结构。
  2. 检查推荐的字段,按需调整,然后点击“Scrape”。

数据可以直接导出到 Google Sheets、Excel、Airtable 或 Notion。没有要维护的 CSS 选择器,没有代码要调试,也不用配置代理。对于只需要从少量主页提取视频元数据的营销分析师来说,这比搭建 Python 环境快得多,而且 TikTok 前端更新时也不会轻易坏掉(根据社区反馈,这种更新几乎每隔几周就会发生一次)。

Thunderbit 还支持 ——它可以进入每个单独的视频页,补充更多细节,比如完整评论数、音乐信息或视频时长。

你可以通过 免费试用。想了解更多工作原理,可以看看我们的

抓取 TikTok 的法律与伦理边界

这个话题里,几乎没有任何排名靠前的教程会讨论合法性,这一点很值得注意,因为 TikTok 其实已经对一些抓取服务采取过法律行动。你需要知道以下内容。

TikTok 的服务条款(§ 4.1) 明确禁止自动化访问。违反 TOS 属于违约,不是刑事犯罪——但可能会导致账号封禁、IP 屏蔽,甚至民事诉讼。

对于公开数据,法律环境比很多人想象中更宽松。 目前最重要的先例是 Meta Platforms v. Bright Data(加州北区,2024 年 1 月),法院认定,在未登录状态下抓取公开可访问数据并不违反 Meta 的服务条款。Meta 最终撤诉并放弃上诉。更早的 hiQ v. LinkedIn 第九巡回判决(在 Van Buren 之后仍被重申)也确立了:抓取公开可访问数据不构成 CFAA 违规——不过 hiQ 最终和解,支付了 50 万美元,并同意永久禁令,这也说明 TOS 执法依然可能带来实际风险。

如果你收集的是欧盟或加州用户的个人数据,就要考虑 GDPR 和 CCPA。 抓公开帖子是一回事,建立个人用户信息数据库又是另一回事。

实用建议:

  • 控制请求频率(不要猛刷 TikTok 服务器)
  • 不要抓取私密账号或未成年人的内容
  • 不要商业化再分发受版权保护的视频
  • 尊重 robots.txt(TikTok 对大多数自动爬取都做了限制)
  • 为个人研究或分析下载视频,和重新发布视频不是一回事——要分清楚

免责声明: 这篇文章仅供学习参考,不构成法律建议。如果你要基于抓取到的 TikTok 数据开发商业产品,请咨询律师。

总结:核心结论

到 2025 年,TikTok 抓取依然是个动态变化的目标。这个平台的反爬体系是网页里最复杂的一批,朴素的方法(普通 requests、ChatGPT 生成的片段、过时教程)基本都会翻车。但只要方法对,还是完全能做。

你可以记住以下几点:

  • 方法 1(隐藏 JSON) 最快也最简单——适合先从快速抓主页开始。
  • 方法 2(内部 API) 能支持分页和批量抓取,但因为端点和签名要求经常变化,维护成本最高。
  • 方法 3(Playwright) 在反爬方面最稳,但速度和资源消耗也更高。
  • 这三种方法 都能提取视频下载链接——而这篇指南是少数会手把手教你带着正确请求头真正下载 .mp4 文件的文章之一。
  • 对非技术用户来说 提供了一条更快的路,不用写代码,也不用维护代码。它的 AI 方案不会因为 TikTok 改版而轻易失效——而根据社区反馈,这种改版发生得比谁都想象得更频繁。

如果你想不做任何 Python 配置就直接开始,——免费额度足够你先在几个主页上测试一下是否适合你的流程。对于走 Python 路线的朋友,建议先从方法 1 开始,先验证数据,再逐步扩展。

如果你想更深入了解网页抓取技巧,可以看看我们的这些指南:

常见问题

用 Python 抓取 TikTok 视频合法吗?

抓取公开可访问的数据处于法律灰区,并不是明确违法。Meta v. Bright Data(2024)一案支持这样一种观点:在未登录状态下抓取公开数据并不违反平台服务条款。不过,TikTok 的 TOS 明确禁止自动化访问,而且如果涉及个人数据,还会受到 GDPR/CCPA 的约束。它并不像很多人想的那样“违法”,但也绝不是零风险。具体场景请咨询法律专业人士。

抓 TikTok 时,最好用哪个 Python 库?

这要看你的方法。如果是隐藏 JSON 提取(方法 1),requests + beautifulsoup4 就够了。如果是调用内部 API(方法 2),requestshttpx 都可以。如果是浏览器自动化(方法 3),playwright 是当前标准——在新的抓取项目里,它的采用度已经超过 Selenium,,而 Selenium 约 5300 万。如果你想要更高层的接口,TikTok-Api 这个封装库(GitHub 大约 6.3K stars)也值得考虑,不过稳定性可能比较脆弱。

能用 Python 下载没有水印的 TikTok 视频吗?

可以。TikTok 自己的数据里就包含一个 playAddr 链接,通常提供的是不带标准水印的视频版本。本文演示了如何从这三种方法中提取该链接,并用正确请求头下载 .mp4 文件。相比之下,downloadAddr 字段包含的是水印版本。

为什么我的 TikTok 爬虫总是返回空数据?

最常见的原因是 TikTok 需要 JavaScript 来渲染内容。普通的 requests.get() 只会拿到外壳 HTML——真正的数据要么在隐藏 JSON 脚本标签里(方法 1),要么是通过 JavaScript 动态加载的(方法 3)。如果你拿到的是空 HTML,先试方法 1;如果不行,再检查请求头(缺少 Referer 是导致 403 的首要原因),或者直接升级到 Playwright 的方法 3。

抓 TikTok 时怎么避免被封?

使用像浏览器一样的请求头(包括 User-AgentRefererAccept-Language),轮换住宅或移动代理(数据中心 IP 往往几分钟就会被标记),请求之间加入随机延迟(至少 1–3 秒),并避免高频率、大规模抓取。方法 3(Playwright)因为更像真实浏览器会话,所以抗封能力最好。如果要认真跑量,建议把代理成本算进去——主流服务商的入门级住宅代理大约是每 GB

试试 Thunderbit 抓取 TikTok
Shuai Guan
Shuai Guan
Co-founder/CEO @ Thunderbit. Passionate about cross section of AI and Automation. He's a big advocate of automation and loves making it more accessible to everyone. Beyond tech, he channels his creativity through a passion for photography, capturing stories one picture at a time.
Topics
Scrape Tiktok pythonTiktok data extraction pythonPython Tiktok scraper scriptHow to scrape Tiktok videos with python
目录

试试 Thunderbit

只需 2 次点击即可抓取线索和其他数据。AI 驱动。

获取 Thunderbit 免费使用
使用 AI 提取数据
轻松将数据转移到 Google Sheets、Airtable 或 Notion
PRODUCT HUNT#1 Product of the Week