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升级提示Tkinter模块找不到的解决方法
Aug 22 Python
Python图算法实例分析
Aug 13 Python
python保存网页图片到本地的方法
Jul 24 Python
python实现dijkstra最短路由算法
Jan 17 Python
Django中自定义模型管理器(Manager)及方法
Sep 23 Python
pytorch多GPU并行运算的实现
Sep 27 Python
python随机模块random使用方法详解
Feb 14 Python
python GUI库图形界面开发之PyQt5线程类QThread详细使用方法
Feb 26 Python
Python写捕鱼达人的游戏实现
Mar 31 Python
Selenium基于PIL实现拼接滚动截图
Apr 10 Python
Python用requests库爬取返回为空的解决办法
Feb 21 Python
python元组拆包实现方法
Feb 28 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大小写问题:函数名和类名不区分,变量名区分
2013/06/17 PHP
php 中文字符串首字母的获取函数分享
2013/11/04 PHP
详解PHP的Yii框架的运行机制及其路由功能
2016/03/17 PHP
php微信支付接口开发程序
2016/08/02 PHP
php简单计算年龄的方法(周岁与虚岁)
2016/12/06 PHP
PHP封装的分页类与简单用法示例
2019/02/25 PHP
JavaScript 设计模式学习 Factory
2009/07/29 Javascript
jQuery :nth-child前有无空格的区别分析
2011/07/11 Javascript
DOM2非标准但却支持很好的几个属性小结
2012/01/21 Javascript
jquery 跳到顶部和底部动画2句代码简单实现
2013/07/18 Javascript
js实现单行文本向上滚动效果实例代码
2013/11/28 Javascript
easyui validatebox验证
2016/04/29 Javascript
清除浏览器缓存的几种方法总结(必看)
2016/12/09 Javascript
AngularJs中Bootstrap3 datetimepicker使用实例
2016/12/13 Javascript
Javascript中常用类型的格式化方法小结
2016/12/26 Javascript
canvas实现十二星座星空图
2017/02/14 Javascript
node.js中路由,中间件,ge请求和post请求的参数详解
2017/12/26 Javascript
vue iview实现动态路由和权限验证功能
2018/04/17 Javascript
利用Node.js批量抓取高清妹子图片实例教程
2018/08/02 Javascript
Vue Element UI + OSS实现上传文件功能
2019/07/31 Javascript
怎么理解wx.navigateTo的events参数使用详情
2020/05/18 Javascript
Vue 事件的$event参数=事件的值案例
2021/01/29 Vue.js
Python图像灰度变换及图像数组操作
2016/01/27 Python
解决Python网页爬虫之中文乱码问题
2018/05/11 Python
pandas 对每一列数据进行标准化的方法
2018/06/09 Python
python3在同一行内输入n个数并用列表保存的例子
2019/07/20 Python
Django用户认证系统 User对象解析
2019/08/02 Python
Python SSL证书验证问题解决方案
2020/01/13 Python
python如何修改文件时间属性
2021/02/05 Python
SpringBoot首页设置解析(推荐)
2021/02/11 Python
美国卡车、吉普车和SUV零件网站:4 Wheel Parts
2016/11/24 全球购物
毕业生实习证明
2014/09/19 职场文书
小学四年级学生评语
2014/12/26 职场文书
党组织关系的介绍信模板
2019/06/21 职场文书
CSS+HTML 实现顶部导航栏功能
2021/08/30 HTML / CSS
Spring Data JPA框架自定义Repository接口
2022/04/28 Java/Android