You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Requests调用API遇401 Unauthorized,如何自动重新认证?

解决CEASA API 401未授权自动重认证问题

问题原因

你的请求返回401是因为headers中的JSESSIONID Cookie已过期。这个Cookie是服务器用来标识用户会话的,超时或长时间未活动后会失效,必须重新获取有效会话标识才能继续请求。

解决方案

通过代码自动获取新的会话Cookie,并且在请求失败(401)时自动重试。核心思路是:

  • 先访问CEASA数据平台首页,获取服务器返回的有效JSESSIONID
  • 使用requests.Session()管理会话,自动维护Cookie
  • 当API请求返回401时,重新获取会话并重发请求

完整代码实现

import requests
import json
from bs4 import BeautifulSoup as bs4
import pandas as pd

API_URL = "https://dw.ceasa.gov.br/saiku/rest/saiku/api/query/execute"
HOME_URL = "https://dw.ceasa.gov.br/"

payload = json.dumps({
  "name": "0A777C63-EAF6-181A-9FB1-248AFCE90BE1",
  "queryModel": {
    "axes": {
      "FILTER": {
        "mdx": None,
        "filters": [],
        "sortOrder": None,
        "sortEvaluationLiteral": None,
        "hierarchizeMode": None,
        "location": "FILTER",
        "hierarchies": [],
        "nonEmpty": False,
        "aggregators": []
      },
      "COLUMNS": {
        "mdx": None,
        "filters": [],
        "sortOrder": None,
        "sortEvaluationLiteral": None,
        "hierarchizeMode": None,
        "location": "COLUMNS",
        "hierarchies": [
          {
            "name": "[04-Produto].[04-Produto]",
            "levels": {
              "Produto": {
                "name": "Produto"
              }
            }
          }
        ],
        "nonEmpty": True,
        "aggregators": []
      },
      "ROWS": {
        "mdx": None,
        "filters": [],
        "sortOrder": None,
        "sortEvaluationLiteral": None,
        "hierarchizeMode": None,
        "location": "ROWS",
        "hierarchies": [
          {
            "name": "[06-Ano].[06-Ano]",
            "levels": {
              "Ano": {
                "name": "Ano",
                "aggregators": [],
                "selection": {
                  "type": "EXCLUSION",
                  "members": [
                    {
                      "uniqueName": "[06-Ano].[06-Ano].[2015]",
                      "caption": "2015"
                    },
                    {
                      "uniqueName": "[06-Ano].[06-Ano].[2016]",
                      "caption": "2016"
                    },
                    {
                      "uniqueName": "[06-Ano].[06-Ano].[2017]",
                      "caption": "2017"
                    },
                    {
                      "uniqueName": "[06-Ano].[06-Ano].[2018]",
                      "caption": "2018"
                    },
                    {
                      "uniqueName": "[06-Ano].[06-Ano].[2019]",
                      "caption": "2019"
                    },
                    {
                      "uniqueName": "[06-Ano].[06-Ano].[2020]",
                      "caption": "2020"
                    },
                    {
                      "uniqueName": "[06-Ano].[06-Ano].[2021]",
                      "caption": "2021"
                    },
                    {
                      "uniqueName": "[06-Ano].[06-Ano].[2022]",
                      "caption": "2022"
                    },
                    {
                      "uniqueName": "[06-Ano].[06-Ano].[2023]",
                      "caption": "2023"
                    }
                  ]
                }
              }
            }
          },
          {
            "name": "[07-Mes].[07-Mes]",
            "levels": {
              "Mes": {
                "name": "Mes",
                "aggregators": [],
                "selection": {
                  "type": "EXCLUSION",
                  "members": [
                    {
                      "uniqueName": "[07-Mes].[07-Mes].[1º SEM].[JANEIRO]",
                      "caption": "JANEIRO"
                    },
                    {
                      "uniqueName": "[07-Mes].[07-Mes].[1º SEM].[FEVEREIRO]",
                      "caption": "FEVEREIRO"
                    },
                    {
                      "uniqueName": "[07-Mes].[07-Mes].[1º SEM].[MARÇO]",
                      "caption": "MARÇO"
                    },
                    {
                      "uniqueName": "[07-Mes].[07-Mes].[1º SEM].[ABRIL]",
                      "caption": "ABRIL"
                    },
                    {
                      "uniqueName": "[07-Mes].[07-Mes].[1º SEM].[MAIO]",
                      "caption": "MAIO"
                    },
                    {
                      "uniqueName": "[07-Mes].[07-Mes].[1º SEM].[JUNHO]",
                      "caption": "JUNHO"
                    },
                    {
                      "uniqueName": "[07-Mes].[07-Mes].[2º SEM].[JULHO]",
                      "caption": "JULHO"
                    }
                  ]
                }
              }
            }
          },
          {
            "name": "[08-Dia].[08-Dia]",
            "levels": {
              "Dia Mes": {
                "name": "Dia Mes"
              }
            }
          }
        ],
        "nonEmpty": True,
        "aggregators": []
      }
    },
    "visualTotals": False,
    "visualTotalsPattern": None,
    "lowestLevelsOnly": False,
    "details": {
      "axis": "COLUMNS",
      "location": "BOTTOM",
      "measures": []
    },
    "calculatedMeasures": []
  },
  "queryType": "OLAP",
  "type": "QUERYMODEL",
  "cube": {
    "uniqueName": "[Prohort].[Prohort].[Prohort].[PROHORT - PRECO DIARIO]",
    "name": "PROHORT - PRECO DIARIO",
    "connection": "Prohort",
    "catalog": "Prohort",
    "schema": "Prohort",
    "caption": None,
    "visible": False
  },
  "mdx": None,
  "parameters": {},
  "plugins": {},
  "properties": {
    "saiku.olap.query.automatic_execution": False,
    "saiku.olap.query.nonempty": True,
    "saiku.olap.query.nonempty.rows": True,
    "saiku.olap.query.nonempty.columns": True,
    "saiku.ui.render.mode": "table",
    "saiku.olap.query.filter": True,
    "saiku.olap.result.formatter": "flattened",
    "org.saiku.query.explain": True,
    "org.saiku.connection.scenario": False,
    "saiku.olap.query.drillthrough": True
  },
  "metadata": {}
})

