源代码和工具 | 2023 bilibili 视频评论爬虫,单条视频最多可爬取 10000 条评论

月小水长

共 12080字,需浏览 25分钟

 ·

2023-06-21 18:50

欢迎关注公众号「月小水长」,唯一笔者是 BuyiXiao,又名小布衣、肖不已。 

BuyiXiao,何许人也?本衡州一乡野村夫,身高八尺不足,年方二十有余;弱冠之年曾求学于潭州,为谋生计,背井离乡,远赴京畿,我本南人,不习北土,兼有故友,威逼利诱,急于星火,遂下岭南,打工未半,中道创业,所为何业?赛博朋克,智能硬件;假工程师之名,行农民工之实,满腹经纶,无用书生,善于自黑,贻笑大方。 

笔者水平有限,可能暂时无法将非常干货的教程讲的不拖泥带水又不哗众取宠,公众号文章诸多遗漏或不妥之处,可以加月小水长微信「2391527690」备注「学校专业/研究方向/工作岗位」进行交流。

另外,文末点下「」和「在看」,这样每次新文章推送,就会第一时间出现在你的订阅号列表里。

我帮一些没玩过 b 站的朋友问了 ChatGPT,b 站是什么,它是这么回答我的。

Bilibili 是一家中国的视频分享平台,也被称为“哔哩哔哩”或“B站”,其社区调性可以用年轻、有趣、创新、多元等词语来描述。Bilibili的用户主要是年轻人,其中以学生和年轻白领居多,他们倾向于追求个性化、独特的内容,同时对新鲜事物和潮流保持敏感。

在 Bilibili 上,用户可以创建自己的账号并上传、观看、评论各种类型的视频,包括动画、游戏、音乐、舞蹈、电影等等。Bilibili注重用户互动,鼓励用户之间进行交流和分享,因此 Bilibili 社区中的用户活跃度较高。

正因为 b 站用户群体巨大,公众号后台也有不少读者留言需要 b 站爬虫的,今天正是分享的是 b 站评论爬虫,可以一键导出指定 b 站视频的评论。

以前分享过 b 站评论的工具(开箱即用的 B 站评论抓取工具),到第今年三个年头已经失效,有一些 bug 需要修复今天也算是这篇分享的延续,同时文末附上源代码和 exe 工具链接,不想看细节的可以直接拉到文末

测试了下这份代码/工具大概单个视频最多能爬到 10000 条以上的评论。

b 站没啥反爬的,带个 User-Agent 就能请求数据。

headers = {
    'User-Agent''Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3970.5 Safari/537.36',
    'Referer''https://www.bilibili.com/'
}

请求评论数据主要注意下 F12 寻找评论的 url 地址即可。

数据保存时记得把时间戳转成时间字符串,

def intToStrTime(a):
    b = time.localtime(a)  # 转为日期字符串
    c = time.strftime("%Y/%m/%d %H:%M:%S", b)  # 格式化字符串
    return c

如果以{标题}.csv 命名字符串,记得先把标题处理下以符合文件命名的规则。

def validateTitle(title):
    re_str = r"[\/\\\:\*\?\"\<\>\|]"  # '/ \ : * ? " < > |'
    new_title = re.sub(re_str, "_", title)  # 替换为下划线
    return new_title

用个 for 循环遍历要爬取的视频的 bv 号,实现一次爬取多个视频的评论的功能。

最后构造 dataframe,边爬取边保存。

需要注意的是,该爬虫没有抓取全部二级评论(回复,楼中楼),只是回复的前 3 条,如需爬取所有的自行展开回复,扩展该爬虫代码即可。

以 b 站下面这个热门视频为例,

标题:不开除张某保研资格,就是寒了天下人的心!

链接:https://www.bilibili.com/video/BV1Zo4y1N7f1

BV 号:BV1Zo4y1N7f1

抓取的结果字段包括评论时间、评论用户名、评论内容和评论点赞数四个字段,如下图所示。

关于这个 CSV 结果文件的获取可以查看今天的另外一篇推送。

源代码已经打包成 exe,不需要 Python 环境,双击即可运行,需要的读者公众号后台回复【2023 b站评论提取工具】即可获取下载链接。

最后附上源代码,欢迎点赞、转发、留言,支持原创更好的创作。

