182 lines
5.9 KiB
Python
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() |