python-data/east/diagram.PY
2025-05-10 16:45:01 +08:00

182 lines
5.9 KiB
Python

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
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)
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', '')
if isinstance(stock_names, str):
stock_names = stock_names.split(';') # 假设股票名称以分号分隔
else:
stock_names = [] # 如果 f62 为空或格式不正确,设置为空列表
if not stock_names:
continue
# 确保涨停数是有效的数字,并且为正数
limit_up_count = item.get('f165', 0)
if not isinstance(limit_up_count, (int, float)) or limit_up_count < 0:
limit_up_count = 0
parsed_data.append({
'板块': item.get('f100', '未知板块'),
'涨停数': limit_up_count, # 获取涨停股数,确保是非负数
})
# 确保至少有一些数据
if not parsed_data:
raise Exception("未能解析到有效的板块数据")
return pd.DataFrame(parsed_data)
except Exception as e:
print(f"获取数据时发生错误: {str(e)}")
return None
def create_pie_chart(data):
"""创建涨停股数的扇形图"""
# 确保所有要绘制的值都是正数
filtered_data = data[data['涨停数'] > 0].copy()
# 如果没有正数值,给用户提示并返回
if filtered_data.empty:
print("没有找到正数的涨停股数,无法绘制饼图")
return None
# 获取前15个有效的板块的涨停股数
filtered_data = filtered_data.sort_values('涨停数', ascending=False).head(15)
sectors = filtered_data['板块'].tolist()
pie_data = filtered_data['涨停数'].tolist()
# 确保数据长度一致且非空
if not sectors or not pie_data or len(sectors) != len(pie_data):
print("数据不一致或为空,无法绘制饼图")
return None
# 打印一下要绘制的数据,用于调试
print("要绘制的数据:")
for i, (sector, value) in enumerate(zip(sectors, pie_data)):
print(f"{i + 1}. {sector}: {value}")
root = tk.Tk()
root.title("前15板块涨停股数占比")
root.geometry("800x600")
root.configure(bg='#2C3E50') # 深色背景
# 创建Matplotlib图形
fig = plt.Figure(figsize=(8, 6), facecolor='#FFFFFF')
ax = fig.add_subplot(111)
# 设置图形背景颜色
ax.set_facecolor('#2C3E50')
# 绘制扇形图
wedges, texts, autotexts = ax.pie(
pie_data,
labels=sectors,
autopct='%1.1f%%',
startangle=140,
colors=plt.cm.Paired.colors, # 使用配色方案
wedgeprops={'edgecolor': 'black', 'linewidth': 0.5} # 设置扇形边框
)
# 设置标题
ax.set_title('前15板块涨停股数占比', fontsize=16, color='black', pad=20)
# 设置标签样式
for text in texts:
text.set_fontsize(10)
text.set_color('black')
for autotext in autotexts:
autotext.set_fontsize(10)
autotext.set_color('black')
# 设置图例
ax.legend(wedges, sectors, title="板块", loc="upper left", fontsize=10, bbox_to_anchor=(1, 1))
# 将图形添加到Tkinter窗口
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
# 添加关闭按钮
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)
# 启动Tkinter主循环
root.mainloop()
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}")
# 检查数据是否包含有效的涨停数
if data['涨停数'].max() <= 0:
print("警告: 没有找到正的涨停数据,无法绘制饼图")
else:
# 创建并显示扇形图
print("正在创建扇形图...")
create_pie_chart(data)
else:
print("获取数据失败,请检查网络连接或接口可用性。")
if __name__ == "__main__":
main()