不能用yfinance批量拉取a股或美股行情,因其不支持国内代码格式且无均线计算逻辑;应使用akshare拉取历史数据并用pandas计算均线,该方案稳定、免费、无需登录、不触发反爬。

直接用 yfinance 批量拉取 A 股或美股行情是行不通的——它不支持国内交易所的代码格式,且无内置日均线计算逻辑;真正能跑通的方案是:用 akshare 拉取历史数据 + pandas 计算均线,全程无需登录、不触发反爬。
为什么不能用 requests + 网页解析批量抓股票行情
主流财经网站(如东方财富、同花顺)对高频请求返回 403 或动态渲染内容,requests 拿不到真实数据;即使加 headers 和 delay,IP 也会在几十次请求后被限流。而 akshare 封装的是交易所直连接口(如上交所/深交所 OpenAPI),返回结构化 CSV/JSON,稳定且免费。
- 网页源码里找不到
kline数据?大概率是前端用WebSocket或fetch异步加载的,静态爬虫无效 - 想用
Selenium?单只股票耗时 >3s,100 只就是 5 分钟起,还容易被识别为自动化行为 -
yfinance的Ticker对 A 股代码(如600519.SH)支持差,常返回空history
用 akshare 获取多只股票日线并合并成 DataFrame
akshare 的 stock_zh_a_hist 函数可按交易日范围批量拉取,返回标准 pandas.DataFrame,列名统一(日期、收盘、成交量 等),省去清洗步骤。
使用 font_manager.addfont() 添加中文字体文件,设置 rcParams['font.family'],并禁用 unicode_minus,使 matplotlib 显示中文。
- 注意参数:
symbol必须用纯数字代码(如"600519"),不是"600519.SH";period固定为"daily";start_date/end_date格式为"20230101" - 避免循环调用:每次
stock_zh_a_hist都是独立 HTTP 请求,10 只股票就发 10 次。应先构造 symbol 列表,再用pd.concat合并 - 实际示例:
import akshare as ak import pandas as pd <p>symbols = ["600519", "000858", "300750"] dfs = [] for s in symbols: df = ak.stock_zh_a_hist(symbol=s, period="daily", start_date="20230101", end_date="20231231") df["symbol"] = s # 补充股票代码列,便于后续分组 dfs.append(df) all_data = pd.concat(dfs, ignore_index=True)</p>
用 pandas rolling 计算 5 日、10 日、20 日均线
均线本质是窗口均值,pandas.Series.rolling(window).mean() 是最直接的方式,比手动写 for 循环快 10 倍以上,且自动对齐日期索引。
- 必须先按
symbol和日期排序:all_data.sort_values(["symbol", "日期"], inplace=True),否则rolling会跨股票计算 - 使用
groupby("symbol")["收盘"].rolling(5).mean(),而不是先set_index("日期")—— 因为不同股票交易日不完全重合,全局时间索引会导致 NaN 泛滥 - 结果列命名要明确:
df["ma5"] = df.groupby("symbol")["收盘"].rolling(5).mean().reset_index(level=0, drop=True),避免索引错位 - 注意:
rolling默认不包含当前行(即“向前看”),但股票均线是包含当日收盘价的,所以无需额外参数,window=5即表示当日+前4日
真正卡住人的地方不是代码怎么写,而是数据对齐——比如某只股票停牌导致某日无记录,rolling 会跳过该位置,但如果你误用了全局时间索引做重采样,均线就会整体偏移。建议始终保留原始 日期 列,不做 resample,只依赖原生交易日序列计算。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










