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应用的教程
Apr 16 Python
Python常用小技巧总结
Jun 01 Python
Python循环语句之break与continue的用法
Oct 14 Python
Windows中使用wxPython和py2exe开发Python的GUI程序的实例教程
Jul 11 Python
Python实现对百度云的文件上传(实例讲解)
Oct 21 Python
Django的HttpRequest和HttpResponse对象详解
Jan 26 Python
python+mysql实现教务管理系统
Feb 20 Python
PyQt5通信机制 信号与槽详解
Aug 07 Python
Python 文件操作之读取文件(read),文件指针与写入文件(write),文件打开方式示例
Sep 29 Python
python爬虫库scrapy简单使用实例详解
Feb 10 Python
Python解释器以及PyCharm的安装教程图文详解
Feb 26 Python
PyQt5的相对布局管理的实现
Aug 07 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
PHP分页类集锦
2014/11/18 PHP
PHP+redis实现的悲观锁机制示例
2018/06/12 PHP
php使用环形链表解决约瑟夫问题完整示例
2018/08/07 PHP
Laravel第三方包报class not found的解决方法
2019/10/13 PHP
根据分辨率不同,调用不同的css文件
2006/08/25 Javascript
HTML中的setCapture和releaseCapture使用介绍
2012/03/21 Javascript
Extjs中ComboBox加载并赋初值的实现方法
2012/03/22 Javascript
js中如何复制一个对象并获取其所有属性和属性对应的值
2013/10/24 Javascript
《JavaScript DOM 编程艺术》读书笔记之DOM基础
2015/01/09 Javascript
检测一个函数是否是JavaScript原生函数的小技巧
2015/03/13 Javascript
详解JavaScript中void语句的使用
2015/06/04 Javascript
jQuery实现带幻灯的tab滑动切换风格菜单代码
2015/08/27 Javascript
js判断手机号运营商的方法
2015/10/23 Javascript
js实现仿微博滚动显示信息的效果
2015/12/21 Javascript
Vue2 Vue-cli中使用Typescript的配置详解
2017/07/24 Javascript
监听angularJs列表数据是否渲染完毕的方法示例
2018/11/07 Javascript
vue+mock.js实现前后端分离
2019/07/24 Javascript
Ant Design moment对象和字符串之间的相互转化教程
2020/10/27 Javascript
利用python发送和接收邮件
2016/09/27 Python
Python中如何优雅的合并两个字典(dict)方法示例
2017/08/09 Python
PyTorch中Tensor的拼接与拆分的实现
2019/08/18 Python
Python函数参数分类原理详解
2020/05/28 Python
DBA的职责都有哪些
2012/05/16 面试题
运动会开幕式邀请函
2014/02/03 职场文书
关于孝道的演讲稿
2014/05/21 职场文书
中秋晚会策划方案
2014/06/12 职场文书
教师遵守党的政治纪律情况对照检查材料
2014/09/26 职场文书
2014房屋登记授权委托书
2014/10/13 职场文书
2014年安全生产工作总结
2014/11/13 职场文书
酒店客房服务员岗位职责
2015/04/09 职场文书
2015年出纳年终工作总结
2015/05/14 职场文书
国家助学金受助感言
2015/08/01 职场文书
安全生产隐患排查制度
2015/08/05 职场文书
python3实现常见的排序算法(示例代码)
2021/07/04 Python
详解Mysq MVCC多版本的并发控制
2022/04/29 MySQL
Go Grpc Gateway兼容HTTP协议文档自动生成网关
2022/06/16 Golang