1. 抖音主页视频列表接口到底长什么样
抖音用户主页的视频数据,本质上是一个分页拉取的 POST 接口。你打开任意一个博主主页,往下滚动,浏览器就会不断向服务端要下一页数据。这个接口返回的 JSON 里,除了视频标题、封面、时长,还带着点赞数、收藏数、分享数、评论数这些互动字段。很多人第一次抓的时候以为点赞收藏是单独接口,其实它们就藏在视频列表的statistics结构里,一次请求全给你。
这篇要解决的问题很具体:怎么在本地稳定复现「输入一个博主主页链接 → 拿到他全部视频的点赞/收藏/分享数据 → 落成表格」。适合有 Python 基础、想练接口分析但不想碰复杂逆向的人。我会把请求参数拆开讲清楚,给出可复制的config.toml和settings.json骨架,最后用 TaoToken 统一 Key 通道做鉴权验证,让整条链路跑通。
需要提前说明的是,抖音的sec_user_id是加密的,max_cursor是翻页游标,has_more决定要不要继续请求。这三个东西不理解,脚本一定写不对。下面按「先看懂接口 → 再配环境 → 再写配置 → 再验证 → 再排错」的顺序走。
2. 抓包看清请求参数与响应结构
2.1 找到那个 POST 包
打开目标博主主页,F12 切到 Network,筛选 Fetch/XHR,然后往下滚动页面。你会看到一串请求,其中有一个以post开头、路径里带/aweme/v1/web/aweme/post/的接口,就是主页视频列表。右键复制为 cURL,丢进你习惯的请求分析工具里,先把 headers 和 params 完整还原出来。
2.2 参数删减:哪些是必需的
把 cURL 转成请求后,逐个删参数测试。实测下来,真正必需的只有这几个:
| 参数 | 作用 | 是否加密 |
|---|---|---|
sec_user_id | 博主唯一标识 | 是,需从主页 URL 提取 |
max_cursor | 翻页游标,首页传 0 | 否 |
count | 期望返回条数 | 否 |
device_platform | 设备标识 | 否 |
aid | 应用 ID | 否 |
这里有个坑:你把count改成 100,返回的并不一定是 100 条。抖音服务端有自己的返回节奏,实际条数以响应里的数组长度为准。所以别用count判断是否抓完,要用has_more。
2.3 max_cursor 与 has_more 的翻页逻辑
响应 JSON 里有两个关键字段:
max_cursor:下一次请求要带的游标值,直接取本次响应里的这个字段。has_more:为 1 表示还有下一页,为 0 表示到底了。
翻页判断写成这样最稳:
next_cursor = data.get("max_cursor", 0) has_more = data.get("has_more", 0) if has_more == 1: params["max_cursor"] = next_cursor else: break2.4 互动字段藏在哪
每条视频对象里有个statistics字段,结构大致如下:
{ "statistics": { "digg_count": 12345, "collect_count": 678, "share_count": 90, "comment_count": 456, "play_count": 78900 } }digg_count是点赞,collect_count是收藏,share_count是分享,comment_count是评论。提取时直接按 key 取,别去猜字段名。
2.5 sec_user_id 怎么拿
它就在博主主页 URL 里,形如https://www.douyin.com/user/MS4wLjABAAAA...,user/后面那串就是。用正则匹配即可:
import re def extract_sec_user_id(url: str) -> str: match = re.search(r"/user/([A-Za-z0-9_\-]+)", url) if not match: raise ValueError("URL 中未找到 sec_user_id") return match.group(1)如果你要批量抓多个博主,可以用自动化浏览器打开主页,等页面加载后从当前 URL 里正则提取,避免手动复制。
3. TaoToken 前置:统一 Key 与 API 通道
3.1 为什么这里要接 TaoToken
抖音接口的 Cookie 很容易过期,批量抓的时候经常跑到一半就 401。我的做法是把请求鉴权统一走 TaoToken 的 API 通道,用一个 Key 管理所有请求,Cookie 失效时集中刷新,不用在每个脚本里散落一堆凭证。TaoToken 官网是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api 。
3.2 拿 Key 的路径
进入控制台创建 API Key,地址是 https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite 。创建后复制保存,后面写进config.toml。如果你还想顺手验证模型通道是否通,可以去模型对话页 https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite 发一条测试消息。
3.3 接入文档位置
请求头格式、鉴权方式、错误码说明都在接入文档里:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。写配置前先扫一遍,能省很多排错时间。
4. 可复制的 config.toml 与 settings.json 骨架
4.1 config.toml
# config.toml [taotoken] api_base = "https://taotoken.net/api" api_key = "sk-你的Key" timeout = 30 [spider] base_url = "https://www.douyin.com/aweme/v1/web/aweme/post/" count = 20 max_pages = 50 sleep_min = 1.5 sleep_max = 3.0 [output] format = "excel" path = "./output/douyin_videos.xlsx" [headers] user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" referer = "https://www.douyin.com/"4.2 settings.json
{ "targets": [ { "name": "示例博主A", "homepage": "https://www.douyin.com/user/MS4wLjABAAAA示例", "sec_user_id": "" } ], "fields": ["digg_count", "collect_count", "share_count", "comment_count"], "retry": { "times": 3, "backoff": 2 }, "cookie_refresh": { "enabled": true, "trigger_status": [401, 403] } }sec_user_id留空时,脚本会用正则从homepage自动提取。fields决定导出哪些互动列,想加播放量就补play_count。
4.3 请求构造与鉴权注入
import toml import json import requests config = toml.load("config.toml") settings = json.load(open("settings.json", encoding="utf-8")) def build_headers(cfg): return { "User-Agent": cfg["headers"]["user_agent"], "Referer": cfg["headers"]["referer"], "Authorization": f"Bearer {cfg['taotoken']['api_key']}" } def fetch_page(sec_user_id, cursor, cfg): params = { "sec_user_id": sec_user_id, "max_cursor": cursor, "count": cfg["spider"]["count"], "device_platform": "webapp", "aid": "6383" } resp = requests.post( cfg["spider"]["base_url"], params=params, headers=build_headers(cfg), timeout=cfg["taotoken"]["timeout"] ) resp.raise_for_status() return resp.json()5. 验证请求与成功结果
5.1 单页验证
先只抓一页,确认字段能取到:
data = fetch_page("MS4wLjABAAAA示例", 0, config) items = data.get("aweme_list", []) print("本页条数:", len(items)) for it in items[:3]: stat = it.get("statistics", {}) print(it.get("desc", "")[:20], stat.get("digg_count"), stat.get("collect_count"), stat.get("share_count"))跑通后你会看到类似输出:
本页条数: 20 今天分享一个技巧 12345 678 90 实测有效的配置方法 9876 543 215.2 翻页验证
cursor = 0 all_items = [] for page in range(config["spider"]["max_pages"]): data = fetch_page("MS4wLjABAAAA示例", cursor, config) items = data.get("aweme_list", []) all_items.extend(items) if data.get("has_more") != 1: break cursor = data.get("max_cursor", 0) print("累计条数:", len(all_items))5.3 导出 Excel
import pandas as pd rows = [] for it in all_items: stat = it.get("statistics", {}) rows.append({ "desc": it.get("desc", ""), "digg_count": stat.get("digg_count", 0), "collect_count": stat.get("collect_count", 0), "share_count": stat.get("share_count", 0), "comment_count": stat.get("comment_count", 0) }) pd.DataFrame(rows).to_excel(config["output"]["path"], index=False) print("导出完成:", config["output"]["path"])6. 本篇常见错排查
6.1 返回空列表或 has_more 一直为 1
多半是sec_user_id提取错了,或者max_cursor没更新。检查正则是否匹配到完整串,检查翻页时是否把响应里的max_cursor赋给了下一次请求。
6.2 401 / 403 频繁出现
Cookie 过期是主因。把cookie_refresh.enabled设为 true,触发状态码时重新走自动化浏览器登录刷新。如果还是不行,去接入文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 核对鉴权头格式,确认 Key 没写错。
6.3 count 设 100 但只返回 20 条
这是服务端行为,不是 bug。以aweme_list实际长度为准,别用count判断抓取量。
6.4 导出 Excel 中文乱码
to_excel默认编码没问题,乱码通常出在打开方式。用 pandas 直接写.xlsx即可,别中途转 CSV 再转回来。
6.5 批量抓取中途断掉
给请求加 retry 和退避,settings.json里的retry.times和backoff就是干这个的。再配合sleep_min/sleep_max随机间隔,稳定性会好很多。
7. 把鉴权通道固定下来
整条链路里最容易出问题的不是字段解析,而是鉴权。Cookie 会过期,Key 要统一管理。我的建议是把 TaoToken 的 API Key 作为唯一凭证入口,所有请求走同一个通道,Cookie 刷新逻辑集中在一处。这样你换博主、加字段、改导出格式,都不用动鉴权代码。
如果你后面要做长期编码或 Agent 自动化,可以看 Coding Plan https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite ,把请求调度和重试策略固化下来。需要新建或轮换 Key 时,直接去 https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite 操作。配置骨架已经给你了,先跑通单页,再开翻页,最后接导出,顺序别乱。