# -*- coding: utf-8 -*-
# 作者:             inspurer(月小水长)
# 创建时间:          2020/10/30 23:48
# 运行环境           Python3.6+
# github            https://github.com/inspurer
# qq邮箱            2391527690@qq.com
# 微信公众号         月小水长(ID: inspurer)
# 文件备注信息       回复没有展开

import requests
import os
from time import sleep
import json
import time
import pandas as pd

import re


def intToStrTime(a):
    b = time.localtime(a)  # 转为日期字符串
    c = time.strftime("%Y/%m/%d %H:%M:%S", b)  # 格式化字符串
    return c


headers = {
    'User-Agent''Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3970.5 Safari/537.36',
    'Referer''https://www.bilibili.com/'
}


def validateTitle(title):
    re_str = r"[\/\\\:\*\?\"\<\>\|]"  # '/ \ : * ? " < > |'
    new_title = re.sub(re_str, "_", title)  # 替换为下划线
    return new_title


def main():
    save_folder = 'Comment'
    if not os.path.exists(save_folder):
        os.mkdir(save_folder)
    bvs = ['BV1Zo4y1N7f1']
    for bv in bvs:
        print(bv)
        response = requests.get(url='https://www.bilibili.com/video/{}'.format(bv), headers=headers)

        res = re.findall('<script>window.__INITIAL_STATE__=(.*)?;\(function\(\)', response.text, re.S)

        json_data = json.loads(res[0])
        if 'message' in json_data['error']:
            print(json_data['error']['message'])
            continue
        aid = json_data['aid']
        title = json_data['videoData']['title']

        title = validateTitle(title)

        video_info_url = 'https://api.bilibili.com/x/web-interface/archive/stat?aid={}'.format(aid)
        res_json = requests.get(url=video_info_url, headers=headers).json()
        like_count, coin_count, collection_count = res_json['data']['like'], res_json['data']['coin'], res_json['data'][
            'favorite']
        # print(aid, title, like_count, coin_count, collection_count)

        comment_url = 'https://api.bilibili.com/x/v2/reply?callback=jQueryjsonp=jsonp&pn={}&type=1&oid={}&sort=2&_=1594459235799'

        response = requests.get(url=comment_url.format(1, aid), headers=headers)

        total_page = json.loads(response.text)['data']['page']['count'] // 20 + 1
        page = 1
        is_root, uname, comments, times, likes = [], [], [], [], []
        while True:
            data = json.loads(response.text)['data']['replies']
            print(data)
            if not data:
                data = json.loads(response.text)['data']
                if 'hots' in data.keys():
                    data = data['hots']
                else:
                    break
            for row in data:
                print('根评论', row['member']['uname'], row['content']['message'])
                is_root.append('是')
                times.append(intToStrTime(row['ctime']))
                uname.append(row['member']['uname'])
                comments.append(row['content']['message'])
                likes.append(row['like'])
                if row.get('replies'):
                    for crow in row['replies']:
                        is_root.append('否')
                        times.append(intToStrTime(crow['ctime']))
                        uname.append(crow['member']['uname'])
                        comments.append(crow['content']['message'])
                        likes.append(crow['like'])
                        print('---子评论', crow['member']['uname'], crow['content']['message'])

            page += 1
            if page > total_page:
                break
            sleep(1)
            response = requests.get(url=comment_url.format(page, aid), headers=headers)

            # 边爬取边保存
            df = pd.DataFrame(
                {'评论时间': times, '评论者': uname, '评论内容': [''.join(comment.split()) for comment in comments], '点赞数': likes})
            df.to_csv(f'{save_folder}/{title}.csv', encoding='utf-8-sig', index=False)

            print(f'\n\n已经保存 {df.shape[0]} 条评论到 {save_folder}/{title}.csv\n\n')

            sleep(1)

        # 每抓完 1 条视频的评论休眠 10s
        sleep(10)


if __name__ == '__main__':
    main()

往期精选


自研小红书评论区自动回复软件,于繁杂的客服流水作业中抽身

2023 微博评论爬虫 | 突破 1000 页限制,抓取 10w 条微博评论

CBDB | 可视化历史名人的关系和足迹

小红书帖子和评论自助提取工具

浏览 41
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报