Python基于Tkinter开发一个爬取B站直播弹幕的工具


Posted in Python onMay 06, 2021

简介

使用Python Tkinter开发一个爬取B站直播弹幕的工具,启动后在弹窗中输入房间号即可,弹幕内容会保存在脚本文件同级目录下的.log扩展名的文件中

开发工具

  • python 3.7.9
  • pycharm 2019.3.5

实现代码

import threading
import time
import tkinter.simpledialog  # 使用Tkinter前需要先导入
from tkinter import END, messagebox

import requests

# 全局变量,用于标识线程是否退出
is_exit = True


# B站获取弹幕对象
class Danmu():
    def __init__(self, room_id):
        # 弹幕url
        self.url = 'https://api.live.bilibili.com/xlive/web-room/v1/dM/gethistory'
        # 请求头
        self.headers = {
            'Host': 'api.live.bilibili.com',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0',
        }
        # 定义POST传递的参数
        self.data = {
            'roomid': room_id,
            'csrf_token': '',
            'csrf': '',
            'visit_id': '',
        }
        # 日志写对象
        self.log_file_write = open('danmu.log', mode='a', encoding='utf-8')
        # 读取日志
        log_file_read = open('danmu.log', mode='r', encoding='utf-8')
        self.log = log_file_read.readlines()

    def get_danmu(self):
        # 暂停0.5防止cpu占用过高
        time.sleep(1)
        # 获取直播间弹幕
        html = requests.post(url=self.url, headers=self.headers, data=self.data).json()
        # 解析弹幕列表
        for content in html['data']['room']:
            # 获取昵称
            nickname = content['nickname']
            # 获取发言
            text = content['text']
            # 获取发言时间
            timeline = content['timeline']
            # 记录发言
            msg = timeline + ' ' + nickname + ': ' + text
            # 判断对应消息是否存在于日志,如果和最后一条相同则打印并保存
            if msg + '\n' not in self.log:
                # 打印消息
                listb.insert(END, msg)
                listb.see(END)
                # 保存日志
                self.log_file_write.write(msg + '\n')
                # 添加到日志列表
                self.log.append(msg + '\n')
            # 清空变量缓存
            nickname = ''
            text = ''
            timeline = ''
            msg = ''


# 线程对象
def bilibili(room_id):
    # 创建bDanmu实例
    bDanmu = Danmu(room_id)
    # 获取弹幕
    bDanmu.get_danmu()


class BilibiliThread(threading.Thread):
    def __init__(self, room_id=None):
        threading.Thread.__init__(self)
        self.room_id = room_id

    # 重写run()方法
    def run(self):
        global is_exit
        while not is_exit:
            print(self.room_id)
            bilibili(self.room_id)
            # 暂停防止cpu占用过高
            time.sleep(0.5)


def author():
    # 弹出对话框
    messagebox.showinfo(title='关于', message='作者:阿壮Jonson\n日期:2021年2月4日\n微信公众号:科技猫')


# 实例化object,建立窗口window
window = tkinter.Tk()
# 给窗口的可视化起名字
window.title('BiliBli弹幕查看工具')
# 设定窗口的大小(长 * 宽)
window.minsize(300, 500)
window.geometry('400x600+250+100')

# 菜单栏
menubar = tkinter.Menu(window)
# Open放在菜单栏中,就是装入容器
menubar.add_command(label='关于', command=author)
# 创建菜单栏完成后,配置让菜单栏menubar显示出来
window.config(menu=menubar)

# 创建一个主frame,长在主window窗口上
frame = tkinter.Frame(window)
frame.pack()

# 创建第二层框架frame,长在主框架frame上面
# 上
frame_t = tkinter.Frame(frame)
# 下
frame_b = tkinter.Frame(frame)
frame_t.pack(side=tkinter.TOP)
frame_b.pack(side=tkinter.BOTTOM)

# 创建标签
tkinter.Label(frame_t, text='请输入房间号:', width=10, font=('Arial', 10)).pack(side=tkinter.LEFT)
# 显示成明文形式
default_text = tkinter.StringVar()
default_text.set("21089733")
e1 = tkinter.Entry(frame_t, show=None, width=15, textvariable=default_text, font=('Arial', 10))
e1.pack(side=tkinter.LEFT)


# 定义两个触发事件时的函数start_point和end_point(注意:因为Python的执行顺序是从上往下,所以函数一定要放在按钮的上面)
# 开始
def start_point():
    try:
        room = e1.get()
        room_int = int(room)
        e1.configure(state=tkinter.DISABLED)
        b1.configure(state=tkinter.DISABLED)
        b2.configure(state=tkinter.NORMAL)
        if room_int is not None:
            global is_exit
            is_exit = False
            t = BilibiliThread()
            t.room_id = room_int
            # 创建获取弹幕线程
            t.setDaemon(True)
            t.start()
    except ValueError:
        messagebox.showinfo(title='警告', message='输入的房间号格式不正确,请再次尝试输入!')


# 停止
def end_point():
    global is_exit
    is_exit = True
    e1.configure(state=tkinter.NORMAL)
    b1.configure(state=tkinter.NORMAL)
    b2.configure(state=tkinter.DISABLED)


