[Python] 纯文本查看 复制代码
import tkinter as tk
from tkinter import ttk, font
import threading
import time
from datetime import datetime, timedelta
import requests
import json
from urllib.parse import urljoin
class SportsLivePlatform:
def __init__(self, root):
self.root = root
self.root.title("体育赛事直播中心")
self.root.geometry("1000x700")
self.root.configure(bg="#0F172A") # 深色背景
# 确保中文显示正常
self.default_font = font.nametofont("TkDefaultFont")
self.default_font.configure(family="SimHei", size=10)
self.root.option_add("*Font", self.default_font)
# 比赛数据
self.basketball_games = []
self.football_games = []
# 添加数据URL
self.base_url = "https://matchs.qiumibao.com/live/"
self.basketball_data_url = urljoin(self.base_url, "all.htm")
# 创建UI
self.create_ui()
# 启动数据更新线程
self.stop_event = threading.Event()
self.update_thread = threading.Thread(target=self.update_data)
self.update_thread.daemon = True
self.update_thread.start()
# 初始数据加载
self.fetch_live_data()
def create_ui(self):
# 顶部导航栏
navbar = tk.Frame(self.root, bg="#1E40AF", height=50)
navbar.pack(fill=tk.X)
title_label = tk.Label(navbar, text="体育赛事直播中心", bg="#1E40AF", fg="white",
font=("SimHei", 16, "bold"))
title_label.pack(side=tk.LEFT, padx=20, pady=10)
# 标签页控件
tab_control = ttk.Notebook(self.root)
# 篮球比赛标签页
basketball_frame = tk.Frame(tab_control, bg="#0F172A")
tab_control.add(basketball_frame, text="篮球赛事")
# 足球比赛标签页
football_frame = tk.Frame(tab_control, bg="#0F172A")
tab_control.add(football_frame, text="足球赛事")
tab_control.pack(expand=1, fill="both", padx=10, pady=10)
# 篮球比赛列表
self.basketball_list = tk.Frame(basketball_frame, bg="#0F172A")
self.basketball_list.pack(fill=tk.BOTH, expand=True)
# 足球比赛列表
self.football_list = tk.Frame(football_frame, bg="#0F172A")
self.football_list.pack(fill=tk.BOTH, expand=True)
def fetch_live_data(self):
"""从网络获取实时比赛数据"""
try:
# 设置请求头,模拟浏览器访问
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Referer': 'https://www.188bifen.com/',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
}
# 发送HTTP请求获取数据
response = requests.get(self.basketball_data_url, headers=headers)
if response.status_code == 200:
# 解析JSON数据
data = json.loads(response.text)
if "matches" in data:
self.parse_basketball_data(data["matches"])
else:
print("数据格式不正确:找不到'matches'字段")
self.load_fallback_data()
else:
print(f"请求失败:状态码 {response.status_code}")
self.load_fallback_data()
except Exception as e:
print(f"获取数据时出错:{e}")
self.load_fallback_data()
def parse_basketball_data(self, matches):
"""解析篮球比赛数据"""
self.basketball_games = []
for match in matches:
try:
# 解析比赛基本信息
match_id = match[0] # 比赛ID
sport_type = match[19] # 体育类型 (7表示篮球)
if sport_type != '2': # 跳过非篮球比赛 ["", "zuqiu", "lanqiu", "game"][t[19]]
continue
# 解析主队和客队信息
home_team_info = match[5]
away_team_info = match[6]
home_team_name = home_team_info[1] # 主队名称
away_team_name = away_team_info[1] # 客队名称
home_score = home_team_info[-2] # 主队得分
away_score = away_team_info[-2] # 客队得分
# 解析比赛状态
match_status = match[3] # 比赛状态码
period_info = match[8] # 比赛阶段信息
# 转换比赛状态
status_text = self.get_status_text(match_status, period_info)
# 创建比赛对象
game = {
"id": match_id,
"home_team": home_team_name,
"away_team": away_team_name,
"home_score": home_score,
"away_score": away_score,
"status_text": status_text,
"last_updated": datetime.now()
}
self.basketball_games.append(game)
except Exception as e:
print(f"解析比赛数据时出错:{e}")
continue
# 显示数据
self.update_ui()
def get_status_text(self, status_code, period_info):
"""根据状态码和阶段信息获取比赛状态文本"""
status_map = {
0: "未开始",
1: "进行中",
2: "上半场",
3: "下半场",
4: "加时赛",
5: "点球大战",
6: "已结束",
7: "中断",
8: "推迟",
9: "取消",
10: "延期",
11: "待定"
}
# 获取基本状态文本
status_text = status_map.get(status_code, "未知状态")
# 如果比赛进行中,添加具体时间信息
if status_code == 1:
period = period_info[0] # 比赛阶段 (1-4表示常规时间节数,5表示加时赛)
time_remaining = period_info[1] # 剩余时间
if period in [1, 2, 3, 4]:
status_text = f"Q{period} {time_remaining}"
elif period == 5:
status_text = f"OT {time_remaining}"
return status_text
def load_fallback_data(self):
"""加载备用数据(当网络请求失败时使用)"""
# 模拟加载初始篮球比赛数据
self.basketball_games.append({
"id": 1,
"home_team": "洛杉矶湖人",
"away_team": "布鲁克林篮网",
"home_score": 88,
"away_score": 82,
"status_text": "Q3 4:23",
"last_updated": datetime.now()
})
self.basketball_games.append({
"id": 2,
"home_team": "金州勇士",
"away_team": "波士顿凯尔特人",
"home_score": 76,
"away_score": 76,
"status_text": "Q2 7:12",
"last_updated": datetime.now() - timedelta(minutes=2)
})
# 更新UI
self.update_ui()
def update_data(self):
"""后台线程更新比赛数据"""
while not self.stop_event.is_set():
# 每隔一段时间从网络获取最新数据
self.fetch_live_data()
# 等待一段时间再更新
time.sleep(30) # 每30秒更新一次
def update_ui(self):
"""更新UI显示"""
# 清空现有比赛卡片
for widget in self.basketball_list.winfo_children():
widget.destroy()
for widget in self.football_list.winfo_children():
widget.destroy()
# 创建篮球比赛卡片
for game in self.basketball_games:
card = tk.Frame(self.basketball_list, bg="#1E293B", bd=1, relief=tk.RAISED, padx=10, pady=10)
card.pack(fill=tk.X, padx=10, pady=5)
# 比赛状态
status_frame = tk.Frame(card, bg="#1E293B")
status_frame.pack(fill=tk.X)
# 确定状态标签颜色
if "进行中" in game["status_text"] or "Q" in game["status_text"] or "OT" in game["status_text"]:
status_color = "#DC2626" # 红色表示直播中
elif "已结束" in game["status_text"]:
status_color = "#059669" # 绿色表示已结束
else:
status_color = "#F59E0B" # 橙色表示其他状态
status_label = tk.Label(status_frame, text=game["status_text"], bg=status_color, fg="white",
font=("SimHei", 10, "bold"), padx=5, pady=2)
status_label.pack(side=tk.LEFT)
# 主队信息
home_frame = tk.Frame(card, bg="#1E293B")
home_frame.pack(fill=tk.X, pady=5)
home_team_label = tk.Label(home_frame, text=game["home_team"], bg="#1E293B", fg="#E2E8F0",
font=("SimHei", 12))
home_team_label.pack(side=tk.LEFT, padx=10)
home_score_label = tk.Label(home_frame, text=str(game["home_score"]), bg="#1E293B", fg="#E2E8F0",
font=("SimHei", 16, "bold"))
home_score_label.pack(side=tk.RIGHT, padx=10)
# 客队信息
away_frame = tk.Frame(card, bg="#1E293B")
away_frame.pack(fill=tk.X, pady=5)
away_team_label = tk.Label(away_frame, text=game["away_team"], bg="#1E293B", fg="#E2E8F0",
font=("SimHei", 12))
away_team_label.pack(side=tk.LEFT, padx=10)
away_score_label = tk.Label(away_frame, text=str(game["away_score"]), bg="#1E293B", fg="#E2E8F0",
font=("SimHei", 16, "bold"))
away_score_label.pack(side=tk.RIGHT, padx=10)
# 最后更新时间
last_updated = game["last_updated"].strftime("%H:%M:%S")
updated_label = tk.Label(card, text=f"最后更新: {last_updated}", bg="#1E293B", fg="#94A3B8",
font=("SimHei", 9))
updated_label.pack(anchor=tk.E)
def run(self):
"""运行应用程序"""
self.root.mainloop()
def stop(self):
"""停止应用程序"""
self.stop_event.set()
self.update_thread.join()
if __name__ == "__main__":
root = tk.Tk()
app = SportsLivePlatform(root)
try:
app.run()
finally:
app.stop()