Spyder定时获取NSE期权链数据异常:重试循环与数据空白排查
NSE期权链定时获取数据异常排查与修复
我用Spyder IDE写Python代码抓取印度国家证券交易所(NSE)的期权链数据:
- 不设置定时器时,代码能正常把数据写入Excel,Variable Explorer里也能看到对应的DataFrame
- 加上1分钟定时获取逻辑后,Excel文件和Variable Explorer全空白;有时候能按1分钟间隔正常获取,有时候会陷入无限"Retrying"循环,搞不懂Variable Explorer空白的原因。
可正常运行的代码(无定时逻辑)
import requests import json import pandas as pd import xlwings as xw import time from datetime import datetime import winsound file = xw.Book("NiftyOptionChainFeed.xlsm") sh1 = file.sheets("Sheet1") def oc(sym): url = "https://www.nseindia.com/api/option-chain-indices?symbol="+sym headers = {"Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en-US,en;q=0.9", "referer": "https://www.nseindia.com/option-chain", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",} response = requests.get(url, headers = headers).text data = json.loads(response) expiry_list = data['records']['expiryDates'] ce = {} pe = {} n = 0 m = 0 for i in data['records']['data']: #if i['expiryDate'] == expiry_date: try: ce[n] = i['CE'] n = n + 1 except: pass try: pe[m] = i['PE'] m = m + 1 except: pass ce_df = pd.DataFrame.from_dict(ce).transpose() ce_df.columns = "CE_" + ce_df.columns pe_df = pd.DataFrame.from_dict(pe).transpose() pe_df.columns = "PE_" + pe_df.columns df = pd.concat([ce_df, pe_df],axis = 1) return expiry_list, df try: data = oc(sym) sh1.range("A1").value = data[1] sh1.range("AO2").options(transpose = True).value = data[0] timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") sh1.range("AQ2").value = timestamp time.sleep(90) except: print("retrying") time.sleep(5)
出现异常的代码(含定时相关逻辑)
import requests import json import pandas as pd import xlwings as xw import time from datetime import datetime import winsound def oc(sym): url = "https://www.nseindia.com/api/option-chain-indices?symbol="+sym headers = {"Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en-US,en;q=0.9", "referer": "https://www.nseindia.com/option-chain", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",} response = requests.get(url, headers = headers).text data = json.loads(response) expiry_list = data['records']['expiryDates'] ce = {} pe = {} n = 0 m = 0 for i in data['records']['data']: #if i['expiryDate'] == expiry_date: try: ce[n] = i['CE'] n = n + 1 except: pass try: pe[m] = i['PE'] m = m + 1 except: pass ce_df = pd.DataFrame.from_dict(ce).transpose() ce_df.columns = "CE_" + ce_df.columns pe_df = pd.DataFrame.from_dict(pe).transpose() pe_df.columns = "PE_" + pe_df.columns df = pd.concat([ce_df, pe_df],axis = 1) file = xw.Book("NiftyOptionChainFeed.xlsm") sh1 = file.sheets("Sheet1") sh1.range("A1").value = df sh1.range("AO2").options(transpose = True).value = expiry_list
问题根源分析
- Excel对象重复绑定:异常代码里每次调用
oc()都会重新打开Excel文件,多次实例化会导致xlwings的对象引用混乱,数据无法正常写入。 - 变量作用域局限:
df、expiry_list都是函数内部的局部变量,函数执行完就被销毁,Spyder的Variable Explorer只能追踪全局变量,所以显示空白。 - 无异常处理机制:定时场景下网络波动更频繁,但异常代码没有错误捕获,请求失败后直接中断流程,没有重试逻辑,要么空白要么无限卡死。
- 定时逻辑缺失:提供的异常代码里没有完整的定时循环(比如
while True),如果是手动添加的逻辑位置错误,会导致执行流程异常。
修复后的完整代码
import requests import json import pandas as pd import xlwings as xw import time from datetime import datetime # 全局初始化Excel,避免重复打开 file = xw.Book("NiftyOptionChainFeed.xlsm") sh1 = file.sheets("Sheet1") def oc(sym): url = f"https://www.nseindia.com/api/option-chain-indices?symbol={sym}" headers = { "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en-US,en;q=0.9", "referer": "https://www.nseindia.com/option-chain", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" } try: # 添加超时,避免无限等待 response = requests.get(url, headers=headers, timeout=10) # 触发HTTP错误(比如403、500) response.raise_for_status() data = json.loads(response.text) except Exception as e: print(f"请求出错: {str(e)}") return None, None expiry_list = data['records']['expiryDates'] ce = {} pe = {} n = 0 m = 0 for i in data['records']['data']: # 只捕获KeyError,避免掩盖其他严重错误 try: ce[n] = i['CE'] n += 1 except KeyError: pass try: pe[m] = i['PE'] m += 1 except KeyError: pass ce_df = pd.DataFrame.from_dict(ce).transpose() ce_df.columns = "CE_" + ce_df.columns pe_df = pd.DataFrame.from_dict(pe).transpose() pe_df.columns = "PE_" + pe_df.columns df = pd.concat([ce_df, pe_df], axis=1) return expiry_list, df # 定时执行主逻辑 if __name__ == "__main__": sym = "NIFTY" # 替换为你需要的标的 while True: expiry_list, df = oc(sym) if df is not None and not df.empty: # 写入Excel sh1.range("A1").value = df sh1.range("AO2").options(transpose=True).value = expiry_list timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") sh1.range("AQ2").value = timestamp print(f"数据更新成功: {timestamp}") else: print("获取数据失败,即将重试") # 间隔1分钟执行一次 time.sleep(60)
关键修复点
- 全局Excel实例:把Excel文件打开放在函数外,避免重复加载导致的资源冲突。
- 变量作用域优化:函数返回数据到全局循环中,Spyder的Variable Explorer能追踪到
expiry_list和df变量。 - 完善异常处理:添加网络请求超时、HTTP错误捕获,明确失败原因,避免静默失败。
- 规范定时循环:用
while True+time.sleep(60)实现稳定的定时任务,确保每次流程完整。 - 精准异常捕获:替换宽泛的
except:为具体的KeyError,避免掩盖其他严重问题。
内容的提问来源于stack exchange,提问作者Mohammad Haneef Ahmad
相关产品推荐
相关产品推荐

