Python爬取NSE期权数据随机报JSONDecodeError问题排查
问题根因
报错的核心原因是NSE官网有反爬校验机制:
- 原代码第一次请求直接打在API接口上,无法拿到服务端颁发的合法会话cookie,会被随机拦截返回
Resource not found的HTML错误页,而不是预期的JSON格式数据,直接调用.json()就会触发解析报错。 - 原代码没有做请求结果校验、异常重试逻辑,单次请求被拦截就会直接崩溃。
- 请求头缺少必要的
referer字段,不符合正常浏览器的请求特征,容易被反爬识别。
修复后完整代码
import os import time from importers import * abd = input('Name the stock: ').strip().upper() url = 'https://www.nseindia.com/api/option-chain-equities?symbol='+abd print(url) headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', 'referer': 'https://www.nseindia.com/option-chain', 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8' } session1 = requests.Session() # 先访问官网首页初始化会话,拿到合法cookie session1.get('https://www.nseindia.com', headers=headers, timeout=10) time.sleep(1) max_retry = 3 response = None for i in range(max_retry): try: resp = session1.get(url, headers=headers, timeout=10) # 校验响应状态 if resp.status_code != 200: print(f"第{i+1}次请求失败,状态码:{resp.status_code},1秒后重试") time.sleep(1) continue # 尝试解析JSON response = resp.json() break except Exception as e: print(f"第{i+1}次请求解析失败,错误:{str(e)[:50]},1秒后重试") time.sleep(1) if not response: raise Exception("多次重试后仍无法获取有效数据,请检查网络或股票代码是否正确") rawdata3 = pd.DataFrame(response) rawop3 = pd.DataFrame(rawdata3['filtered']['data']).fillna(0) rawop3.to_csv('StockOC.csv', index=False) results = pd.read_csv('StockOC.csv') print("数据导出成功,已保存为StockOC.csv")
关键修改说明
- 新增会话初始化步骤:请求API前先访问NSE官网首页,拿到服务端合法校验cookie,从根源解决随机被拦截返回404页面的问题
- 补全请求头字段:补充
referer、accept等浏览器常规请求头,模拟真实用户访问行为,降低被反爬识别的概率 - 自动格式化输入参数:将用户输入的股票代码自动去除首尾空格、转为大写,适配NSE接口的参数格式要求
- 增加重试机制:最多尝试3次请求,每次请求间隔1秒,遇到状态码异常、解析失败时自动重试,避免偶发网络波动、反爬拦截导致脚本崩溃
- 增加异常校验:所有请求成功拿到合法JSON数据后才进入后续数据处理流程,避免直接解析非JSON内容报错
内容的提问来源于stack exchange,提问作者user2293569
相关产品推荐
相关产品推荐

