[原码]虎牙直播收看器。任意直播源播放,不定期更新时,请看置顶贴
本帖最后由 dltest 于 2022-10-16 23:47 编辑1输入虎牙房间ID号,不是网址中的号.
2点解析
3如果主播在线,默认播放地址为蓝光4M. 或者可以自己选择其它CDN及清晰度
4 播放
5.全屏快捷键 F11 ,或Esc键退出全屏
6 URL栏可以直播输入其它直播源地址,直接进行播放
7 代码编写环境 win7x64python3.8
获取房间ID
本软件运行中截图
打包后的下载,如下。因本代码调用三方程序VLC所以同时打包了该程序约139M,测试环境win7x64
下载:https://wwz.lanzoub.com/i0n8F0e0biqf 密码:52pj
代码如下
# -*- coding:utf-8 -*-
# @FileName:huya_live_read.py
# @ Author :dltest@52pojie
import json
import tkinter as tk
import tkinter.font as tkFont
from tkinter import *
from tkinter import ttk
import requests
import re
import os, platform
# 设置VLC库路径,需在import vlc之前
# os.environ['PYTHON_VLC_MODULE_PATH'] = "./vlc-3.0.6"
import vlc
class Player:
'''
args:设置 options
'''
def __init__(self, *args):
if args:
instance = vlc.Instance(*args)
self.media = instance.media_player_new()
else:
self.media = vlc.MediaPlayer()
# 设置待播放的url地址或本地文件路径,每次调用都会重新加载资源
def set_uri(self, uri):
self.media.set_mrl(uri)
# 播放 成功返回0,失败返回-1
def play(self, path=None):
if path:
self.set_uri(path)
return self.media.play()
else:
return self.media.play()
# 暂停
def pause(self):
self.media.pause()
# 恢复
def resume(self):
self.media.set_pause(0)
# 停止
def stop(self):
self.media.stop()
# 释放资源
def release(self):
return self.media.release()
# 是否正在播放
def is_playing(self):
return self.media.is_playing()
# 已播放时间,返回毫秒值
def get_time(self):
return self.media.get_time()
# 拖动指定的毫秒值处播放。成功返回0,失败返回-1 (需要注意,只有当前多媒体格式或流媒体协议支持才会生效)
def set_time(self, ms):
return self.media.get_time()
# 音视频总长度,返回毫秒值
def get_length(self):
return self.media.get_length()
# 获取当前音量(0~100)
def get_volume(self):
return self.media.audio_get_volume()
# 设置音量(0~100)
def set_volume(self, volume):
return self.media.audio_set_volume(volume)
# 返回当前状态:正在播放;暂停中;其他
def get_state(self):
state = self.media.get_state()
if state == vlc.State.Playing:
return 1
elif state == vlc.State.Paused:
return 0
else:
return -1
# 当前播放进度情况。返回0.0~1.0之间的浮点数
def get_position(self):
return self.media.get_position()
# 拖动当前进度,传入0.0~1.0之间的浮点数(需要注意,只有当前多媒体格式或流媒体协议支持才会生效)
def set_position(self, float_val):
return self.media.set_position(float_val)
# 获取当前文件播放速率
def get_rate(self):
return self.media.get_rate()
# 设置播放速率(如:1.2,表示加速1.2倍播放)
def set_rate(self, rate):
return self.media.set_rate(rate)
# 设置宽高比率(如"16:9","4:3")
def set_ratio(self, ratio):
self.media.video_set_scale(0)# 必须设置为0,否则无法修改屏幕宽高
self.media.video_set_aspect_ratio(ratio)
# 设置窗口句柄
def set_window(self, wm_id):
if platform.system() == 'Windows':
self.media.set_hwnd(wm_id)
else:
self.media.set_xwindow(wm_id)
# 注册监听器
def add_callback(self, event_type, callback):
self.media.event_manager().event_attach(event_type, callback)
# 移除监听器
def remove_callback(self, event_type, callback):
self.media.event_manager().event_detach(event_type, callback)
class App:
def __init__(self, root):
self.editdate = '2022/10/17'
self.root =root
self.initUI(root)
self.initData()
self.player = Player()
self.create_video_view(self.GLineEdit_621.winfo_id())
self.root.bind("<F11>",self.changescreen)
self.root.bind("<Escape>",self.exitfullscreen)
def initData(self):
self.GLineEdit_621.insert(0,'请输入直播间的ID')
self.vol =50
self.flag= True
self.headers = {'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148'}
self.api_url = 'https://mp.huya.com/cache.php?m=Live&do=profileRoom&roomid='
def initUI(self,root):
#setting title
root.title(f"虎牙直播收看器 {self.editdate}dltest@52pojie")
#setting window size
width=1244
height=744
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
root.geometry(alignstr)
# root.resizable(width=False, height=False)
self.GLineEdit_621=tk.Entry(root)
self.GLineEdit_621["borderwidth"] = "1px"
ft = tkFont.Font(family='Times',size=10)
self.GLineEdit_621["font"] = ft
self.GLineEdit_621["fg"] = "#333333"
self.GLineEdit_621["bg"] = "#393d49"
self.GLineEdit_621["justify"] = "center"
self.GLineEdit_621["text"] = "ve"
self.w =1243
self.h =705
self.GLineEdit_621.place(x=0,y=0,width=self.w,height=self.h)
self.GLineEdit_621.bind('<Double-Button-1>',self.changescreen)
self.GListBox_294=ttk.Combobox(root)
ft = tkFont.Font(family='Times',size=10)
self.GListBox_294["font"] = ft
self.GListBox_294["justify"] = "center"
self.GListBox_294.place(x=600,y=710,width=103,height=30)
self.GListBox_294.bind("<<ComboboxSelected>>", self.choose)
self.GLabel_149=tk.Label(root)
ft = tkFont.Font(family='Times',size=10)
self.GLabel_149["font"] = ft
self.GLabel_149["fg"] = "#333333"
self.GLabel_149["justify"] = "center"
self.GLabel_149["text"] = "直播间ID:"
self.GLabel_149.place(x=10,y=710,width=67,height=30)
self.GLineEdit_15=tk.Entry(root)
self.GLineEdit_15["borderwidth"] = "1px"
ft = tkFont.Font(family='Times',size=10)
self.GLineEdit_15["font"] = ft
self.GLineEdit_15["fg"] = "#333333"
self.GLineEdit_15["justify"] = "center"
self.GLineEdit_15["text"] = "room_id"
self.GLineEdit_15["relief"] = "groove"
self.GLineEdit_15.place(x=80,y=710,width=83,height=30)
self.GButton_246=tk.Button(root)
self.GButton_246["bg"] = "#f0f0f0"
ft = tkFont.Font(family='Times',size=10)
self.GButton_246["font"] = ft
self.GButton_246["fg"] = "#000000"
self.GButton_246["justify"] = "center"
self.GButton_246["text"] = "解析"
self.GButton_246["relief"] = "groove"
self.GButton_246.place(x=170,y=710,width=67,height=30)
self.GButton_246["command"] = self.GButton_246_command
self.GLabel_158=tk.Label(root)
ft = tkFont.Font(family='Times',size=10)
self.GLabel_158["font"] = ft
self.GLabel_158["fg"] = "#333333"
self.GLabel_158["justify"] = "center"
self.GLabel_158["text"] = "选择清晰度:"
self.GLabel_158.place(x=530,y=710,width=78,height=30)
self.GLineEdit_316=tk.Entry(root)
self.GLineEdit_316["borderwidth"] = "1px"
ft = tkFont.Font(family='Times',size=10)
self.GLineEdit_316["font"] = ft
self.GLineEdit_316["fg"] = "#333333"
self.GLineEdit_316["justify"] = "center"
self.GLineEdit_316["text"] = "real_url"
self.GLineEdit_316["relief"] = "groove"
self.GLineEdit_316.place(x=450,y=710,width=80,height=30)
self.GButton_701=tk.Button(root)
self.GButton_701["bg"] = "#f0f0f0"
ft = tkFont.Font(family='Times',size=10)
self.GButton_701["font"] = ft
self.GButton_701["fg"] = "#000000"
self.GButton_701["justify"] = "center"
self.GButton_701["text"] = "►播 放"
self.GButton_701["relief"] = "groove"
self.GButton_701.place(x=710,y=710,width=66,height=30)
self.GButton_701["command"] = self.GButton_701_command
self.GButton_132=tk.Button(root)
self.GButton_132["bg"] = "#f0f0f0"
ft = tkFont.Font(family='Times',size=10)
self.GButton_132["font"] = ft
self.GButton_132["fg"] = "#000000"
self.GButton_132["justify"] = "center"
self.GButton_132["text"] = "▍▍暂停"
self.GButton_132["relief"] = "groove"
self.GButton_132.place(x=780,y=710,width=66,height=30)
self.GButton_132["command"] = self.GButton_132_command
self.GButton_492=tk.Button(root)
self.GButton_492["bg"] = "#f0f0f0"
ft = tkFont.Font(family='Times',size=10)
self.GButton_492["font"] = ft
self.GButton_492["fg"] = "#000000"
self.GButton_492["justify"] = "center"
self.GButton_492["text"] = "⬛ 停止"
self.GButton_492["relief"] = "groove"
self.GButton_492.place(x=850,y=710,width=66,height=30)
self.GButton_492["command"] = self.GButton_492_command
self.GButton_813=tk.Button(root)
self.GButton_813["bg"] = "#f0f0f0"
ft = tkFont.Font(family='Times',size=10)
self.GButton_813["font"] = ft
self.GButton_813["fg"] = "#000000"
self.GButton_813["justify"] = "center"
self.GButton_813["text"] = "音量 +"
self.GButton_813["relief"] = "groove"
self.GButton_813.place(x=940,y=710,width=66,height=30)
self.GButton_813["command"] = self.GButton_813_command
self.GButton_229=tk.Button(root)
self.GButton_229["bg"] = "#f0f0f0"
ft = tkFont.Font(family='Times',size=10)
self.GButton_229["font"] = ft
self.GButton_229["fg"] = "#000000"
self.GButton_229["justify"] = "center"
self.GButton_229["text"] = "音量 -"
self.GButton_229["relief"] = "groove"
self.GButton_229.place(x=1010,y=710,width=66,height=30)
self.GButton_229["command"] = self.GButton_229_command
self.GButton_316=tk.Button(root)
self.GButton_316["bg"] = "#f0f0f0"
ft = tkFont.Font(family='Times',size=10)
self.GButton_316["font"] = ft
self.GButton_316["fg"] = "#000000"
self.GButton_316["justify"] = "center"
self.GButton_316["text"] = "静 音"
self.GButton_316["relief"] = "groove"
self.GButton_316.place(x=1080,y=710,width=66,height=30)
self.GButton_316["command"] = self.GButton_316_command
self.GButton_275=tk.Button(root)
self.GButton_275["bg"] = "#f0f0f0"
ft = tkFont.Font(family='Times',size=10)
self.GButton_275["font"] = ft
self.GButton_275["fg"] = "#000000"
self.GButton_275["justify"] = "center"
self.GButton_275["text"] = "F11全屏"
self.GButton_275["relief"] = "groove"
self.GButton_275.place(x=1180,y=710,width=59,height=30)
self.GButton_275["command"] = self.GButton_275_command
self.GLineEdit_754=tk.Entry(root)
self.GLineEdit_754["borderwidth"] = "1px"
ft = tkFont.Font(family='Times',size=10)
self.GLineEdit_754["font"] = ft
self.GLineEdit_754["fg"] = "#333333"
self.GLineEdit_754["justify"] = "center"
self.GLineEdit_754["text"] = "zhubo_name"
self.GLineEdit_754.place(x=290,y=710,width=153,height=30)
self.GLabel_143=tk.Label(root)
ft = tkFont.Font(family='Times',size=10)
self.GLabel_143["font"] = ft
self.GLabel_143["fg"] = "#333333"
self.GLabel_143["justify"] = "center"
self.GLabel_143["text"] = "主播名:"
self.GLabel_143.place(x=240,y=710,width=57,height=30)
def create_video_view(self,wid):
self.player.set_window(wid)
def choose(self,event):
url = self.GListBox_294.get()
self.GLineEdit_316.delete(0,'end')
self.GLineEdit_316.insert(0,url.split('::'))
#解析
def GButton_246_command(self):
self.GLineEdit_316.delete(0,'end')
room_id = self.GLineEdit_15.get()
if not room_id:
return
try:
html = requests.get(self.api_url + room_id, headers=self.headers)
data = json.loads(html.text)['data']
nick = data['profileInfo']['nick']
room_name = data['liveData']['roomName']
liveStatus = data['liveStatus']
print(f'{nick} {room_name} {liveStatus}')
except:
print('Room id is invalid!')
self.GLineEdit_754.delete(0,'end')
self.GLineEdit_754.insert(0,'房号错误!')
return
if liveStatus == "OFF":
self.GLineEdit_754.delete(0,'end')
self.GLineEdit_754.insert(0,f'未开播 {nick}')
return f'{room_name} {nick} is offline'
elif liveStatus == "REPLAY":
self.GLineEdit_754.delete(0,'end')
self.GLineEdit_754.insert(0,f'未开播 {nick}')
return f'{room_name} {nick} is REPLAY'
else:
self.GLineEdit_754.delete(0,'end')
self.GLineEdit_754.insert(0,f'【{nick}】{room_name}')
stream_dict = data['stream']
flv = stream_dict['flv']# type: dict
cdn = flv['multiLine']# type: List
rate = flv['rateArray']# type: List
supportable_resolution = {'原画': '', }
for b in rate:
supportable_resolution] = b['iBitRate']
sort_dict = {}
listbox = []
for resolution, bitrate in supportable_resolution.items():
url_list = []
for i in cdn:
url = i['url'].replace('http://', 'https://')
url = url.replace(
'imgplus.flv', f'imgplus_{bitrate}.flv')
url_list.append(url)
sort_dict = url_list
for resolution, url_list in sort_dict.items():
count=0
for i in url_list:
count += 1
listbox.append(f'【{resolution}】{count}::{i}')
self.GListBox_294["values"] = listbox
for i in listbox:
if i.startswith('【蓝光4M】'):
# self.GListBox_294.current(1)
self.GListBox_294.set(i)
self.GLineEdit_316.delete(0,'end')
self.GLineEdit_316.insert(0,i.split('::'))
break
else:
self.GListBox_294.current(1)
self.GLineEdit_316.delete(0,'end')
self.GLineEdit_316.insert(0,i.split('::'))
def GButton_701_command(self): #►播 放
url = self.GLineEdit_316.get().strip()
if not url:
return
if self.player.get_state() == 0:
self.player.resume()
elif self.player.get_state() == 1:
pass# 播放新资源
self.player.play(url)
else:
self.player.play(url)
#暂停
def GButton_132_command(self):
self.player.pause()
#停止
def GButton_492_command(self):
self.player.stop()
#音量加
def GButton_813_command(self):
vol = self.player.get_volume()
self.player.set_volume(vol+5)
#音量减
def GButton_229_command(self):
vol = self.player.get_volume()
self.player.set_volume(vol-5)
#静音
def GButton_316_command(self):
vol = self.player.get_volume()
if vol == 0:
self.player.set_volume(self.vol)
else:
self.vol = self.player.get_volume()
self.player.set_volume(0)
#全屏
def GButton_275_command(self):
ifself.flag:
self.root.attributes('-fullscreen',True)
self.w, self.h = self.root.winfo_screenwidth(), self.root.winfo_screenheight()
self.GLineEdit_621.place(x=0,y=0,width=self.w,height=self.h)
self.GButton_492.place_forget()
self.GLabel_149.place_forget()
self.GLineEdit_15.place_forget()
self.GButton_246.place_forget()
self.GLabel_143.place_forget()
self.GLineEdit_754.place_forget()
self.GLineEdit_316.place_forget()
self.GLabel_158.place_forget()
self.GListBox_294.place_forget()
self.GButton_701.place_forget()
self.GButton_132.place_forget()
self.GButton_492.place_forget()
self.GButton_813.place_forget()
self.GButton_229.place_forget()
self.GButton_316.place_forget()
self.GButton_275.place_forget()
else:
self.root.attributes('-fullscreen',False)
# self.GLineEdit_621.place(x=0,y=0,width=self.w,height=self.h)
self.GLineEdit_621.place(x=0,y=0,width=1243,height=705)
self.GLabel_149.place(x=10,y=710,width=67,height=30)
self.GLineEdit_15.place(x=80,y=710,width=83,height=30)
self.GButton_246.place(x=170,y=710,width=67,height=30)
self.GLabel_143.place(x=240,y=710,width=57,height=30)
self.GLineEdit_754.place(x=290,y=710,width=153,height=30)
self.GLineEdit_316.place(x=450,y=710,width=80,height=30)
self.GLabel_158.place(x=530,y=710,width=78,height=30)
self.GListBox_294.place(x=600,y=710,width=103,height=30)
self.GButton_701.place(x=710,y=710,width=66,height=30)
self.GButton_132.place(x=780,y=710,width=66,height=30)
self.GButton_492.place(x=850,y=710,width=66,height=30)
self.GButton_813.place(x=940,y=710,width=66,height=30)
self.GButton_229.place(x=1010,y=710,width=66,height=30)
self.GButton_316.place(x=1080,y=710,width=66,height=30)
self.GButton_275.place(x=1180,y=710,width=59,height=30)
self.flag = not self.flag
def changescreen(self,event):
self.GButton_275_command()
def exitfullscreen(self,event):
self.flag = True
self.root.attributes('-fullscreen',False)
self.GLineEdit_621.place(x=0,y=0,width=1243,height=705)
self.GLabel_149.place(x=10,y=710,width=67,height=30)
self.GLineEdit_15.place(x=80,y=710,width=83,height=30)
self.GButton_246.place(x=170,y=710,width=67,height=30)
self.GLabel_143.place(x=240,y=710,width=57,height=30)
self.GLineEdit_754.place(x=290,y=710,width=153,height=30)
self.GLineEdit_316.place(x=450,y=710,width=80,height=30)
self.GLabel_158.place(x=530,y=710,width=78,height=30)
self.GListBox_294.place(x=600,y=710,width=103,height=30)
self.GButton_701.place(x=710,y=710,width=66,height=30)
self.GButton_132.place(x=780,y=710,width=66,height=30)
self.GButton_492.place(x=850,y=710,width=66,height=30)
self.GButton_813.place(x=940,y=710,width=66,height=30)
self.GButton_229.place(x=1010,y=710,width=66,height=30)
self.GButton_316.place(x=1080,y=710,width=66,height=30)
self.GButton_275.place(x=1180,y=710,width=59,height=30)
if __name__ == "__main__":
root = tk.Tk()
app = App(root)
root.mainloop()
本次更新:
[*]重写UI
[*]可以自由缩放播放器大小
[*]加载虎牙分类菜单,方便快速找到喜欢的主播
[*]解析出来的主播,可以加入关注/收藏,点右侧列表快速加载
[*]其它
原功能仍保留
[*]可以自己输入房间号,进行解析、观看
[*]可以输入自定义直播间地址,观看
提醒
[*]返回选择类别或收藏界面,要先停止直播收看
程序目前尚存问题
1部份直播无法正常播放,例 娱乐天地/一起看 这个类型的直播基本都无法播放,语音类的无法正常显示等
2鼠标滚轮快捷调节音量,有时会失灵
打包好的exe文件下载(含vlc三方控件)
下载:https://wwz.lanzoub.com/iXbyS0ei3uja 密码:52pj
代码如下
# -*- coding:utf-8 -*-
# @FileName:huya_live_read.py
# @ Author :dltest@52pojie
import json
import tkinter as tk
import tkinter.font as tkFont
from tkinter import *
from tkinter import ttk
import requests
import re
import os, platform
# 设置VLC库路径,需在import vlc之前
os.environ['PYTHON_VLC_MODULE_PATH'] = "./vlc-3.0.9.2-win64"
import vlc
from lxml import etree
class Player:
'''
args:设置 options
'''
def __init__(self, *args):
if args:
instance = vlc.Instance(*args)
self.media = instance.media_player_new()
else:
self.media = vlc.MediaPlayer()
# 设置待播放的url地址或本地文件路径,每次调用都会重新加载资源
def set_uri(self, uri):
self.media.set_mrl(uri)
# 播放 成功返回0,失败返回-1
def play(self, path=None):
if path:
self.set_uri(path)
return self.media.play()
else:
return self.media.play()
# 暂停
def pause(self):
self.media.pause()
# 恢复
def resume(self):
self.media.set_pause(0)
# 停止
def stop(self):
self.media.stop()
# 释放资源
def release(self):
return self.media.release()
# 是否正在播放
def is_playing(self):
return self.media.is_playing()
# 已播放时间,返回毫秒值
def get_time(self):
return self.media.get_time()
# 拖动指定的毫秒值处播放。成功返回0,失败返回-1 (需要注意,只有当前多媒体格式或流媒体协议支持才会生效)
def set_time(self, ms):
return self.media.get_time()
# 音视频总长度,返回毫秒值
def get_length(self):
return self.media.get_length()
# 获取当前音量(0~100)
def get_volume(self):
return self.media.audio_get_volume()
# 设置音量(0~100)
def set_volume(self, volume):
return self.media.audio_set_volume(volume)
# 返回当前状态:正在播放;暂停中;其他
def get_state(self):
state = self.media.get_state()
if state == vlc.State.Playing:
return 1
elif state == vlc.State.Paused:
return 0
else:
return -1
# 当前播放进度情况。返回0.0~1.0之间的浮点数
def get_position(self):
return self.media.get_position()
# 拖动当前进度,传入0.0~1.0之间的浮点数(需要注意,只有当前多媒体格式或流媒体协议支持才会生效)
def set_position(self, float_val):
return self.media.set_position(float_val)
# 获取当前文件播放速率
def get_rate(self):
return self.media.get_rate()
# 设置播放速率(如:1.2,表示加速1.2倍播放)
def set_rate(self, rate):
return self.media.set_rate(rate)
# 设置宽高比率(如"16:9","4:3")
def set_ratio(self, ratio):
self.media.video_set_scale(0)# 必须设置为0,否则无法修改屏幕宽高
self.media.video_set_aspect_ratio(ratio)
# 设置窗口句柄
def set_window(self, wm_id):
if platform.system() == 'Windows':
self.media.set_hwnd(wm_id)
else:
self.media.set_xwindow(wm_id)
# 注册监听器
def add_callback(self, event_type, callback):
self.media.event_manager().event_attach(event_type, callback)
# 移除监听器
def remove_callback(self, event_type, callback):
self.media.event_manager().event_detach(event_type, callback)
class App:
def __init__(self, root):
self.root =root
self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36'}
self.editdate = '2022/10/24'
self.init_ui(root)
self.player = Player()
self.create_video_view(self.frame_video.winfo_id())
self.root.bind("<F11>",self.changescreen)
self.root.bind("<Escape>",self.exitfullscreen)
self.root.bind("<MouseWheel>",self.change_vol)
self.flag= True
self.choose_active(None)
self.count = 0
self.zhubo_list = self.getzhubolist()
if not self.zhubo_list or len(self.zhubo_list) < 1:
return
self.anchor_list =[]
self.settvlist(self.zhubo_list)
def init_ui(self,root):
#setting title
root.title(f"虎牙直播收看器 {self.editdate}dltest@52pojie")
#setting window size
width=578
height=380
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
root.geometry(alignstr)
root.grid_rowconfigure(0,weight=1,minsize=40) # row为1,缩放比为1
root.grid_columnconfigure(0,weight=1,minsize=40) # column为0,缩放比为1
self.frame_main=tk.Frame(root, relief='groove' )
self.frame_main.grid(row=0,column=0,sticky=NSEW)
self.frame_video=tk.Frame(root, relief='groove' )
self.frame_video['bg'] = "#ccc"
self.frame_video.grid(row=0,column=0,sticky=NSEW)
self.frame_main.tkraise()
self.frame_buttom=tk.Frame(root, relief='groove')
# self.frame_buttom['bg'] = "#ffffff"
self.frame_buttom.grid(row=1,column=0,sticky=NSEW,padx=0, pady=0 ) # 跨2列
self.GButton_274=tk.Button(self.frame_buttom)
self.GButton_274["bg"] = "#efefef"
ft = tkFont.Font(family='Times',size=10)
self.GButton_274["font"] = ft
self.GButton_274["fg"] = "#000000"
self.GButton_274["justify"] = "center"
self.GButton_274["text"] = "►"
self.GButton_274["relief"] = "groove"
# self.GButton_274.place(x=0,y=0,width=30,height=30)
self.GButton_274.grid(row=0,column=0,sticky=NSEW,padx=5, pady=1 )
self.GButton_274["command"] = self.GButton_274_command
self.GButton_751=tk.Button(self.frame_buttom)
self.GButton_751["bg"] = "#efefef"
ft = tkFont.Font(family='Times',size=10)
self.GButton_751["font"] = ft
self.GButton_751["fg"] = "#000000"
self.GButton_751["justify"] = "center"
self.GButton_751["text"] = "▍▍"
self.GButton_751["relief"] = "groove"
self.GButton_751.grid(row=0,column=1,sticky=NSEW,padx=1, pady=1 )
self.GButton_751["command"] = self.GButton_751_command
self.GButton_159=tk.Button(self.frame_buttom)
self.GButton_159["bg"] = "#efefef"
ft = tkFont.Font(family='Times',size=10)
self.GButton_159["font"] = ft
self.GButton_159["fg"] = "#000000"
self.GButton_159["justify"] = "center"
self.GButton_159["text"] = "⬛"
self.GButton_159["relief"] = "groove"
self.GButton_159.grid(row=0,column=2,sticky=NSEW,padx=5, pady=1 )
self.GButton_159["command"] = self.GButton_159_command
self.GButton_991=tk.Button(self.frame_buttom)
self.GButton_991["bg"] = "#efefef"
ft = tkFont.Font(family='Times',size=10)
self.GButton_991["font"] = ft
self.GButton_991["fg"] = "#000000"
self.GButton_991["justify"] = "center"
self.GButton_991["text"] = "静音"
self.GButton_991["relief"] = "groove"
self.GButton_991.grid(row=0,column=3,sticky=NSEW,padx=5, pady=1 )
self.GButton_991["command"] = self.GButton_991_command
self.scint = IntVar()
self.scint.set(50)
self.GButton_79=tk.Scale(self.frame_buttom,from_=0,to=100,showvalue=False,tickinterval = 0,variable = self.scint,
activebackground='#00ced1',orient=HORIZONTAL)
self.GButton_79["bg"] = "#efefef"
ft = tkFont.Font(family='Times',size=10)
self.GButton_79["font"] = ft
self.GButton_79["fg"] = "#000000"
# self.GButton_79["justify"] = "center"
# self.GButton_79["text"] = "音量控制"
self.GButton_79["relief"] = "groove"
self.GButton_79.grid(row=0,column=4,sticky=NSEW,padx=1, pady=1 )
self.GButton_79["command"] = self.GButton_79_command
self.GButton_39=tk.Button(self.frame_buttom)
self.GButton_39["bg"] = "#efefef"
ft = tkFont.Font(family='Times',size=10)
self.GButton_39["font"] = ft
self.GButton_39["fg"] = "#000000"
self.GButton_39["justify"] = "center"
self.GButton_39["text"] = "F11全屏"
self.GButton_39["relief"] = "groove"
self.GButton_39.grid(row=0,column=5,sticky=NSEW,padx=15, pady=1 )
self.GButton_39["command"] = self.GButton_39_command
#####################################################################################
value = [('全部', '/g'), ('网游竞技', '/g_ol'), ('单机热游', '/g_pc'), ('娱乐天地', '/g_yl'), ('手游休闲', '/g_sy')]
self.GLineEdit_678 = ttk.Combobox(self.frame_main, state='readonly')
ft = tkFont.Font(family='Times',size=10)
self.GLineEdit_678["font"] = ft
self.GLineEdit_678["value"] = value
self.GLineEdit_678.place(x=40,y=0,width=253,height=30)
self.GLineEdit_678.bind("<<ComboboxSelected>>", self.choose_active)
self.GLineEdit_678.current(0)
self.GLabel_397=tk.Label(self.frame_main)
ft = tkFont.Font(family='Times',size=10)
self.GLabel_397["font"] = ft
self.GLabel_397["fg"] = "#333333"
self.GLabel_397["justify"] = "center"
self.GLabel_397["text"] = "分 类"
self.GLabel_397.place(x=0,y=0,width=30,height=30)
self.GLabel_268=tk.Label(self.frame_main)
ft = tkFont.Font(family='Times',size=10)
self.GLabel_268["font"] = ft
self.GLabel_268["fg"] = "#333333"
self.GLabel_268["justify"] = "center"
self.GLabel_268["text"] = "列 表"
self.GLabel_268.place(x=0,y=40,width=30,height=30)
self.GLineEdit_803=ttk.Combobox(self.frame_main, state='readonly')
ft = tkFont.Font(family='Times',size=10)
self.GLineEdit_803["font"] = ft
self.GLineEdit_803.place(x=40,y=40,width=252,height=30)
self.GLineEdit_803.bind("<<ComboboxSelected>>", self.choose_game)
self.GLabel_354=tk.Label(self.frame_main)
ft = tkFont.Font(family='Times',size=10)
self.GLabel_354["font"] = ft
self.GLabel_354["fg"] = "#333333"
self.GLabel_354["justify"] = "center"
self.GLabel_354["text"] = "在 播 "
self.GLabel_354.place(x=0,y=80,width=30,height=30)
self.GLineEdit_178=ttk.Combobox(self.frame_main, state='readonly')
ft = tkFont.Font(family='Times',size=10)
self.GLineEdit_178["font"] = ft
self.GLineEdit_178.place(x=40,y=80,width=253,height=30)
self.GLineEdit_178.bind("<<ComboboxSelected>>", self.choose_anchor)
self.GButton_112=tk.Button(self.frame_main)
self.GButton_112["bg"] = "#efefef"
ft = tkFont.Font(family='Times',size=10)
self.GButton_112["font"] = ft
self.GButton_112["fg"] = "#000000"
self.GButton_112["relief"] = "groove"
self.GButton_112["justify"] = "center"
self.GButton_112["text"] = "解析"
self.GButton_112.place(x=50,y=160,width=96,height=30)
self.GButton_112["command"] = self.GButton_112_command
self.GButton_706=tk.Button(self.frame_main)
self.GButton_706["bg"] = "#efefef"
ft = tkFont.Font(family='Times',size=10)
self.GButton_706["font"] = ft
self.GButton_706["fg"] = "#000000"
self.GButton_706["justify"] = "center"
self.GButton_706["text"] = "加入关注"
self.GButton_706.place(x=170,y=160,width=98,height=30)
self.GButton_706["command"] = self.GButton_706_command
self.GLineEdit_945=tk.Entry(self.frame_main)
self.GLineEdit_945["borderwidth"] = "1px"
ft = tkFont.Font(family='Times',size=10)
self.GLineEdit_945["font"] = ft
self.GLineEdit_945["fg"] = "#333333"
self.GLineEdit_945["justify"] = "center"
self.GLineEdit_945["text"] = "id"
self.GLineEdit_945.place(x=40,y=120,width=253,height=30)
self.GLabel_608=tk.Label(self.frame_main)
ft = tkFont.Font(family='Times',size=10)
self.GLabel_608["font"] = ft
self.GLabel_608["fg"] = "#333333"
self.GLabel_608["justify"] = "center"
self.GLabel_608["text"] = "房间ID"
self.GLabel_608.place(x=0,y=120,width=41,height=30)
self.GLabel_538=tk.Label(self.frame_main)
ft = tkFont.Font(family='Times',size=10)
self.GLabel_538["font"] = ft
self.GLabel_538["fg"] = "#333333"
self.GLabel_538["justify"] = "center"
self.GLabel_538["text"] = "主播名"
self.GLabel_538.place(x=0,y=200,width=40,height=32)
self.GLabel_803=tk.Label(self.frame_main)
self.GLabel_803["bg"] = "#ffffff"
ft = tkFont.Font(family='Times',size=10)
self.GLabel_803["font"] = ft
self.GLabel_803["fg"] = "#333333"
self.GLabel_803["justify"] = "center"
self.GLabel_803.place(x=40,y=200,width=252,height=31)
self.GLabel_953=tk.Label(self.frame_main)
ft = tkFont.Font(family='Times',size=10)
self.GLabel_953["font"] = ft
self.GLabel_953["fg"] = "#333333"
self.GLabel_953["justify"] = "center"
self.GLabel_953["text"] = "房间名"
self.GLabel_953.place(x=0,y=240,width=42,height=30)
self.GLabel_201=tk.Label(self.frame_main)
self.GLabel_201["bg"] = "#ffffff"
ft = tkFont.Font(family='Times',size=10)
self.GLabel_201["font"] = ft
self.GLabel_201["fg"] = "#333333"
self.GLabel_201["justify"] = "center"
self.GLabel_201.place(x=40,y=240,width=253,height=30)
self.GLabel_913=tk.Label(self.frame_main)
ft = tkFont.Font(family='Times',size=10)
self.GLabel_913["font"] = ft
self.GLabel_913["fg"] = "#333333"
self.GLabel_913["justify"] = "center"
self.GLabel_913["text"] = "清晰度"
self.GLabel_913.place(x=0,y=280,width=36,height=30)
self.GLineEdit_440=ttk.Combobox(self.frame_main, state='readonly')
ft = tkFont.Font(family='Times',size=10)
self.GLineEdit_440["font"] = ft
self.GLineEdit_440.place(x=40,y=280,width=254,height=30)
self.GLineEdit_440.bind("<<ComboboxSelected>>", self.chooseCDN)
self.GLabel_708=tk.Label(self.frame_main)
ft = tkFont.Font(family='Times',size=10)
self.GLabel_708["font"] = ft
self.GLabel_708["fg"] = "#333333"
self.GLabel_708["justify"] = "center"
self.GLabel_708["text"] = "地址"
self.GLabel_708.place(x=0,y=320,width=35,height=30)
self.GLineEdit_795=tk.Entry(self.frame_main)
self.GLineEdit_795["borderwidth"] = "1px"
ft = tkFont.Font(family='Times',size=10)
self.GLineEdit_795["font"] = ft
self.GLineEdit_795["fg"] = "#333333"
self.GLineEdit_795["justify"] = "center"
self.GLineEdit_795["text"] = "address"
self.GLineEdit_795.place(x=40,y=320,width=253,height=30)
self.GLineEdit_136=tk.Entry(self.frame_main)
self.GLineEdit_136["borderwidth"] = "1px"
ft = tkFont.Font(family='Times',size=10)
self.GLineEdit_136["font"] = ft
self.GLineEdit_136["fg"] = "#333333"
self.GLineEdit_136["justify"] = "center"
self.GLineEdit_136["text"] = "关注列表"
self.GLineEdit_136.place(x=300,y=0,width=293,height=352)
yscroll = Scrollbar(self.GLineEdit_136, orient=VERTICAL)
yscroll.pack(side=RIGHT, fill=Y)
titles = ('房号', '主播', '操作')
self.tvList =ttk.Treeview(self.GLineEdit_136, columns=titles, style='Treeview', show='headings', height=21,
yscrollcommand=yscroll.set)
self.tvList.pack()
for i in range(len(titles)):
self.tvList.heading(column=titles, text=titles, anchor=CENTER) # 定义表头
self.tvList.column(titles, minwidth=20, anchor=CENTER ,stretch=True) # 定义列
self.tvList.column(titles, width=80, anchor=CENTER)
self.tvList.column(titles, width=120, anchor='w')
self.tvList.column(titles, width=75, anchor=CENTER)
yscroll.config(command=self.tvList.yview)
self.tvList.bind("<ButtonRelease-1>", self.tvList_leftButtonRelease)
def tvList_leftButtonRelease(self,event):
if str(event.widget) == ".!frame.!entry3.!treeview":# 左键释放的是否为表格
items = event.widget.selection()
try:
item = self.tvList.item(items)['values']
id = item
name = item
self.GLineEdit_945.delete(0,'end')
self.GLineEdit_945.insert(0,id)
self.GLabel_803['text'] = name
self.GButton_112_command()
except:
pass
row = self.tvList.identify_row(event.y)# 点击的行
column = self.tvList.identify_column(event.x)# 点击的列
col = int(str(column).replace('#', ''))# 列号
item = self.tvList.item(row)['values']
if item:
if col == 3:
# print("删除操作")
value = f'{item}={item}'
self.zhubo_list.remove(value)
self.tvList.delete(row)
self.save_list(self.zhubo_list)
def save_list(self,zhubo_list):
with open('HYZBconfig.ini', 'w', encoding='utf-8') as writer:
for item in zhubo_list:
writer.writelines(item)
writer.writelines('\n')
def getzhubolist(self):
try:
file = open("HYZBconfig.ini", "rb")
l1 = []
while 1:
line = file.readline().strip()
data = line.decode('utf-8', 'ignore') #ignore"的作用就是有异常就越过
if len(data)>0 and len(data.split('='))>1 :
l1.append(data)
if not line:
break
return l1
except:
with open('HYZBconfig.ini', 'w', encoding='utf-8') as writer:
writer.writelines('关注列表')
writer.writelines('\n')
return []
#关注
def GButton_706_command(self):
roomid = self.GLineEdit_945.get().strip()
anchor = self.GLabel_803.cget("text")
self.tvList.insert('','end',values=((roomid,anchor,'删除')))
self.zhubo_list.append((f'{roomid}={anchor}'))
with open('HYZBconfig.ini', 'a+', encoding='utf-8') as writer:
writer.writelines(f'{roomid}={anchor}')
writer.writelines('\n')
def settvlist(self,zhubo_list):
if len(zhubo_list) < 1:
return
for zhubo in zhubo_list:
self.count +=1
li = zhubo.split('=')
li.append('删除')
self.tvList.insert('','end',values=(li))
def GButton_274_command(self):
url = self.GLineEdit_795.get().strip()
if not url:
return
if self.player.get_state() == 0:
self.player.resume()
elif self.player.get_state() == 1:
self.player.play(url)
else:
self.player.play(url)
self.frame_video.tkraise()
#停止
def GButton_159_command(self):
self.player.stop()
self.frame_main.tkraise()
#暂停
def GButton_751_command(self):
self.player.pause()
#静音
def GButton_991_command(self):
vol = self.player.get_volume()
if vol == 0:
self.player.set_volume(self.vol)
else:
self.vol = self.player.get_volume()
self.player.set_volume(0)
#调音
def GButton_79_command(self,value):
self.player.set_volume(int(value))
# self.scint
#全屏
def GButton_39_command(self):
ifself.flag:
self.root.attributes('-fullscreen',True)
# self.frame_video.tkraise()
self.frame_buttom.grid_forget()
else:
self.root.attributes('-fullscreen',False)
self.frame_buttom.grid(row=1,column=0,sticky=NSEW,padx=0, pady=0 )
self.flag = not self.flag
def change_vol(self,evt):
vol = self.player.get_volume()
if evt.delta == 120:
if vol < 100:
vol += 5
else:
if vol > 0:
vol -= 5
self.player.set_volume(vol)
self.scint.set(vol)
print(vol)
def changescreen(self,event):
self.GButton_39_command()
def exitfullscreen(self,event):
self.flag = True
self.root.attributes('-fullscreen',False)
self.frame_buttom.grid(row=1,column=0,sticky=NSEW,padx=0, pady=0 )
def create_video_view(self,wid):
self.player.set_window(wid)
def choose_active(self,event):
url = 'https://www.huya.com/'
text = self.GLineEdit_678.get()
url += text.split('/')
self.set_game_list(url)
def set_game_list(self,url):
# url = 'https://www.huya.com/g'
req = requests.get(url, headers=self.headers).content.decode('utf8', 'ignore')
html_etree = etree.HTML(req)
game_list =html_etree.xpath('//*[@id="js-game-list"]/li')
value =[]
for idx,row in enumerate(game_list):
idx +=1
game = row.attrib['title']
url =self.get_row_text(row,'./a','href')
value.append((game,url))
self.GLineEdit_803["values"] = value
self.GLineEdit_803.current(0)
self.choose_game(None)
def choose_game(self,event):
url = 'http'
text = self.GLineEdit_803.get()
url += text.split('http')
self.set_live_list(url)
def set_live_list(self,url):
req = requests.get(url, headers=self.headers).content.decode('utf8', 'ignore')
html_etree = etree.HTML(req)
live_list =html_etree.xpath('//*[@id="js-live-list"]/li')
value =[]
for idx,row in enumerate(live_list):
idx +=1
nick = self.get_row_text(row,'.//*[@class="nick"]')
title = self.get_row_text(row,'.//*[@class="title"]')
#人气
js_num = self.get_row_text(row,'.//i[@class="js-num"]')
tag_recommend =self.get_row_text(row,'.//*[@class="tag tag-recommend"]')
#英雄
pos2_content = self.get_row_text(row,'.//*[@class="tag-pos2-content"]')
url_anchor =self.get_row_text(row,'.//a','href')
value.append((nick,title,js_num,tag_recommend,pos2_content,url_anchor))
self.GLineEdit_178["values"] = value
self.GLineEdit_178.current(0)
self.choose_anchor(None)
def choose_anchor(self,event):
url = 'http'
text = self.GLineEdit_178.get()
url += text.split('http')
req = requests.get(url, headers=self.headers).content.decode('utf8', 'ignore')
html_etree = etree.HTML(req)
host_rid =self.get_row_text(html_etree,'//span[@class="host-rid"]/em')
self.GLineEdit_945.delete(0,'end')
self.GLineEdit_945.insert(0,host_rid)
def get_row_text(self,str_html,str_analysis,str_attrib='0'):
table_element = str_html.xpath(str_analysis)
if len(table_element) > 0:
if str_attrib == '0':
return table_element.text
else:
return table_element.attrib
else:
return ' '
#解析
def GButton_112_command(self):
self.GLineEdit_795.delete(0,'end')
room_id = self.GLineEdit_945.get().strip()
if not room_id:
return
try:
api_url = 'https://mp.huya.com/cache.php?m=Live&do=profileRoom&roomid='
html = requests.get(api_url + room_id, headers=self.headers)
data = json.loads(html.text)['data']
nick = data['profileInfo']['nick']
room_name = data['liveData']['roomName']
liveStatus = data['liveStatus']
except:
self.GLabel_803['text']='房号错误!'
return
if liveStatus == "OFF":
self.GLabel_803['text']=f'未开播 {nick}'
return f'{room_name} {nick} is offline'
elif liveStatus == "REPLAY":
self.GLabel_803['text']=f'未开播 {nick}'
return f'{room_name} {nick} is REPLAY'
else:
self.GLabel_803['text']=f'{nick}'
self.GLabel_201['text']=f'{room_name}'
stream_dict = data['stream']
flv = stream_dict['flv']# type: dict
cdn = flv['multiLine']# type: List
bitRateInfo = json.loads(data['liveData']['bitRateInfo'])
bitRateInfo.append(({'sDisplayName': '原画', 'iBitRate': -1, 'iCodecType': 0, 'iCompatibleFlag': 0, 'iHEVCBitRate': -1}))
listbox = []
for item in bitRateInfo:
count=0
for i in cdn:
count += 1
url = i['url'].replace('http://', 'https://')
if item["iBitRate"] >= 0:
url = url.replace('imgplus.flv', f'imgplus_{item["iBitRate"]}.flv')
listbox.append(f'【{item["sDisplayName"]}-线路{count}】::{url}')
self.GLineEdit_440["values"] = listbox
for i in listbox:
if i.startswith('【蓝光4M】'):
# self.GListBox_294.current(1)
self.GLineEdit_440.set(i)
self.GLineEdit_795.delete(0,'end')
self.GLineEdit_795.insert(0,i.split('::'))
break
else:
self.GLineEdit_440.current(1)
self.GLineEdit_795.delete(0,'end')
self.GLineEdit_795.insert(0,i.split('::'))
def chooseCDN(self,event):
url = self.GLineEdit_440.get()
self.GLineEdit_795.delete(0,'end')
self.GLineEdit_795.insert(0,url.split('::'))
if __name__ == "__main__":
root = tk.Tk()
app = App(root)
root.mainloop()
大佬 出现了这个问题 能帮忙看看、?
Traceback (most recent call last):
File "huya_live_read2.py", line 677, in <module>
File "huya_live_read2.py", line 140, in __init__
File "huya_live_read2.py", line 557, in choose_active
File "huya_live_read2.py", line 571, in set_game_list
File "huya_live_read2.py", line 576, in choose_game
File "huya_live_read2.py", line 591, in set_live_list
File "huya_live_read2.py", line 613, in get_row_text
File "src\lxml\etree.pyx", line 2494, in lxml.etree._Attrib.__getitem__
KeyError: 'href' 6呀我先试试是看 刚刚去测试了下,显示房间号错误。不知道我是不是个例。
当然,我输入的是房间号 好东西,值得点赞...... 流畅,清晰度不错。要是有自定义缩放就更好了~ 支持原创,膜拜的大佬{:1_919:} 感觉不错 下来试试看 感谢分享 要是有自定义缩放就更好了~ 感谢楼主分享! 厉害,感谢楼主分享