调用NSE India API获取OHLC数据时遭遇401状态码错误求助
解决NSE India API 401未授权错误
调用NSE India的历史指数API获取NIFTY 50的OHLC数据时返回401状态码,核心原因是NSE的API需要先通过访问主页获取合法会话Cookie,直接请求接口会被反爬机制拦截。以下是具体修复方案:
关键修复点
- 先通过Session访问NSE主页建立会话,获取必要的Cookie后再发起历史数据请求
- 确保从Excel读取的日期是DD-MM-YYYY格式的字符串,避免传入datetime对象导致格式错误
- 更新User-Agent为较新版本的浏览器标识,降低被反爬识别的概率
修改后的完整代码
import requests import xlwings as xw from datetime import datetime def NseHistoricalData(index_type, from_date, to_date): # 初始化会话 session = requests.Session() # 先访问NSE主页获取会话Cookie headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36', 'Referer': 'https://www.nseindia.com/', 'Accept-Language': 'en-US,en;q=0.9', 'Accept-Encoding': 'gzip, deflate, br' } session.get('https://www.nseindia.com/', headers=headers) # 构造历史数据请求URL url = f"https://www.nseindia.com/api/historical/indicesHistory?indexType={index_type}&from={from_date}&to={to_date}" try: response_session = session.get(url, headers=headers) if response_session.status_code == 200: data = response_session.json()['data']['indexCloseOnlineRecords'] if data: # 提取OHLC数据 eod_open = data[0]['EOD_OPEN_INDEX_VAL'] eod_high = data[0]['EOD_HIGH_INDEX_VAL'] eod_close = data[0]['EOD_CLOSE_INDEX_VAL'] eod_low = data[0]['EOD_LOW_INDEX_VAL'] # 写入Excel文件 file_path = r"C:\Users\vhind\Desktop\a\Zerodha\Version_v0\Zerodha\NSE_data.xlsm" wb = xw.Book(file_path) sheet = wb.sheets["Main"] sheet.range('M8').value = eod_open sheet.range('M9').value = eod_high sheet.range('M10').value = eod_close sheet.range('M11').value = eod_low wb.save(file_path) print("历史数据已成功写入Excel表格。") else: print("指定日期范围内无数据,请检查是否为交易日。") else: print(f"数据请求失败,状态码: {response_session.status_code}") except Exception as e: print(f"发生错误: {str(e)}") # 读取并处理Excel中的日期 file_path = r"C:\Users\vhind\Desktop\a\Zerodha\Version_v0\Zerodha\NSE_data.xlsm" wb = xw.Book(file_path) sheet = wb.sheets["Main"] # 转换日期为DD-MM-YYYY格式字符串 from_date_raw = sheet.range('C15').value from_date = from_date_raw.strftime('%d-%m-%Y') if isinstance(from_date_raw, datetime) else str(from_date_raw) to_date_raw = sheet.range('C16').value to_date = to_date_raw.strftime('%d-%m-%Y') if isinstance(to_date_raw, datetime) else str(to_date_raw) index_type = "NIFTY%2050" NseHistoricalData(index_type, from_date, to_date)
额外说明
- NSE的反爬机制会定期更新,若后续再次出现401错误,可尝试更新User-Agent为当前浏览器的最新标识
- 请求的日期必须是NSE的交易日,非交易日API会返回空数据
内容的提问来源于stack exchange,提问作者drk
相关产品推荐
相关产品推荐

