
在短视频商业化、内容分析、用户行为研究等场景中,抖音公开数据的爬取已成为技术从业者的必备技能。相较于通用网站爬虫,抖音基于移动端的加密机制、反爬策略增加了开发难度,但只要掌握核心逻辑,新手也能从 0 到 1 搭建完整的爬虫体系。本文将以实战为导向,从环境配置、接口分析、代码实现到异常处理,全方位拆解 Python 抖音爬虫的开发流程,确保每一步都可复现、可落地。
在开始开发前,需明确核心原则,避免触碰法律和平台规则红线:
robots.txt协议,控制请求频率(建议单 IP 请求间隔≥5 秒),避免对服务器造成压力;环境配置是爬虫开发的基础,也是新手最易踩坑的环节。以下以 Windows 系统为例(Mac/Linux 仅需微调终端命令),完成 Python 环境和依赖库的搭建。
推荐使用 Python 3.8~3.10 版本(兼容性最佳,过高版本可能导致部分第三方库适配异常):
python --version,若输出Python 3.9.x等版本信息,说明安装成功。抖音爬虫需依赖以下库实现请求发送、数据解析和反爬规避,新建requirements.txt文件,写入如下内容:
txt
requests==2.31.0 # 发送HTTP请求,获取接口数据
fake-useragent==1.4.0 # 生成随机User-Agent,模拟真实浏览器
json5==0.9.14 # 解析抖音非标准JSON数据
time # 内置库,控制请求延迟
random # 内置库,生成随机间隔
logging # 内置库,记录爬取日志抖音对单 IP 高频请求敏感,需提前准备基础反爬配置:
抖音数据接口分为网页版和移动端,网页版接口反爬较弱、上手简单,适合新手。本节以「爬取指定用户公开作品数据」为例,拆解完整爬取逻辑。
爬虫的核心是定位返回 JSON 数据的接口,步骤如下:
plaintext
https://www.douyin.com/aweme/v1/web/aweme/post/?sec_uid=【用户加密ID】&count=20&max_cursor=0&aid=6383关键参数说明:
sec_uid:用户唯一加密标识,从用户主页 URL 或接口请求中提取;max_cursor:分页游标,初始为 0,每次请求返回下一页的游标值,用于加载更多作品;count:每页返回的作品数量,默认 20 条。以下是可直接运行的完整代码,包含请求封装、数据解析、分页爬取、日志记录四大核心模块,代码附带详细注释:
python
运行
import requests
import json5
import time
import random
import logging
from fake_useragent import UserAgent
# 配置日志,记录爬取过程和异常
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[logging.FileHandler("douyin_spider.log", encoding="utf-8"), logging.StreamHandler()]
)
class DouYinCrawler:
def __init__(self):
"""初始化爬虫配置:请求头、代理、Cookie"""
self.ua = UserAgent()
# 请求头:模拟移动端浏览器,需替换为自己的Cookie
self.headers = {
"User-Agent": self.ua.random,
"Referer": "https://www.douyin.com/",
"Accept": "application/json, text/plain, */*",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cookie": "请替换为自己的抖音网页版Cookie" # 从浏览器开发者工具复制
}
# 代理配置(无代理则注释以下两行)
self.proxies = {
"http": "http://你的代理IP:端口",
"https": "https://你的代理IP:端口"
}
def get_user_awemes(self, sec_uid, max_cursor=0):
"""
爬取单页用户作品数据
:param sec_uid: 用户加密ID
:param max_cursor: 分页游标
:return: 作品数据列表、下一页游标
"""
# 核心请求URL
url = f"https://www.douyin.com/aweme/v1/web/aweme/post/?sec_uid={sec_uid}&count=20&max_cursor={max_cursor}&aid=6383"
try:
# 发送GET请求,设置超时时间10秒
response = requests.get(
url=url,
headers=self.headers,
# proxies=self.proxies, # 无代理则注释此行
timeout=10
)
# 检查请求状态码
response.raise_for_status()
# 解析JSON数据(抖音返回数据可能含特殊字符,用json5解析)
data = json5.loads(response.text)
aweme_list = data.get("aweme_list", [])
next_cursor = data.get("max_cursor", 0) # 下一页游标
if not aweme_list:
logging.info("当前页无作品数据,爬取结束")
return [], 0
# 提取核心字段(可根据需求扩展)
result = []
for aweme in aweme_list:
item = {
"作品ID": aweme.get("aweme_id"),
"作品标题": aweme.get("desc", "无标题"),
"发布时间": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(aweme.get("create_time"))),
"点赞数": aweme.get("statistics", {}).get("digg_count", 0),
"评论数": aweme.get("statistics", {}).get("comment_count", 0),
"分享数": aweme.get("statistics", {}).get("share_count", 0),
"作品链接": f"https://www.douyin.com/video/{aweme.get('aweme_id')}"
}
result.append(item)
logging.info(f"成功爬取{len(result)}条作品数据")
return result, next_cursor
except requests.exceptions.RequestException as e:
logging.error(f"请求失败:{str(e)}")
return [], 0
except json5.JSON5DecodeError as e:
logging.error(f"数据解析失败:{str(e)}")
return [], 0
def run(self, sec_uid, max_page=5):
"""
爬虫主函数:循环爬取分页数据
:param sec_uid: 用户加密ID
:param max_page: 最大爬取页数
"""
all_data = []
max_cursor = 0
current_page = 1
while current_page <= max_page:
logging.info(f"开始爬取第{current_page}页数据")
# 爬取当前页数据
page_data, next_cursor = self.get_user_awemes(sec_uid, max_cursor)
if not page_data:
break
# 合并数据
all_data.extend(page_data)
# 随机延迟3~6秒,规避反爬
delay = random.uniform(3, 6)
logging.info(f"等待{delay:.2f}秒后爬取下一页")
time.sleep(delay)
# 更新游标和页数
max_cursor = next_cursor
current_page += 1
# 若无下一页数据,终止循环
if max_cursor == 0:
logging.info("已爬取全部作品数据")
break
# 将数据保存为JSON文件
with open("douyin_awemes.json", "w", encoding="utf-8") as f:
json5.dump(all_data, f, ensure_ascii=False, indent=4)
logging.info(f"爬取完成!共获取{len(all_data)}条作品数据,已保存至douyin_awemes.json")
if __name__ == "__main__":
# 实例化爬虫
crawler = DouYinCrawler()
# 替换为目标用户的sec_uid(从抖音网页版接口中提取)
target_sec_uid = "请替换为目标用户的sec_uid"
# 启动爬虫(最多爬取5页)
crawler.run(target_sec_uid, max_page=5)3.3 代码核心说明日志配置:通过logging模块记录爬取过程和异常,便于排查问题;请求封装:将请求逻辑封装为类方法,提高代码复用性,同时加入超时和异常捕获,避免程序崩溃;分页逻辑:通过max_cursor参数实现分页爬取,直到无数据或达到最大页数;数据解析:使用json5替代原生json库,兼容抖音返回的非标准 JSON 数据;反爬优化:加入随机延迟,模拟真人操作节奏,降低被识别为爬虫的概率。3.4 关键参数获取指南代码中需替换的核心参数获取方式:Cookie:抖音网页版登录后,F12→Network→任意请求→Headers→Request Headers→复制 Cookie 字段;sec_uid:进入目标用户主页→F12→Network→筛选「aweme/post」请求→URL 中提取sec_uid参数;代理 IP:若无代理,直接注释proxies=self.proxies一行即可。四、常见问题与解决方案新手在运行代码时易遇到以下问题,针对性解决方案如下:返回 403 Forbidden:Cookie 失效或 User-Agent 被识别,需重新登录抖音获取 Cookie,或更换 User-Agent 模板;数据为空:sec_uid错误或目标用户设置作品隐私权限,需核对sec_uid,或更换公开作品较多的用户测试;IP 被封禁:立即停止爬取,更换 IP / 代理,将请求延迟调整至 10 秒以上;(推荐使用亿牛云爬虫代理)JSON 解析报错:抖音返回数据含特殊字符,确保使用json5库解析,而非原生json库。五、进阶优化方向(可选)基础版本满足学习需求,若需面向生产环境使用,可做以下优化:动态签名获取:抖音的_signature参数是动态生成的,需通过逆向 JS 代码(如 Node.js 执行签名算法)获取;Cookie 自动刷新:使用 Selenium 模拟登录,自动获取最新 Cookie,避免手动替换;异步爬取:用aiohttp替代requests实现异步请求,提升爬取效率(需配合代理池);数据去重:基于作品 ID 建立去重机制,避免重复爬取同一作品。总结本文从 0 到 1 完成了 Python 抖音爬虫的实战开发,核心要点如下:环境配置需优先保证 Python 版本(3.8~3.10)和依赖库的兼容性,Cookie 和 User-Agent 是模拟真实请求的关键;核心爬取逻辑是定位公开数据接口,通过分页游标实现多页数据爬取,同时加入延迟和异常处理规避反爬;新手需重点关注参数替换(Cookie、sec_uid)和合规性,进阶优化可围绕动态签名、Cookie 自动刷新展开。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。