# 创建并放置两个按钮分别触发两种情况
b1 = tkinter.Button(frame_t, text='开始', width=10, command=start_point, font=('Arial', 10))
b1.pack(side=tkinter.LEFT)
b2 = tkinter.Button(frame_t, text='停止', width=10, command=end_point, font=('Arial', 10))
b2.pack(side=tkinter.LEFT)

# 滚动条
sc = tkinter.Scrollbar(frame_b)
sc.pack(side=tkinter.RIGHT, fill=tkinter.Y)
# Listbox控件
listb = tkinter.Listbox(frame_b, yscrollcommand=sc.set, width=200, height=120)
# 将部件放置到主窗口中
listb.pack(side=tkinter.LEFT, fill=tkinter.BOTH, expand=True)
# 滚动条动,列表跟着动
sc.config(command=listb.yview)

# 主窗口循环显示
window.mainloop()

爬取效果

Python基于Tkinter开发一个爬取B站直播弹幕的工具

Github地址:

https://github.com/jonssonyan/bilibli-danmu

以上就是Python Tkinter开发一个爬取B站直播弹幕的工具的详细内容,更多关于Python 爬取B站直播弹幕的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
详解Python中heapq模块的用法
Jun 28 Python
Python3实现简单可学习的手写体识别(实例讲解)
Oct 21 Python
python3学习笔记之多进程分布式小例子
Feb 13 Python
Windows平台Python编程必会模块之pywin32介绍
Oct 01 Python
Python使用指定字符长度切分数据示例
Dec 05 Python
Python Selenium参数配置方法解析
Jan 19 Python
浅谈SciPy中的optimize.minimize实现受限优化问题
Feb 29 Python
Python urllib.request对象案例解析
May 11 Python
Python图像阈值化处理及算法比对实例解析
Jun 19 Python
python 如何将两个实数矩阵合并为一个复数矩阵
May 19 Python
浅谈pytorch中stack和cat的及to_tensor的坑
May 20 Python
使用pd.merge表连接出现多余行的问题解决
Jun 16 Python
Python爬虫之爬取最新更新的小说网站
May 06 #Python
Python基础之操作MySQL数据库
Python 如何安装Selenium
Django实现在线无水印抖音视频下载(附源码及地址)
Django给表单添加honeypot验证增加安全性
Django利用AJAX技术实现博文实时搜索
May 06 #Python
python 如何获取页面所有a标签下href的值
May 06 #Python
You might like
奉献出一个封装的curl函数 便于调用(抓数据专用)
2013/07/22 PHP
php登陆页的密码处理方式分享
2013/10/14 PHP
js判断浏览器的比较全的代码
2007/02/13 Javascript
escape编码与unescape解码汉字出现乱码的解决方法
2014/07/02 Javascript
纯jquery实现模仿淘宝购物车结算
2015/08/20 Javascript
Bootstrap媒体对象的实现
2016/05/01 Javascript
jQuery插件简单学习实例教程
2016/07/01 Javascript
JS简单实现无缝滚动效果实例
2016/08/24 Javascript
JS实现的样式切换功能tableCSS实例
2016/12/30 Javascript
Javascript 链式作用域详细介绍
2017/02/23 Javascript
JavaScript实现自动跳转文本功能
2017/05/25 Javascript
Node.js学习之TCP/IP数据通讯(实例讲解)
2017/10/11 Javascript
vuex实现登录状态的存储,未登录状态不允许浏览的方法
2018/03/09 Javascript
Vue 仿QQ左滑删除组件功能
2018/03/12 Javascript
使用mpvue搭建一个初始小程序及项目配置方法
2018/12/03 Javascript
js实现多个标题吸顶效果
2020/01/08 Javascript
前端使用crypto.js进行加密的函数代码
2020/08/16 Javascript
Python闭包实现计数器的方法
2015/05/05 Python
python关键字and和or用法实例
2015/05/28 Python
python中类变量与成员变量的使用注意点总结
2017/04/29 Python
python使用生成器实现可迭代对象
2018/03/20 Python
python实现梯度下降算法
2020/03/24 Python
Python初学者需要注意的事项小结(python2与python3)
2018/09/26 Python
python输出电脑上所有的串口名的方法
2019/07/02 Python
Python解析命令行读取参数之argparse模块
2019/07/26 Python
python实现桌面气泡提示功能
2019/07/29 Python
Python re 模块findall() 函数返回值展现方式解析
2019/08/09 Python
python批量读取文件名并写入txt文件中
2020/09/05 Python
Herve Leger官网:标志性绷带连衣裙等
2018/12/26 全球购物
北京银河万佳Java面试题
2012/03/21 面试题
学生拾金不昧表扬信
2014/01/21 职场文书
医科大学毕业生自荐信
2014/02/03 职场文书
承诺书怎么写
2014/03/26 职场文书
啦啦队口号大全
2014/06/16 职场文书
银行贷款收入证明
2014/10/17 职场文书
2015年环境监察工作总结
2015/07/23 职场文书