首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python 抖音爬虫从 0 到 1 实战:环境配置与数据爬取全教程

Python 抖音爬虫从 0 到 1 实战:环境配置与数据爬取全教程

原创
作者头像
小白学大数据
发布2026-02-24 16:39:53
发布2026-02-24 16:39:53
5660
举报

在短视频商业化、内容分析、用户行为研究等场景中,抖音公开数据的爬取已成为技术从业者的必备技能。相较于通用网站爬虫,抖音基于移动端的加密机制、反爬策略增加了开发难度,但只要掌握核心逻辑,新手也能从 0 到 1 搭建完整的爬虫体系。本文将以实战为导向,从环境配置、接口分析、代码实现到异常处理,全方位拆解 Python 抖音爬虫的开发流程,确保每一步都可复现、可落地。

一、前置声明:合规与风险提示

在开始开发前,需明确核心原则,避免触碰法律和平台规则红线:

  1. 仅爬取抖音公开可见的数据(如公开作品、用户主页信息),不获取私密数据、付费内容或未授权接口数据;
  2. 遵守robots.txt协议,控制请求频率(建议单 IP 请求间隔≥5 秒),避免对服务器造成压力;
  3. 本文代码仅用于技术学习,禁止用于商业牟利,因违规使用产生的一切风险由使用者自行承担。

二、环境配置:从 0 搭建爬虫开发环境

环境配置是爬虫开发的基础,也是新手最易踩坑的环节。以下以 Windows 系统为例(Mac/Linux 仅需微调终端命令),完成 Python 环境和依赖库的搭建。

2.1 Python 版本选择与安装

推荐使用 Python 3.8~3.10 版本(兼容性最佳,过高版本可能导致部分第三方库适配异常):

  1. 下载地址:Python 官方下载页,选择对应系统的安装包;
  2. 安装时务必勾选「Add Python to PATH」,避免手动配置环境变量;
  3. 验证安装:打开 CMD 命令提示符,输入python --version,若输出Python 3.9.x等版本信息,说明安装成功。

2.2 核心依赖库安装

抖音爬虫需依赖以下库实现请求发送、数据解析和反爬规避,新建requirements.txt文件,写入如下内容:

txt

代码语言:txt
复制
requests==2.31.0  # 发送HTTP请求,获取接口数据
fake-useragent==1.4.0  # 生成随机User-Agent,模拟真实浏览器
json5==0.9.14  # 解析抖音非标准JSON数据
time  # 内置库,控制请求延迟
random  # 内置库,生成随机间隔
logging  # 内置库,记录爬取日志

2.3 反爬基础配置

抖音对单 IP 高频请求敏感,需提前准备基础反爬配置:

  1. User-Agent 模拟:抖音优先识别移动端请求,推荐使用安卓端 User-Agent 模板(可从浏览器开发者工具中复制);
  2. Cookie 获取:登录抖音网页版(https://www.douyin.com/),按 F12 打开开发者工具→Network→任意请求→Headers→复制 Cookie 字段(用于模拟登录状态);
  3. 代理(可选):若无代理,需将请求间隔设置为 8~10 秒;有条件可使用高匿代理池,降低 IP 封禁风险。

三、核心实战:抖音公开作品数据爬取

抖音数据接口分为网页版和移动端,网页版接口反爬较弱、上手简单,适合新手。本节以「爬取指定用户公开作品数据」为例,拆解完整爬取逻辑。

3.1 接口分析:找到数据请求的核心 URL

爬虫的核心是定位返回 JSON 数据的接口,步骤如下:

  1. 打开抖音网页版,搜索目标用户并进入其主页;
  2. 按 F12 打开开发者工具,切换到「Network」标签,刷新页面;
  3. 筛选「XHR/Fetch」类型请求,找到包含「aweme/post」的请求(抖音作品核心接口),其 URL 格式如下(脱敏):

plaintext

代码语言:txt
复制
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 条。

3.2 完整代码实现:爬取用户公开作品

以下是可直接运行的完整代码,包含请求封装、数据解析、分页爬取、日志记录四大核心模块,代码附带详细注释:

python

运行

代码语言:txt
复制
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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前置声明:合规与风险提示
  • 二、环境配置:从 0 搭建爬虫开发环境
    • 2.1 Python 版本选择与安装
    • 2.2 核心依赖库安装
    • 2.3 反爬基础配置
  • 三、核心实战:抖音公开作品数据爬取
    • 3.1 接口分析:找到数据请求的核心 URL
    • 3.2 完整代码实现:爬取用户公开作品
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档