def get_session():
    """创建新会话并获取有效Cookie"""
    session = requests.Session()
    # 访问首页获取JSESSIONID
    session.get(HOME_URL, headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
        'Accept-Language': 'pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7'
    })
    return session

def execute_query(session):
    """执行API请求,返回响应"""
    headers = {
        'Accept': 'application/json, text/javascript, */*; q=0.01',
        'Accept-Language': 'pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7',
        'Connection': 'keep-alive',
        'Content-Type': 'application/json',
        'Origin': 'https://dw.ceasa.gov.br',
        'Referer': 'https://dw.ceasa.gov.br/',
        'Sec-Fetch-Dest': 'empty',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Site': 'same-origin',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
        'X-Requested-With': 'XMLHttpRequest',
        'sec-ch-ua': '"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"'
    }
    response = session.post(API_URL, headers=headers, data=payload)
    return response

# 主逻辑
session = get_session()
response = execute_query(session)

# 如果返回401,重新获取会话并重试
if response.status_code == 401:
    print("会话过期,重新获取会话...")
    session = get_session()
    response = execute_query(session)

print(response.status_code)
# 后续可以处理响应内容,比如解析为DataFrame
# if response.status_code == 200:
#     data = response.json()
#     df = pd.DataFrame(data['resultset'])

代码说明

  • get_session()函数:创建新的requests.Session对象,访问CEASA首页获取服务器颁发的新JSESSIONID,会话会自动保存这个Cookie。
  • execute_query()函数:使用传入的会话执行API请求,无需手动指定Cookie,会话会自动携带。
  • 主逻辑:先尝试请求,若返回401则重新获取会话并重试,确保请求始终使用有效会话。

内容的提问来源于stack exchange,提问作者Ramiro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 13:24:51