前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >源代码和软件 | 采集 1w+ B 站视频评论(年底更新版)

源代码和软件 | 采集 1w+ B 站视频评论(年底更新版)

作者头像
月小水长
发布2023-12-30 14:37:48
4343
发布2023-12-30 14:37:48
举报
文章被收录于专栏:月小水长

欢迎关注」,唯一笔者是 BuyiXiao,又名小布衣、肖不已。 BuyiXiao,何许人也?本衡州一乡野村夫,身高八尺不足,年方二十有余;弱冠之年曾求学于潭州,为谋生计,背井离乡,远赴京畿,我本南人,不习北土,兼有故友,威逼利诱,急于星火,遂下岭南,打工未半,中道创业,所为何业?赛博朋克,智能硬件;假工程师之名,行农民工之实,满腹经纶,无用书生,善于自黑,贻笑大方。 笔者水平有限,可能暂时无法将非常干货的教程讲的不拖泥带水又不哗众取宠,公众号文章诸多遗漏或不妥之处。 另外,文末点下「」和「在看」,这样每次新文章推送,就会第一时间出现在你的订阅号列表里。

转眼又到年关,不知不觉距离 2023 bilibili 视频评论爬虫 发布已经过去 6 个月了,当时一并分享了 python 3 源代码和 windows 打包软件,收到了不少反馈。

然后陆陆续续收到了一些代码无法运行、软件双击崩溃之类的 bug 反馈,应该是要更新了,本着不拖到 2024 再更新的原则,就有了今天这次推送。

其实报错的原因就一个:

errors.JSONDecodeError: Expecting value

一个请求的响应解析错误,而这个请求又是冗余的,直接把请求发起和响应全部删除掉就行,即原来的代码 58-62 行全部删除,又加了屏蔽代理等小改动,于是代码变成了下面这样:

代码语言:javascript
复制
# -*- 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

os.environ['NO_PROXY'] = 'bilibili.com'


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']
    input_bvs = input('请输入 bv 号,多个 bv 号以空格分隔:')
    bvs = input_bvs.split(' ')
    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)

        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()

直接将上述代码保存到 py 文件中,无需任何修改,可以在 cmd 中调用 python 环境或者直接在 Pycharm 运行该文件,输入待抓取的 b 站 bv 号就可开始采集该视频的评论~

同时考虑到很多读者朋友们没有 Python 环境,或者根本不想安装 Python 环境,一如既往地提供了 windows exe 版本。

年底老板让你写公司的 B 站账号总结的时候,

直接拿出这个工具,一顿操作,把公司账号的视频下面的评论采集到本地,

然后 Excel 打开分析,或者用本号分析过的一些在线分析工具,

同事还在肉眼总结的时候,你已经得出漂亮的分析结果了,一跃成为办公室最靓的仔,来年开工的升职加薪,铁定少不了你;

如果你把这个工具发给同事,同事成为靓仔升职加薪了,他能忘得了你嘛,提拔你也是分分钟的事好吧。

In a word,有需求的用好这个工具,赢麻了

多多点赞评论转发,读者朋友的支持是更新的最大动力

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-12-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 月小水长 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档