如何使用Python的pandas与yfinance批量提取CSV中股票代码对应股价
可行性结论
这个需求完全可实现。145家上市公司的股价批量拉取属于yfinance的常规使用场景,正常情况下全量拉取耗时不会超过2分钟,连续尝试失败基本都是踩了环境配置、参数格式、接口限制类的常见坑,和需求本身无关。
高频失败原因先排查
大部分人卡在这里都是犯了几个很低级的错误,先挨个核对:
- 股票代码格式不符合yfinance要求:如果是A股标的,上交所上市的代码后缀要加
.SS,深交所上市的加.SZ,港股标的后缀加.HK,美股标的直接用交易代码即可。很多人CSV里只存了纯数字代码,没交易所后缀,yfinance根本识别不出来,自然返回空值。 - yfinance版本过旧:雅虎财经的接口经常无通知调整,旧版本yfinance会直接报连接错误、权限错误,先执行
pip install yfinance --upgrade升级到最新版本再调试。 - CSV读入环节出问题:用pandas读CSV时如果不指定
dtype=str,纯数字的股票代码会被识别成整数,要么丢失前导0(比如港股00700会被读成700),要么格式错乱;另外代码前后如果带了空格、换行符,请求也会失败。 - 请求频率过高被临时限制:短时间内连续发上百个请求很容易被雅虎的反爬机制临时封IP,不要写裸循环单只串行无间隔请求。
可直接复用的实现方案
不要自己写单只循环拉取的逻辑,直接用yfinance自带的批量下载接口,速度快、触发反爬的概率低。
假设你的CSV文件中存股票代码的列名是ticker,按下面的步骤写代码即可:
- 导入依赖、读入并清洗股票代码列表
import pandas as pd import yfinance as yf import time # 读入代码文件,必须指定dtype=str避免数字格式错乱 ticker_df = pd.read_csv("你的股票代码CSV文件路径.csv", dtype=str) # 清除代码前后的空格、换行符等冗余字符 ticker_df["ticker"] = ticker_df["ticker"].str.strip() ticker_list = ticker_df["ticker"].dropna().unique().tolist() # 先打印核对代码数量,确认是不是145个,避免读入环节丢数据 print(f"有效股票代码数量:{len(ticker_list)}")
- 批量拉取价格数据
# 参数按自己的需求调整:start/end是时间范围,interval是时间粒度 price_df = yf.download( tickers=ticker_list, start="2020-01-01", end="2024-06-01", interval="1d", # 1d=日线,1wk=周线,1mo=月线 group_by="ticker", # 按股票代码分组,方便后续提取单只标的数据 auto_adjust=True, # 自动采用前复权价格 threads=True # 开启多线程加速拉取 ) # 校验拉取结果,找出拉取失败的标的 failed_tickers = [] for tk in ticker_list: if price_df[tk].dropna(how="all").empty: failed_tickers.append(tk) print(f"首次拉取失败标的数量:{len(failed_tickers)},列表:{failed_tickers}")
- 补拉失败标的
# 如果有失败标的,间隔10秒后补拉,避免触发频率限制 if failed_tickers: time.sleep(10) retry_df = yf.download( tickers=failed_tickers, start="2020-01-01", end="2024-06-01", interval="1d", group_by="ticker", auto_adjust=True, threads=False # 补拉时关掉多线程,降低被封概率 ) # 将补拉成功的数据合并到主数据集 for tk in failed_tickers: if not retry_df[tk].dropna(how="all").empty: price_df[tk] = retry_df[tk]
- 导出结果
price_df.to_csv("全量标的股价数据.csv")
注意事项
- 全量拉取前先拿1-2个标的做测试,比如测试拉取贵州茅台数据用
yf.download("600519.SS", start="2024-01-01"),确认能正常返回数据后再跑全量,避免因为代码格式问题白等。 - 如果多次触发IP限制,就把批量拉取的
threads参数设为False,每拉20个标的加3秒延时,145个标的总耗时也不会超过5分钟,稳定性高很多。 - 不要用单只
Ticker.history()接口循环拉取上百个标的,效率低且极易触发反爬。
内容的提问来源于stack exchange,提问作者Catherine Pemblington
相关产品推荐
相关产品推荐

