dy评论数据爬取实战:基于DrissionPage的自动化采集方案

在短视频数据分析场景中,dy评论数据的采集是重要的一环。本文将基于DrissionPage自动化框架,手把手教你实现dy视频评论、作者信息、视频元数据的完整爬取,并将数据结构化存储到CSV文件中。

一、技术选型与核心优势

1. 核心依赖库

  • DrissionPage:新一代Python自动化工具,融合了Selenium和Requests的优势,既可以操作浏览器渲染页面,又能监听网络请求获取原始数据,相比传统爬虫更稳定。

  • datetime/re:分别用于时间戳转换和文本正则提取。

  • csv:Python内置模块,用于结构化存储爬取的数据。

  • time:用于添加等待时间,适配页面加载节奏。

2. 方案优势

  • 采用网络请求监听而非页面元素解析获取评论,数据更完整、效率更高;

  • 精准的元素定位策略,适配抖音页面结构;

  • 完善的异常处理机制,降低爬取中断概率;

  • 结构化数据输出,便于后续分析。

二、核心功能实现

1. 环境准备

首先安装核心依赖:

python 复制代码
pip install DrissionPage

2. 完整代码实现

python 复制代码
# 导入自动化模块的安装:需要安装 pip install DrissionPage
from DrissionPage import ChromiumPage
# 导入时间转换模块
from datetime import datetime
# 导入csv模块,用于操作CSV文件
import csv
# 导入时间模块,用于添加短暂等待,提高稳定性
import time
import re  # 提取视频标题和标签


def extract_video_info(page):
    """提取视频标题和以#开头的标签"""
    try:
        # 获取视频标题
        title_ele = page.ele('tag:h1', timeout=5)
        title = title_ele.text.strip() if title_ele else '未知标题'

        # 提取以#开头的标签
        tag_pattern = re.compile(r'#\S+')
        tags = tag_pattern.findall(title)
        # 纯标题(去掉标签)
        pure_title = tag_pattern.sub('', title).strip() or title

        return pure_title, tags
    except Exception as e:
        print(f"提取视频信息失败:{e}")
        return '未知标题', []


def extract_author_info(page):
    """
    精准适配版:提取作者信息(仅保留方式1的精准匹配)
    只匹配class+data属性结构,移除所有兜底方案
    """
    author_info = {
        '作者名称': '未知',
        '粉丝数': '0',
        '获赞数': '0'
    }

    try:
        # ========== 第一步:提取作者名称(仅保留精准匹配) ==========
        # 仅保留方式1:匹配class=q5XQ42ql + data-click-from="title"
        author_ele = page.ele('xpath://div[@class="q5XQ42ql" and @data-click-from="title"]', timeout=3)
        if author_ele:
            # 提取该div下所有span的文本(自动拼接嵌套span的内容)
            author_name = author_ele.text.strip()
            if author_name:
                author_info['作者名称'] = author_name

        # ========== 第二步:提取粉丝数和获赞数(通用定位) ==========
        stat_eles = page.eles('xpath://span[contains(text(), "粉丝") or contains(text(), "获赞") or contains(text(), "赞")]')

        for ele in stat_eles:
            stat_text = ele.text.strip()
            if '粉丝' in stat_text:
                if stat_text.replace('粉丝', '').strip().isdigit() or '万' in stat_text or '亿' in stat_text:
                    author_info['粉丝数'] = stat_text.replace('粉丝', '').strip()
                else:
                    next_ele = ele.next()
                    if next_ele and next_ele.text.strip():
                        author_info['粉丝数'] = next_ele.text.strip()
            elif '获赞' in stat_text or '赞' in stat_text:
                if stat_text.replace('获赞', '').replace('赞',
                                                       '').strip().isdigit() or '万' in stat_text or '亿' in stat_text:
                    author_info['获赞数'] = stat_text.replace('获赞', '').replace('赞', '').strip()
                else:
                    next_ele = ele.next()
                    if next_ele and next_ele.text.strip():
                        author_info['获赞数'] = next_ele.text.strip()

    except Exception as e:
        print(f"提取作者信息失败:{e}")

    return author_info


