上一章节,我们获取了股票的实时数据并进行展示, 我看有群友问,怎么获取某财富的股票的历史数据。
今天小亥整理了一下, 分享给大家。 并形成了 streamlit 页面,免费开放给大家。
样式大概如下:
可以查看 K线图

可以查看收盘 价走势

可以查看日K数据并进行下载

也可以查看原始数据。

本文含系统自动匹配的广告,广告收入用于支持持续创作,感谢理解
股票的实时数据,从 某财富平台获取,暂不采用 金亥跃江的股票平台数据。
请求样式为:
https://www.eastmoney.com/
请求地址:
https://push2his.eastmoney.com/api/qt/stock/kline/get?cb=jQuery351030739714292037856_1783413734029&secid=1.000001&ut=fa5fd1943c7b386f172d6893dbfba10b&fields1=f1%2Cf2%2Cf3%2Cf4%2Cf5%2Cf6&fields2=f51%2Cf52%2Cf53%2Cf54%2Cf55%2Cf56%2Cf57%2Cf58%2Cf59%2Cf60%2Cf61&klt=101&fqt=1&end=20500101&lmt=120&_=1783413734042请求方式: Get
请求参数:
cb: jQuery351030739714292037856_1783413734029secid: 1.000001ut: fa5fd1943c7b386f172d6893dbfba10bfields1: f1%2Cf2%2Cf3%2Cf4%2Cf5%2Cf6fields2: f51%2Cf52%2Cf53%2Cf54%2Cf55%2Cf56%2Cf57%2Cf58%2Cf59%2Cf60%2Cf61klt: 101fqt: 1end: 20500101lmt: 120_: 1请求头 Cookie :
xxxxx
关于相应的解析,可以看历史文章
为了方便大家理解和使用, 小亥将采用 streamlit 进行编写相关的脚本, 这样有页面,也方便点击 。
大家可以通过 AI 自行实现, 小亥这儿提供一个简单的版本。
脚本名称为 stock_history_df.py
安装依赖:
pip install streamlit requests pandas plotly -i https://pypi.tuna.tsinghua.edu.cn/simple完整的代码是:
# -*- coding: utf-8 -*-"""Stock History - 东方财富日K线数据展示工具通过输入 secid 获取股票日K线数据,支持表格展示和K线图可视化。"""import timeimport jsonimport reimport requestsimport pandas as pdimport streamlit as stimport plotly.graph_objects as gofrom plotly.subplots import make_subplots# ==================== 配置 ====================EASTMONEY_API = "https://push2his.eastmoney.com/api/qt/stock/kline/get"COOKIE = "st_nvi=JXtoOSyJp10OOMO7codqk7cf9; nid18=0d409d1bdf0f765bed359fb5afb19b0e; nid18_create_time=1776172143567; gviem=Ra4LtS_JOVVDYxS7GBjK1e061; gviem_create_time=1776172143567; mtp=1; ct=LvJ51CmrljYbsp7qFlSOHn7VFCigLZ-oUKziSdwhm6QoiW2PfEY8NuMNbIAhQltzdIL7cXRBNiMr4qp1BoNETrOvupIlJSg6-CX9utxINQQ29VzIW752DBIjV2HnhLPM4vZqa8gKqQIUyV-nurLw-Mt1uEp_5c2QBnB3r8bICYo; ut=FobyicMgeV5FJnFT189SwKsr5jWOQIjKhBFsML-oN6OsBB6yqsyPbl2exqGvqIznyDIwf2IUGOjBI62xNrfy4dMMINyh9bY6q097910z-zTtlawTdRkdujUTwgPoC4gsmCb8_bdltdAizQOiKYVyQb607PJ9ZUDekqP9gFhZ5XrCB82ujMtz8dksMJDIlaacTw2TiUGSTPEBLDJCV0r3NFdaW9u3xZXbLwoZpZZ4Mn4Yvp7p9sGGpk6VLmXuEB28jmDszyO-GIb3ZHapeQShBiz3_WSmXHmGMyd9_yTZHzw3TVAZUsxTpA3AxHfxYzyAdU9TOiJfq4SUwdkaXVbn7oOKONuWOFDJ; pi=3113356087927502%3Bu3113356087927502%3B%E9%87%91%E4%BA%A5%E8%B7%83%E6%B1%9F%E8%81%8A%E9%87%8F%E5%8C%96%3BZ8jzwulgDvjTB%2FdfMXwe7MWCuDFdJYeEZ9YXPw9DaPvNf0yss8FbUnlXbM7VA%2BXQMLHx%2Fd8Jr4Ur6RwdlfiezLt0muyOGZXSCSQyLCn0IYkUMhRoBXDNUUWpEe2YNyTEQMRw68ZUoFByBu86AcX6rz2eoYpSzkDX51UV%2BN%2FwS%2FqYpykpkb9clgPcxcCTeGuDZ56yRw3M%3B3gLCycLHHXJ9%2BdAtJ%2BhdrjF4T3DZE%2BoSuug3tmpvI0DgArXOqSfIAeEEuafgzB6LdnHYk6qYHmBaTH%2FGPAevaAu%2Fr%2F5qvAuRrP8SaMXEeFdxDbmScJ%2Bq%2Bp7KZLm414bBKr5RwgdVmt53CM0n3XPsvgPtBvGZrQ%3D%3D; uidal=3113356087927502%e9%87%91%e4%ba%a5%e8%b7%83%e6%b1%9f%e8%81%8a%e9%87%8f%e5%8c%96; sid=155993128; vtpst=|; qgqp_b_id=afa30b2a29cfa4527a0c5d7a241f3923; emshistory=%5B%22%E4%BA%BA%E5%91%98%E7%BB%84%E5%90%88%22%2C%22%E5%88%9B%E4%B8%9A%E6%9D%BF%E6%8C%87%22%5D; websitepoptg_api_time=1783509762928; st_si=78864800140191; fullscreengg=1; fullscreengg2=1; st_asi=delete; st_pvi=76568201336250; st_sp=2021-11-07%2009%3A48%3A02; st_inirUrl=http%3A%2F%2Fquote.eastmoney.com%2Fsh603233.html; st_sn=27; st_psi=20260709193704892-111000300841-8316770403";HEADERS = { "User-Agent": ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/120.0.0.0 Safari/537.36" ), "Referer": "https://quote.eastmoney.com/", "Cookie": COOKIE,}# fields2 字段映射: f51~f61FIELDS2_MAP = { "f51": "日期", "f52": "开盘", "f53": "收盘", "f54": "最高", "f55": "最低", "f56": "成交量", "f57": "成交额", "f58": "振幅(%)", "f59": "涨跌幅(%)", "f60": "涨跌额", "f61": "换手率(%)",}# 常用 secid 示例SECID_EXAMPLES = { "上证指数": "1.000001", "深证成指": "0.399001", "创业板指": "0.399006", "贵州茅台": "1.600519", "中国平安": "1.601318", "比亚迪": "0.002594", "宁德时代": "0.300750", "腾讯控股(HK)": "116.00700",}# ==================== 数据获取 ====================def fetch_kline_data( secid: str, klt: int = 101, lmt: int = 120, end: str = "20500101", fqt: int = 1,) -> dict: """ 从东方财富接口获取K线数据。 Args: secid: 股票代码,格式为 "市场.代码"(如 1.000001 表示上证指数) klt: K线类型,101=日K, 102=周K, 103=月K, 5=5分钟, 15=15分钟, 30=30分钟, 60=60分钟 lmt: 返回数据条数 end: 结束日期,格式 YYYYMMDD fqt: 复权类型,0=不复权, 1=前复权, 2=后复权 Returns: dict: 接口返回的JSON数据 """ params = { "secid": secid, "ut": "fa5fd1943c7b386f172d6893dbfba10b", "fields1": "f1,f2,f3,f4,f5,f6", "fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61", "klt": str(klt), "fqt": str(fqt), "end": end, "lmt": str(lmt), "_": str(int(time.time() * 1000)), } try: resp = requests.get(EASTMONEY_API, params=params, headers=HEADERS, timeout=15) resp.raise_for_status() data = resp.json() return data except requests.exceptions.JSONDecodeError: # 某些情况下返回 JSONP,用正则提取 text = resp.text match = re.search(r"\((\{.*\})\)", text) if match: return json.loads(match.group(1)) raise ValueError("无法解析接口返回数据") except Exception as e: raise RuntimeError(f"请求接口失败: {e}")def parse_kline_to_df(data: dict) -> pd.DataFrame: """ 将接口返回的K线数据解析为 DataFrame。 Args: data: fetch_kline_data 返回的 dict Returns: pd.DataFrame: 包含日期、开盘、收盘、最高、最低等列的 DataFrame """ klines = data.get("data", {}).get("klines", []) if not klines: return pd.DataFrame() rows = [] for line in klines: parts = line.split(",") if len(parts) >= 11: rows.append({ "日期": parts[0], "开盘": float(parts[1]), "收盘": float(parts[2]), "最高": float(parts[3]), "最低": float(parts[4]), "成交量": int(float(parts[5])), "成交额": float(parts[6]), "振幅(%)": float(parts[7]), "涨跌幅(%)": float(parts[8]), "涨跌额": float(parts[9]), "换手率(%)": float(parts[10]), }) df = pd.DataFrame(rows) df["日期"] = pd.to_datetime(df["日期"]) df = df.sort_values("日期").reset_index(drop=True) return df# ==================== 可视化 ====================def render_candlestick_chart(df: pd.DataFrame, stock_name: str = ""): """ 使用 Plotly 渲染K线图 + 成交量副图。 Args: df: K线数据 DataFrame stock_name: 股票名称(用于标题) """ # 中国股市惯例:涨红跌绿 colors_up = "#E63946" # 红色 - 涨 colors_down = "#2A9D8F" # 绿色 - 跌 # 根据涨跌设置K线颜色 df_plot = df.copy() df_plot["颜色"] = df_plot["收盘"] >= df_plot["开盘"] # 涨用红色,跌用绿色 df_plot["颜色"] = df_plot["颜色"].map({True: colors_up, False: colors_down}) fig = make_subplots( rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.08, row_heights=[0.75, 0.25], subplot_titles=("K线图", "成交量"), ) # --- K线图 --- fig.add_trace( go.Candlestick( x=df_plot["日期"], open=df_plot["开盘"], high=df_plot["最高"], low=df_plot["最低"], close=df_plot["收盘"], name="K线", increasing_line_color=colors_up, decreasing_line_color=colors_down, increasing_fillcolor=colors_up, decreasing_fillcolor=colors_down, ), row=1, col=1, ) # --- 成交量柱状图 --- vol_colors = df_plot["收盘"] >= df_plot["开盘"] vol_colors = vol_colors.map({True: colors_up, False: colors_down}) fig.add_trace( go.Bar( x=df_plot["日期"], y=df_plot["成交量"], name="成交量", marker_color=vol_colors, showlegend=False, ), row=2, col=1, ) # 布局配置 title = f"{stock_name} 日K线图" if stock_name else "日K线图" fig.update_layout( title=dict(text=title, x=0.5, font=dict(size=18)), xaxis_rangeslider_visible=False, template="plotly_white", height=600, margin=dict(l=50, r=50, t=60, b=40), legend=dict(orientation="h", yanchor="bottom", y=1.02), ) fig.update_yaxes(title_text="价格", row=1, col=1) fig.update_yaxes(title_text="成交量", row=2, col=1) st.plotly_chart(fig, use_container_width=True)def render_line_chart(df: pd.DataFrame): """渲染收盘价折线图。""" fig = go.Figure() fig.add_trace( go.Scatter( x=df["日期"], y=df["收盘"], mode="lines+markers", name="收盘价", line=dict(color="#1d6fdb", width=2), marker=dict(size=4), ) ) fig.update_layout( title=dict(text="收盘价走势", x=0.5, font=dict(size=18)), xaxis_title="日期", yaxis_title="价格", template="plotly_white", height=400, margin=dict(l=50, r=50, t=60, b=40), ) st.plotly_chart(fig, use_container_width=True)# ==================== Streamlit 页面 ====================def main(): st.set_page_config( page_title="金亥跃江_股票日K数据查询", page_icon="📈", layout="wide", ) st.title("📈 金亥跃江_股票日K数据查询") st.markdown("---") # --- 侧边栏:参数设置 --- with st.sidebar: st.header("🔧 参数设置") # secid 输入 secid_input = st.text_input( "请输入 secid", value="1.000001", help="格式:市场.代码(1=沪市, 0=深市, 116=港股),如 1.000001 表示上证指数", ) # 快捷选择 st.markdown("**快捷选择:**") selected = st.selectbox( "常用股票/指数", options=[""] + list(SECID_EXAMPLES.keys()), index=0, label_visibility="collapsed", ) if selected: secid_input = SECID_EXAMPLES[selected] # K线类型 klt_options = { 101: "日K", 102: "周K", 103: "月K", 5: "5分钟K", 15: "15分钟K", 30: "30分钟K", 60: "60分钟K", } klt = st.selectbox("K线类型", options=list(klt_options.keys()), format_func=lambda x: klt_options[x], index=0) # 数据条数 lmt = st.slider("数据条数", min_value=30, max_value=500, value=120, step=10) # 复权类型 fqt_options = {0: "不复权", 1: "前复权", 2: "后复权"} fqt = st.selectbox("复权类型", options=list(fqt_options.keys()), format_func=lambda x: fqt_options[x], index=1) st.markdown("---") fetch_btn = st.button("🔍 查询数据", type="primary", use_container_width=True) # --- 主区域 --- if fetch_btn or secid_input: if not secid_input.strip(): st.warning("请输入 secid") return with st.spinner("正在获取数据..."): try: raw_data = fetch_kline_data(secid_input.strip(), klt=klt, lmt=lmt, fqt=fqt) df = parse_kline_to_df(raw_data) except Exception as e: st.error(f"获取数据失败:{e}") return if df.empty: st.warning("未获取到数据,请检查 secid 是否正确。") return # 获取股票名称 stock_name = raw_data.get("data", {}).get("name", "") code = raw_data.get("data", {}).get("code", "") market = raw_data.get("data", {}).get("market", "") # --- 数据概览 --- col1, col2, col3, col4 = st.columns(4) latest = df.iloc[-1] first = df.iloc[0] total_change = ((latest["收盘"] - first["收盘"]) / first["收盘"] * 100) if first["收盘"] != 0 else 0 col1.metric("股票名称", stock_name or "未知") col2.metric("数据条数", f"{len(df)} 条") col3.metric("最新收盘价", f"{latest['收盘']:.2f}", delta=f"{latest['涨跌幅(%)']:.2f}%") col4.metric("区间涨跌幅", f"{total_change:.2f}%", delta=f"{total_change:+.2f}%") st.markdown("---") # --- Tab 切换 --- tab_chart, tab_line, tab_table, tab_raw = st.tabs( ["📊 K线图", "📈 收盘价走势", "📋 数据表格", "🔍 原始数据"] ) with tab_chart: render_candlestick_chart(df, stock_name) with tab_line: render_line_chart(df) with tab_table: # 反转显示(最新在前) df_display = df.iloc[::-1].copy() df_display["日期"] = df_display["日期"].dt.strftime("%Y-%m-%d") st.dataframe( df_display, use_container_width=True, height=500, column_config={ "成交量": st.column_config.NumberColumn(format="%d"), "成交额": st.column_config.NumberColumn(format="%.2f"), }, ) # 下载按钮 csv = df_display.to_csv(index=False).encode("utf-8-sig") st.download_button( label="📥 下载 CSV", data=csv, file_name=f"{stock_name or secid_input}_{klt_options[klt]}.csv", mime="text/csv", ) with tab_raw: st.json(raw_data) else: st.info("请在左侧输入 secid 并点击「查询数据」按钮。") # 使用说明 with st.expander("📖 使用说明"): st.markdown(""" ### secid 格式说明 secid 由 **市场代码** 和 **股票代码** 组成,用 `.` 分隔: | 市场 | 市场代码 | 示例 | 说明 | |------|---------|------|------| | 沪市 | 1 | 1.600519 | 贵州茅台 | | 深市 | 0 | 0.000001 | 平安银行 | | 创业板 | 0 | 0.300750 | 宁德时代 | | 港股 | 116 | 116.00700 | 腾讯控股 | | 指数-沪 | 1 | 1.000001 | 上证指数 | | 指数-深 | 0 | 0.399001 | 深证成指 | ### 功能说明 - **K线图**:展示日K蜡烛图 + 成交量副图(涨红跌绿,符合中国股市惯例) - **收盘价走势**:折线图展示收盘价变化趋势 - **数据表格**:可排序、筛选的表格,支持 CSV 下载 - **原始数据**:查看接口返回的 JSON 原始数据 """)if __name__ == "__main__": main()Google 浏览器会自动打开
免责声明:本文仅供技术交流,不构成任何投资建议。股市有风险,投资需谨慎。
如果你觉得这篇文章说到了心坎里,请点个“在看” 和推荐 ,点个关注,并转发给身边的朋友,让更多人支持小亥!