pandas_datareader读取FRED报RemoteDataError无法读取URL故障
问题根因
pandas-datareader 0.10.0版本请求FRED公开接口时,默认请求头未携带合法的浏览器User-Agent标识,触发FRED站点反爬拦截,接口返回空响应,最终抛出RemoteDataError: Unable to read URL报错,和同版本下雅虎财经接口同类报错的触发逻辑完全一致。
修复方案(无需降级pandas、pandas-datareader,保留最新版本)
方案一:运行时打补丁(推荐,无需修改库源码,原有业务代码无需改动)
在原有代码前追加一段动态补丁逻辑,给FRED读取类的请求方法加上合法请求头即可,完整代码如下:
import pandas_datareader import pandas as pd from pandas_datareader.fred import FredReader # 注入请求头补丁 _origin_get_resp = FredReader._get_response def _patched_get_resp(self, url, *args, **kwargs): kwargs.setdefault("headers", {}) kwargs["headers"]["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" return _origin_get_resp(self, url, *args, **kwargs) FredReader._get_response = _patched_get_resp # 原有业务逻辑保持不变 downloader = pandas_datareader.fred df_idx = downloader.FredReader('USD1MTD156N', start='1986-01-02', end='2021-06-30').read()
方案二:直接请求FRED原生接口(绕开pandas-datareader内置请求逻辑,稳定性更高)
如果补丁方式偶发失效,可以直接用requests请求FRED公开的CSV下载接口,再用pandas解析返回内容,逻辑完全可控:
import pandas as pd import requests from io import StringIO def get_fred_series(series_code, start_date, end_date): req_url = f"https://fred.stlouisfed.org/graph/fredgraph.csv?id={series_code}" req_headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" } req_params = { "cosd": start_date, "coed": end_date } resp = requests.get(req_url, headers=req_headers, params=req_params, timeout=30) resp.raise_for_status() # 解析CSV,自动将日期列设为索引 df = pd.read_csv(StringIO(resp.text), parse_dates=["DATE"], index_col="DATE") return df # 调用示例 df_idx = get_fred_series('USD1MTD156N', start_date='1986-01-02', end_date='2021-06-30')
注意事项
- 两种方案均在
pandas 1.4.2、pandas-datareader 0.10.0环境下测试通过,不需要降级任何依赖 - 不要频繁短时间批量请求FRED接口,否则即使携带UA也可能被临时封禁IP
内容的提问来源于stack exchange,提问作者Gilles Criton
相关产品推荐
相关产品推荐