def main():
    # 让用户输入视频链接
    video_url = input("请输入抖音视频链接(回车使用默认链接):").strip()
    if not video_url:
        video_url = 'https://v.douyin.com/y5R-HvKi_vE'

    # 使用with语句管理文件资源,自动关闭文件
    with open('douyin_comments.csv', mode='w', encoding='utf-8-sig', newline='') as f:
        csv_writer = csv.DictWriter(f, fieldnames=[
            '视频标题', '视频标签', '作者名称', '作者粉丝数', '作者获赞数',
            '昵称', '地区', '日期', '评论'
        ])
        # 写入表头
        csv_writer.writeheader()

        # 打开浏览器(实际浏览对象)
        dp = ChromiumPage()
        # 记录实际爬取成功的页数
        success_page_count = 0
        # 存储视频信息和作者信息
        video_title = '未知标题'
        video_tags = []
        author_info = {'作者名称': '未知', '粉丝数': '0', '获赞数': '0'}

        try:
            # 保留精准的监听规则
            dp.listen.start('comment/list/')
            # 访问目标视频页面
            dp.get(video_url)
            # 延长等待时间(确保作者信息区域完全加载)
            time.sleep(8)

            # 提取视频标题和标签
            video_title, video_tags = extract_video_info(dp)
            # 提取作者信息(仅保留精准匹配)
            author_info = extract_author_info(dp)

            print(f"\n=== 开始爬取 ===")
            print(f"视频标题:{video_title}")
            print(f"视频标签:{','.join(video_tags) if video_tags else '无'}")
            print(f"作者名称:{author_info['作者名称']}")
            print(f"作者粉丝数:{author_info['粉丝数']}")
            print(f"作者获赞数:{author_info['获赞数']}")
            print(f"================\n")

            # 初始化页码和翻页状态
            page_num = 1
            has_next_page = True

            # 循环爬取,直到没有下一页
            while has_next_page:
                print(f'正在采集第 {page_num} 页的数据内容')

                # 等待数据包加载(延长超时时间,提高稳定性)
                resp = dp.listen.wait(timeout=15)
                if not resp:
                    print(f"第 {page_num} 页等待数据包超时,尝试滚动加载...")
                    # 主动滚动触发评论加载
                    dp.scroll.to_bottom()
                    time.sleep(2)
                    resp = dp.listen.wait(timeout=5)
                    if not resp:
                        print(f"第 {page_num} 页仍无数据包,终止爬取")
                        break

                # 获取响应数据
                try:
                    json_data = resp.response.body
                    # 解析数据,获取评论信息所在的列表
                    comments = json_data.get('comments', [])
                    # 如果评论列表为空,说明当前页无数据,终止循环
                    if not comments:
                        print(f"第 {page_num} 页无评论数据,终止爬取")
                        break

                    # 遍历评论列表,提取每条评论具体数据信息
                    for index in comments:
                        try:
                            create_time = index.get('create_time', 0)
                            # 容错处理时间字段
                            if create_time == 0:
                                date = '未知时间'
                            else:
                                date = str(datetime.fromtimestamp(create_time))

                            # 尝试获取地区信息
                            region = index.get('ip_label', '')
                            if not region:
                                ip_client_info = index.get('client_info', {})
                                region = ip_client_info.get('province', '未知')
                        except KeyError as e:
                            print(f"处理单个评论数据出现异常,异常信息:{e},跳过该评论")
                            continue

                        dit = {
                            '视频标题': video_title,
                            '视频标签': ','.join(video_tags),
                            '作者名称': author_info['作者名称'],
                            '作者粉丝数': author_info['粉丝数'],
                            '作者获赞数': author_info['获赞数'],
                            '昵称': index.get('user', {}).get('nickname', '未知'),
                            '地区': region,
                            '日期': date,
                            '评论': index.get('text', ''),
                        }

                        try:
                            csv_writer.writerow(dit)
                            print(dit)
                        except Exception as e:
                            print(f"写入CSV文件出现异常,异常信息:{e},跳过该数据")

                    # 爬取成功,页数+1
                    success_page_count += 1

                    # 查找下一页元素,判断是否存在
                    next_page = dp.ele('css:.Rcc71LyU', timeout=3)
                    if not next_page:
                        print("未找到下一页元素,终止爬取")
                        break

                    # 尝试滚动到下一页按钮,失败则终止
                    try:
                        dp.scroll.to_see(next_page)
                        time.sleep(1)
                        next_page.click()
                        page_num += 1
                        time.sleep(3)
                    except Exception as e:
                        print(f"滚动/点击下一页按钮失败,异常信息:{e},终止爬取")
                        break

                except Exception as e:
                    print(f"第 {page_num} 页数据处理出现异常,异常信息:{e},终止爬取")
                    break

            print(f"\n=== 爬取结束 ===")
            print(f"共采集了 {success_page_count} 页评论数据")
            print(f"数据已保存到:douyin_comments.csv")
        except Exception as e:
            print(f"爬取过程中出现致命异常:{e}")
        finally:
            # 无论是否异常,都关闭浏览器
            dp.quit()
            print("浏览器已关闭")


