调用Yahoo Finance接口随机触发JSONDecodeError问题排查
问题:通过ISIN获取股票代码的函数随机触发JSON解析错误
我实现了一个通过ISIN获取股票代码的函数,输入苹果ISIN「US0378331005」有时能正常返回「AAPL」,但多数时候会触发如下JSON解析错误,成功或报错完全随机,怀疑问题出在请求头但无法确定。
错误信息
raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
完整代码
import requests def get_symbol_for_isin(isin): url = 'https://query1.finance.yahoo.com/v1/finance/search' headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36', } params = dict( q=isin, quotesCount=1, newsCount=0, listsCount=0, quotesQueryId='tss_match_phrase_query' ) resp = requests.get(url=url, headers=headers, params=params) data = resp.json() if 'quotes' in data and len(data['quotes']) > 0: return data['quotes'][0]['symbol'] else: return None apple_isin = 'US0378331005' print(get_symbol_for_isin(apple_isin))
问题原因及解决办法
核心原因
Yahoo Finance的非公开API会对不符合验证规则的请求返回空响应或验证码页面,导致resp.json()解析失败;随机成功是因为部分请求恰好通过了服务器的临时验证。修复方案
- 补充更完整的请求头,模拟真实浏览器行为
- 添加重试机制,遇到错误时自动重试请求
- 先校验响应状态码,再尝试解析JSON
修改后的代码
import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry def get_symbol_for_isin(isin): url = 'https://query1.finance.yahoo.com/v1/finance/search' # 完善请求头,提升请求合法性 headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'en-US,en;q=0.9', 'Referer': 'https://finance.yahoo.com/' } params = dict( q=isin, quotesCount=1, newsCount=0, listsCount=0, quotesQueryId='tss_match_phrase_query' ) # 配置重试策略:针对限流、服务器错误自动重试 session = requests.Session() retry = Retry( total=3, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504] ) adapter = HTTPAdapter(max_retries=retry) session.mount('https://', adapter) try: resp = session.get(url=url, headers=headers, params=params, timeout=10) resp.raise_for_status() # 主动抛出HTTP状态码错误 data = resp.json() if 'quotes' in data and len(data['quotes']) > 0: return data['quotes'][0]['symbol'] return None except (requests.exceptions.RequestException, ValueError) as e: print(f"请求或解析失败: {str(e)}") return None apple_isin = 'US0378331005' print(get_symbol_for_isin(apple_isin))
- 额外提示
- Yahoo Finance的非公开API无官方支持,随时可能变更接口规则,长期使用建议切换到公开合规的金融数据API
- 避免高频连续请求,防止IP被临时封禁
内容的提问来源于stack exchange,提问作者k.dkh
相关产品推荐
相关产品推荐

