169 lines
5.4 KiB
Python
169 lines
5.4 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
|
||
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
|
||
|
||
# 计算三者的平均排名
|
||
avg_rank = np.mean([item['f225'], item['f263'], item['f264']])
|
||
|
||
parsed_data.append({
|
||
'股票名称': stock_names[0], # 只取第一个股票名称
|
||
'今日排名': item['f225'],
|
||
'5日排名': item['f263'],
|
||
'10日排名': item['f264'],
|
||
'平均排名': avg_rank
|
||
})
|
||
|
||
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('#FFFFFF') # 设置背景色
|
||
fig.patch.set_facecolor('#FFFFFF') # 设置背景色
|
||
|
||
# 准备数据
|
||
stock_names = data['股票名称'].tolist()[:30] # 只显示前15个股票,避免过于拥挤
|
||
avg_ranks = data['平均排名'].tolist()[:30]
|
||
|
||
# 设置柱状图位置
|
||
x = np.arange(len(stock_names))
|
||
width = 0.5 # 设置柱状图宽度
|
||
|
||
# 绘制柱状图
|
||
rects1 = ax.bar(x, avg_ranks, width, label='平均排名', color='#2980B9', alpha=0.9, edgecolor='black')
|
||
|
||
# 设置标题和标签
|
||
ax.set_title('股票资金流向排名对比(排名越高表示资金流入越多)', fontsize=18, pad=20, color='black')
|
||
ax.set_xlabel('股票名称', fontsize=14, color='black')
|
||
ax.set_ylabel('平均排名', fontsize=14, color='black')
|
||
|
||
# 设置x轴刻度
|
||
ax.set_xticks(x)
|
||
ax.set_xticklabels(stock_names, rotation=45, ha='right', fontsize=12, color='black')
|
||
|
||
# 设置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()
|