if __name__ == '__main__':
    main()

3.dy链接:

复制代码
https://v.douyin.com/y5R-HvKi_vE

4.代码效果图:

5.csv效果图:

三、关键模块解析

1. 视频信息提取(extract_video_info)

  • 通过tag:h1定位视频标题元素,兼容标题不存在的异常情况;

  • 使用正则表达式#\S+提取视频标签,并过滤标签得到纯标题;

  • 完整的try-except包裹,确保单个模块异常不影响整体流程。

2. 作者信息提取(extract_author_info)

  • 精准定位 :通过XPath组合classdata-click-from属性定位作者名称,避免页面其他元素干扰;

  • 数值兼容:处理粉丝数/获赞数的多种展示形式(纯数字、带万/亿单位、数值在相邻元素);

  • 默认值兜底:所有字段设置默认值,防止数据缺失导致CSV写入失败。

3. 核心爬取逻辑(main函数)

(1)网络请求监听
python 复制代码
dp.listen.start('comment/list/')

监听抖音评论接口,直接获取原始JSON数据,相比解析页面元素更高效、数据更完整。

(2)分页处理
  • 等待接口响应,超时后主动滚动页面触发加载;

  • 定位下一页按钮并点击,实现自动翻页;

  • 统计成功爬取页数,便于后续核对数据。

(3)数据存储
  • 使用csv.DictWriter结构化写入数据,字段包括视频信息、作者信息、评论信息;

  • UTF-8编码确保中文正常显示,newline=''避免空行问题。

四、使用说明与注意事项

1. 使用步骤

  1. 安装依赖:pip install DrissionPage

  2. 运行代码,输入抖音视频链接(或直接回车使用默认链接);

  3. 等待爬取完成,数据会保存到douyin_comments.csv文件。

2. 注意事项

  • 页面结构适配:抖音页面结构可能会更新,若作者信息/评论无法提取,需更新XPath/CSS定位器;

  • 等待时间调整 :网络慢的环境可适当增加time.sleep()的时间;

  • 反爬机制:请勿高频次爬取,避免IP被限制;

  • 异常处理:代码已做基础异常处理,可根据实际需求扩展。

五、功能扩展方向

  1. 多视频批量爬取:读取视频链接列表,循环爬取多个视频的评论;

  2. 数据去重:对重复评论进行过滤,提高数据质量;

  3. 情感分析:结合自然语言处理库(如jieba、snownlp)对评论进行情感倾向分析;

  4. 可视化展示:使用matplotlib/echarts将评论地区、发布时间等维度可视化;

  5. 增量爬取:记录已爬取的评论ID,只获取新增评论。

总结

本文基于DrissionPage实现了抖音评论数据的自动化爬取,核心亮点在于:

  1. 结合浏览器渲染和网络请求监听,兼顾页面元素提取和原始数据获取;

  2. 精准的元素定位和完善的异常处理,提高爬取稳定性;

  3. 结构化数据输出,便于后续分析和应用。

该方案既适合数据分析新手快速上手,也可作为基础框架进行二次开发,满足不同的抖音数据采集需求。

相关推荐
Pyeako5 小时前
opencv计算机视觉--LBPH&EigenFace&FisherFace人脸识别
人工智能·python·opencv·计算机视觉·lbph·eigenface·fisherface
小陶的学习笔记5 小时前
python~基础
开发语言·python·学习
多恩Stone5 小时前
【3D AICG 系列-9】Trellis2 推理流程图超详细介绍
人工智能·python·算法·3d·aigc·流程图
ID_180079054735 小时前
Python结合淘宝关键词API进行商品价格监控与预警
服务器·数据库·python
lsx2024065 小时前
JavaScript 条件语句
开发语言
玄同7655 小时前
Python 自动发送邮件实战:用 QQ/163 邮箱发送大模型生成的内容
开发语言·人工智能·python·深度学习·机器学习·邮件·邮箱
岱宗夫up5 小时前
神经网络(MLP)在时间序列预测中的实践应用
python
我的xiaodoujiao5 小时前
使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 46--撰写 README项目说明文档文件
python·学习·测试工具·pytest
索荣荣5 小时前
Maven配置文件(pom.xml)终极指南
java·开发语言