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 相关文章推荐
Python3实现连接SQLite数据库的方法
Aug 23 Python
python继承和抽象类的实现方法
Jan 14 Python
详解Python中的多线程编程
Apr 09 Python
Python使用lxml模块和Requests模块抓取HTML页面的教程
May 16 Python
django中静态文件配置static的方法
May 20 Python
Python爬虫使用脚本登录Github并查看信息
Jul 16 Python
解决Python plt.savefig 保存图片时一片空白的问题
Jan 10 Python
11个Python Pandas小技巧让你的工作更高效(附代码实例)
Apr 30 Python
python中tkinter的应用:修改字体的实例讲解
Jul 17 Python
django foreignkey外键使用的例子 相当于left join
Aug 06 Python
Python 面向对象之封装、继承、多态操作实例分析
Nov 21 Python
python 中的9个实用技巧,助你提高开发效率
Aug 30 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下实现折线图效果的代码
2007/04/28 PHP
深入php处理整数函数的详解
2013/06/09 PHP
php抓取网站图片并保存的实现方法
2015/10/29 PHP
合格的PHP程序员必备技能
2015/11/13 PHP
Javascript 读后台cookie代码
2008/09/15 Javascript
window.location和document.location的区别分析
2008/12/23 Javascript
input按钮的事件处理大全
2010/12/10 Javascript
Extjs4 Treegrid 使用心得分享(经验篇)
2013/07/01 Javascript
js如何设置在iframe框架中指定div不显示
2013/12/04 Javascript
理运用命名空间让js不产生冲突避免全局变量的泛滥
2014/06/15 Javascript
2014 HTML5/CSS3热门动画特效TOP10
2014/12/07 Javascript
简述JavaScript中正则表达式的使用方法
2015/06/15 Javascript
JavaScript实现弹出广告功能
2017/03/30 Javascript
浅谈Vuex的状态管理(全家桶)
2017/11/04 Javascript
vue form check 表单验证的实现代码
2018/12/09 Javascript
angula中使用iframe点击后不执行变更检测的问题
2020/05/10 Javascript
vue页面跳转实现页面缓存操作
2020/07/22 Javascript
vue 授权获取微信openId操作
2020/11/13 Javascript
[01:03:38]2014 DOTA2国际邀请赛中国区预选赛5.21 CNB VS CIS
2014/05/22 DOTA
[02:50]【扭转乾坤,只此一招】DOTA2永雾林渊版本开启新篇章
2020/12/22 DOTA
解读Python编程中的命名空间与作用域
2015/10/16 Python
利用Python实现网络测试的脚本分享
2017/05/26 Python
Python实现图片转字符画的示例
2017/08/22 Python
Python爬虫实例扒取2345天气预报
2018/03/04 Python
Django中使用MySQL5.5的教程
2019/12/18 Python
pycharm 对代码做静态检查操作
2020/06/09 Python
美国电子产品折扣网站:Daily Steals
2017/05/20 全球购物
行政经理的岗位职责
2013/11/23 职场文书
房地产还款计划书
2014/01/10 职场文书
电焊工工作岗位职责
2014/02/06 职场文书
小学生期末评语
2014/04/21 职场文书
房地产开发项目建议书
2014/05/16 职场文书
《扇形统计图》教学反思
2016/02/17 职场文书
css背景和边框标签实例详解
2021/05/21 HTML / CSS
pytorch 权重weight 与 梯度grad 可视化操作
2021/06/05 Python
漫画「古见同学有交流障碍症」第25卷封面公开
2022/03/21 日漫