快手 API Python 教程:搜索、作品数据、账号作品和评论(2026)
按脚本里的调用顺序,一共五个接口:快手视频搜索、作品详情、账号作品、作品评论和评论回复,每个都是带 API key 的普通 GET 请求,不用登录快手。下面的示例一共 5 次调用,花费 $0.046;失败的调用不扣费。
更新于
用 Python 拿快手数据,多数人第一步会找开源爬虫。名气最大的 MediaCrawler 支持快手的关键词搜索、按作品 ID 抓取、评论和创作者主页,做法是用 Playwright 打开浏览器,在快手 App 里扫码登录,之后复用保存下来的登录态。如果你跑得很频繁,也愿意自己维护浏览器和账号,这条路没问题。这篇讲另一种做法:每次调用就是一个带 API key 的 HTTPS GET,不需要快手账号,不用 Cookie、不用扫码、不用处理签名,依赖只有 requests。
最后会得到两个 CSV:一个是作品表,带播放、点赞、评论、分享和收藏;一个是评论和回复表,带内容、点赞、时间和 IP 属地。
分步操作
先设好 key:export OKDATA_API_KEY=okd_...。每次返回都有 code(成功为 "ok");列表结果在 data.items,翻页信息在 page;单个对象在 data.item。
快手上要分清三种 ID。作品 ID 是网页链接里 3x 开头的那一段,比如 https://www.kuaishou.com/short-video/3xm4f8kq2ze9wbs。账号 ID 是一串数字,比如 2318476509;大家写在简介里的快手号是另一个东西,对应返回里的 author.username。评论 ID 也是数字。
第一步:搜视频
快手视频搜索除了 query,还有三个可选筛选:sort(默认 relevance,另有 latest、popular)、published_within(day、week 或 month)和 duration(under_1_min、1_to_5_min 或 over_5_min)。一次调用返回约 10 条视频,每次 $0.02,每条有文案 text、作者,以及 metrics.views(播放)、metrics.likes、metrics.comments、metrics.shares 和 metrics.favorites。
curl -G "https://api.okdata.online/v1/kuaishou/videos/search" -H "Authorization: Bearer $OKDATA_API_KEY" \
--data-urlencode 'query=露营装备' --data-urlencode 'sort=popular' \
--data-urlencode 'published_within=month' --data-urlencode 'duration=under_1_min'
第二步:刷新一条作品的数据
快手作品详情用 id(3x 开头那段)或 url,分享按钮复制出来的 v.kuaishou.com 短链也可以当 url 传。每次 $0.002,很便宜,适合以后反复查同一条作品的数据,比如每天查一次看增长。
curl -G "https://api.okdata.online/v1/kuaishou/videos/get" -H "Authorization: Bearer $OKDATA_API_KEY" \
--data-urlencode 'id=3xm4f8kq2ze9wbs'
第三步:拉作者的作品
快手账号作品的 id 填数字用户 ID,从作品的 author.id 读。sort 可选 latest(默认)或 popular。每页约 20 条,每页 $0.02。
curl -G "https://api.okdata.online/v1/kuaishou/users/videos/list" -H "Authorization: Bearer $OKDATA_API_KEY" \
--data-urlencode 'id=2318476509' --data-urlencode 'sort=popular'
第四步:读评论
快手作品评论用作品的 id 或 url,按从新到旧返回一级评论,每页约 10 条,每次 $0.002。每条有 id、text、author.name、likes、published_at 和 ip_location。下一页就把 page.next_cursor 作为 cursor 传回去。
curl -G "https://api.okdata.online/v1/kuaishou/videos/comments/list" -H "Authorization: Bearer $OKDATA_API_KEY" \
--data-urlencode 'id=3xm4f8kq2ze9wbs'
第五步:展开回复
快手评论回复要两个参数:id 是评论 ID,post_id 是评论所在作品的 3x ID。每页约 20 条回复,每次 $0.002,每条的 parent_id 指向那条评论。
curl -G "https://api.okdata.online/v1/kuaishou/comments/replies/list" -H "Authorization: Bearer $OKDATA_API_KEY" \
--data-urlencode 'id=927364810552' --data-urlencode 'post_id=3xm4f8kq2ze9wbs'
第六步:完整脚本
所有调用都走一个函数:检查 body["code"],作品被删时返回 None,遇到限流或上游繁忙就用同一个 Idempotency-Key 重试,重试不会重复扣费。翻页用一个带页数上限的生成器。
import csv
import os
import time
import uuid
import requests
API = "https://api.okdata.online"
KEY = os.environ["OKDATA_API_KEY"]
QUERY = "露营装备"
VIDEO_PAGES = 1 # 作者作品读几页;每页一次调用
COMMENT_PAGES = 1 # 评论读几页;每页一次调用
def call(path, **params):
headers = {"Authorization": f"Bearer {KEY}", "Idempotency-Key": str(uuid.uuid4())}
for attempt in range(4):
body = requests.get(API + path, headers=headers, params=params, timeout=60).json()
if body["code"] == "ok":
return body
if body["code"] == "not_found":
return None # 已删除或不公开:不扣费
if body.get("retry") in ("yes", "same_key"):
time.sleep(body.get("retry_after_seconds") or 2 ** attempt)
continue
raise RuntimeError(f"{body['code']}: {body['message']} (request {body['request_id']})")
raise RuntimeError(f"{path}: 重试 4 次仍然失败")
def paged(path, max_pages, **params):
cursor = None
for _ in range(max_pages):
body = call(path, **params, **({"cursor": cursor} if cursor else {}))
if body is None:
return
yield from body["data"]["items"]
if not body["page"]["has_more"]:
return
cursor = body["page"]["next_cursor"]
def video_row(v):
m = v["metrics"]
return [v["id"], v["published_at"], v["author"]["id"], v["author"]["name"], v["text"],
m["views"], m["likes"], m["comments"], m["shares"], m["favorites"]]
hits = call("/v1/kuaishou/videos/search", query=QUERY, sort="popular", published_within="month")["data"]["items"]
if not hits:
raise SystemExit("没有搜到作品")
top = max(hits, key=lambda v: v["metrics"]["views"] or 0)
detail = call("/v1/kuaishou/videos/get", id=top["id"])
video = detail["data"]["item"] if detail else top
author_videos = list(paged("/v1/kuaishou/users/videos/list", VIDEO_PAGES, id=video["author"]["id"], sort="popular"))
comments = list(paged("/v1/kuaishou/videos/comments/list", COMMENT_PAGES, id=video["id"]))
replies = []
if comments:
best = max(comments, key=lambda c: c["likes"] or 0)
replies = list(paged("/v1/kuaishou/comments/replies/list", 1, id=best["id"], post_id=video["id"]))
with open("kuaishou_videos.csv", "w", newline="", encoding="utf-8-sig") as f:
out = csv.writer(f)
out.writerow(["video_id", "published_at", "author_id", "author", "caption", "plays", "likes", "comments", "shares", "saves"])
out.writerows(video_row(v) for v in [video, *author_videos])
with open("kuaishou_comments.csv", "w", newline="", encoding="utf-8-sig") as f:
out = csv.writer(f)
out.writerow(["video_id", "comment_id", "parent_id", "text", "user", "likes", "ip_location", "published_at"])
for c in comments + replies:
out.writerow([video["id"], c["id"], c["parent_id"], c["text"], c["author"]["name"], c["likes"], c["ip_location"], c["published_at"]])
一共 5 次调用,就是上面的示例。作品详情、评论和回复这三个接口便宜,搜索和账号作品每次贵一些,所以要控制花费先给这两个设上限。评论读 50 页(约 500 条)是 $0.10。
注意事项
- 粉丝数。 作品里有作者 ID、昵称和认证,但
author.followers是 null。要粉丝数、获赞总数和作品数,用账号 ID 调快手账号信息。 - 回复数。 快手评论的
replies返回 null,所以要按点赞或者读内容来挑要展开的评论,再调回复接口。 - 评论顺序。 从新到旧,没有按热度排的选项。想看这周大家在说什么,这个顺序反而合适。
- 图集。 搜索结果里有一部分是图集而不是视频,它们的
type是image。 - 更多字段。 加上
view=full,作品会多出ext.duration_ms和ext.ip_location(发布地)。fields=可以精简返回。两者都不影响价格。 - 不收钱的情况。 已删除或不公开的作品返回
not_found,和其他错误一样不扣费。24 小时内用同一个Idempotency-Key重发,会拿回存下的结果,meta.replayed为true。
示例花费
带筛选搜一次“露营装备”,查播放最多那条的详情,拉作者一页作品、这条视频一页评论,再展开点赞最多那条评论的回复
| 接口 | 调用次数 | 单价 | 小计 |
|---|---|---|---|
| 快手视频搜索 | 1 | $0.02 | $0.02 |
| 快手作品详情 | 1 | $0.002 | $0.002 |
| 快手账号作品 | 1 | $0.02 | $0.02 |
| 快手作品评论 | 1 | $0.002 | $0.002 |
| 快手评论回复 | 1 | $0.002 | $0.002 |
| 合计 | 5 | $0.046 |
按本页生成时的价格计算。失败的调用不扣费。
在你的 AI 里用(MCP)
先接好 MCP 服务,然后直接说你要什么。智能体会自己找到这些接口、看清价格,再用你的余额调用。
可以这样说在快手搜最近一个月的“露营装备”视频,按最热排。取播放最多的那条,给我它的数据、作者最热的几条作品、最新的评论,以及点赞最多那条评论下的回复。
智能体第一次调用 call 工具时发送的内容
{
"endpoint": "kuaishou.videos.search",
"params": {
"query": "露营装备"
},
"idempotency_key": "<新的 UUID>"
}