import requests import pandas as pd import json from datetime import datetime import matplotlib.pyplot as plt import matplotlib import numpy as np import tkinter as tk from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体 matplotlib.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 def get_fund_flow_data(): """获取资金流向数据,包括板块和股票名称""" url = "https://push2delay.eastmoney.com/api/qt/clist/get" params = { 'fid': 'f184', 'po': '1', 'pz': '50', 'pn': '1', 'np': '1', 'fltt': '2', 'invt': '2', 'fields': 'f2,f3,f12,f13,f14,f62,f184,f225,f165,f263,f109,f175,f264,f160,f100,f124,f265,f1', 'ut': 'b2884a393a59ad64002292a3e90d46a5', 'fs': 'm:0+t:6+f:!2,m:0+t:13+f:!2,m:0+t:80+f:!2,m:1+t:2+f:!2,m:1+t:23+f:!2,m:0+t:7+f:!2,m:1+t:3+f:!2', } 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://data.eastmoney.com/zjlx/list.html' } try: response = requests.get(url, params=params, headers=headers) print(response.text) data = json.loads(response.text) if 'data' not in data or 'diff' not in data['data']: raise Exception("未能获取到数据") items = data['data']['diff'] parsed_data = [] for idx, item in enumerate(items[:50]): # 获取每个板块的股票名称 stock_names = item.get('f14', '') # 打印调试信息,检查 f62 字段的内容 print(f"板块 {item['f14']} - f62 字段内容: {stock_names}") if isinstance(stock_names, str): stock_names = stock_names.split(';') # 假设股票名称以分号分隔 else: stock_names = [] # 如果 f62 为空或格式不正确,设置为空列表 # 如果股票名称为空,则跳过该项 if not stock_names: print(f"板块 {item['f14']} 没有有效的股票名称") continue parsed_data.append({ '板块': item['f100'], '今日排名': item['f225'], # 转换为排名 '5日排名': item['f263'], # 临时使用索引作为排名 '10日排名': item['f264'], # 临时使用索引作为排名 '股票名称': stock_names[0] # 添加股票名称 }) return pd.DataFrame(parsed_data) except Exception as e: print(f"获取数据时发生错误: {str(e)}") return None def create_ranking_visualization(data): """创建排名可视化窗口""" root = tk.Tk() root.title("板块资金流向排名对比") root.geometry("1500x900") root.configure(bg='#2C3E50') # 深色背景 fig = Figure(figsize=(15, 10)) ax = fig.add_subplot(111) # 设置样式 ax.set_facecolor('#34495E') # 设置背景色 fig.patch.set_facecolor('#2C3E50') # 设置背景色 # 准备数据 sectors = data['板块'].tolist()[:15] # 只显示前15个板块,避免过于拥挤 today_ranks = data['今日排名'].tolist()[:15] five_day_ranks = data['5日排名'].tolist()[:15] ten_day_ranks = data['10日排名'].tolist()[:15] # 设置柱状图位置 x = np.arange(len(sectors)) width = 0.25 # 绘制柱状图 rects1 = ax.bar(x - width, today_ranks, width, label='今日排名', color='#E74C3C', alpha=0.9, edgecolor='black') rects2 = ax.bar(x, five_day_ranks, width, label='5日排名', color='#F39C12', alpha=0.9, edgecolor='black') rects3 = ax.bar(x + width, ten_day_ranks, width, label='10日排名', color='#2980B9', alpha=0.9, edgecolor='black') # 设置标题和标签 ax.set_title('板块资金流向排名对比(排名越高表示资金流入越多)', fontsize=18, pad=20, color='white') ax.set_xlabel('板块', fontsize=14, color='white') ax.set_ylabel('排名', fontsize=14, color='white') # 设置x轴刻度 ax.set_xticks(x) ax.set_xticklabels(sectors, rotation=45, ha='right', fontsize=12, color='white') # 设置y轴范围和刻度 ax.set_ylim(0, 55) ax.set_yticks(np.arange(0, 51, 10)) # 添加图例 ax.legend(loc='upper right', fontsize=12) # 设置网格 ax.grid(True, linestyle='--', alpha=0.3, axis='y') # 调整布局 fig.tight_layout() # 创建canvas canvas = FigureCanvasTkAgg(fig, master=root) canvas.draw() canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) # 生成并显示词云 plt.figure(figsize=(8, 6)) plt.axis('off') plt.show() # 添加关闭按钮 close_button = tk.Button(root, text="关闭", command=root.quit, font=('SimHei', 12), bg='#C82423', fg='white', padx=10, pady=5) close_button.pack(side=tk.BOTTOM, pady=10) return root def main(): # 获取资金流向数据 print("正在获取资金流向数据...") data = get_fund_flow_data() if data is not None: # 保存数据到Excel current_date = datetime.now().strftime('%Y%m%d') output_file = f'fund_flow_ranking_{current_date}.xlsx' data.to_excel(output_file, index=False) print(f"资金流向数据已保存到: {output_file}") # 创建并显示可视化窗口 print("正在创建可视化窗口...") root = create_ranking_visualization(data) root.mainloop() else: print("获取数据失败,请检查网络连接或接口可用性。") if __name__ == "__main__": main()