Update app.py
Browse files
app.py
CHANGED
|
@@ -1038,8 +1038,118 @@ def clear_cache():
|
|
| 1038 |
# ============================================
|
| 1039 |
# NOVO ENDPOINT SIMPLIFICADO /busca (com payload exato)
|
| 1040 |
# ============================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1041 |
@app.route('/busca')
|
| 1042 |
def busca_simplificada():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1043 |
"""
|
| 1044 |
Endpoint público para busca simplificada de jurisprudência.
|
| 1045 |
Usa o payload completo do curl (com boosts, aggs, highlight) e retorna apenas os campos essenciais.
|
|
|
|
| 1038 |
# ============================================
|
| 1039 |
# NOVO ENDPOINT SIMPLIFICADO /busca (com payload exato)
|
| 1040 |
# ============================================
|
| 1041 |
+
|
| 1042 |
+
|
| 1043 |
+
# ============================================
|
| 1044 |
+
# Função get_fresh_token modificada (aceita force_refresh)
|
| 1045 |
+
# ============================================
|
| 1046 |
+
def get_fresh_token(force_refresh=False):
|
| 1047 |
+
global token_cache
|
| 1048 |
+
if not force_refresh and token_cache["token"] and time.time() < token_cache["expires_at"]:
|
| 1049 |
+
logger.info("Usando token em cache")
|
| 1050 |
+
return token_cache["token"]
|
| 1051 |
+
|
| 1052 |
+
logger.info("Obtendo novo token via Playwright" + (" (forçado)" if force_refresh else ""))
|
| 1053 |
+
try:
|
| 1054 |
+
with sync_playwright() as p:
|
| 1055 |
+
browser = p.chromium.launch(headless=True, args=['--no-sandbox'])
|
| 1056 |
+
context = browser.new_context(
|
| 1057 |
+
viewport={'width': 1920, 'height': 1080},
|
| 1058 |
+
user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
| 1059 |
+
)
|
| 1060 |
+
page = context.new_page()
|
| 1061 |
+
page.goto("https://jurisprudencia.stf.jus.br/pages/search", wait_until='domcontentloaded', timeout=30000)
|
| 1062 |
+
page.wait_for_timeout(3000)
|
| 1063 |
+
cookies = context.cookies()
|
| 1064 |
+
token = None
|
| 1065 |
+
for cookie in cookies:
|
| 1066 |
+
if cookie.get('name') == 'aws-waf-token':
|
| 1067 |
+
token = cookie.get('value')
|
| 1068 |
+
break
|
| 1069 |
+
browser.close()
|
| 1070 |
+
if token:
|
| 1071 |
+
# Cache por 10 minutos (600 segundos) – ajustável
|
| 1072 |
+
token_cache["token"] = token
|
| 1073 |
+
token_cache["expires_at"] = time.time() + 600
|
| 1074 |
+
logger.info(f"Token obtido: {token[:30]}...")
|
| 1075 |
+
return token
|
| 1076 |
+
else:
|
| 1077 |
+
logger.warning("Token não encontrado nos cookies")
|
| 1078 |
+
return None
|
| 1079 |
+
except Exception as e:
|
| 1080 |
+
logger.error(f"Erro ao obter token: {str(e)}")
|
| 1081 |
+
return None
|
| 1082 |
+
|
| 1083 |
+
# ============================================
|
| 1084 |
+
# Endpoint /busca com tratamento de 202
|
| 1085 |
+
# ============================================
|
| 1086 |
@app.route('/busca')
|
| 1087 |
def busca_simplificada():
|
| 1088 |
+
query = request.args.get('q', '')
|
| 1089 |
+
if not query:
|
| 1090 |
+
return jsonify({"erro": "Parâmetro 'q' é obrigatório"}), 400
|
| 1091 |
+
|
| 1092 |
+
token = get_fresh_token()
|
| 1093 |
+
if not token:
|
| 1094 |
+
return jsonify({"erro": "Não foi possível obter token de acesso"}), 503
|
| 1095 |
+
|
| 1096 |
+
payload = PAYLOAD_BUSCA_BASE.copy()
|
| 1097 |
+
payload_str = json.dumps(payload).replace("__TERMO__", query)
|
| 1098 |
+
payload = json.loads(payload_str)
|
| 1099 |
+
|
| 1100 |
+
headers = HEADERS.copy()
|
| 1101 |
+
headers['Cookie'] = f'aws-waf-token={token}'
|
| 1102 |
+
|
| 1103 |
+
# Tentativa inicial
|
| 1104 |
+
try:
|
| 1105 |
+
response = requests.post(URL_API, headers=headers, json=payload, verify=False, timeout=30)
|
| 1106 |
+
except Exception as e:
|
| 1107 |
+
return jsonify({"erro": f"Falha na comunicação com a API: {str(e)}"}), 502
|
| 1108 |
+
|
| 1109 |
+
# Se recebeu 202 (token expirado), tenta renovar e faz uma segunda tentativa
|
| 1110 |
+
if response.status_code == 202:
|
| 1111 |
+
logger.info("Recebido status 202, forçando renovação do token...")
|
| 1112 |
+
token = get_fresh_token(force_refresh=True)
|
| 1113 |
+
if token:
|
| 1114 |
+
headers['Cookie'] = f'aws-waf-token={token}'
|
| 1115 |
+
try:
|
| 1116 |
+
response = requests.post(URL_API, headers=headers, json=payload, verify=False, timeout=30)
|
| 1117 |
+
except Exception as e:
|
| 1118 |
+
return jsonify({"erro": f"Falha na comunicação com a API após renovação: {str(e)}"}), 502
|
| 1119 |
+
else:
|
| 1120 |
+
return jsonify({"erro": "Não foi possível renovar o token"}), 503
|
| 1121 |
+
|
| 1122 |
+
if response.status_code != 200:
|
| 1123 |
+
return jsonify({"erro": f"API retornou status {response.status_code}"}), response.status_code
|
| 1124 |
+
|
| 1125 |
+
data = response.json()
|
| 1126 |
+
hits = data.get('result', {}).get('hits', {}).get('hits', [])
|
| 1127 |
+
|
| 1128 |
+
resultados = []
|
| 1129 |
+
for hit in hits:
|
| 1130 |
+
source = hit.get('_source', {})
|
| 1131 |
+
item = {
|
| 1132 |
+
"id": source.get('id') or hit.get('_id'),
|
| 1133 |
+
"titulo": source.get('titulo'),
|
| 1134 |
+
"processo": source.get('processo_codigo_completo'),
|
| 1135 |
+
"relator": source.get('relator_processo_nome'),
|
| 1136 |
+
"orgao": source.get('orgao_julgador'),
|
| 1137 |
+
"data": source.get('julgamento_data'),
|
| 1138 |
+
"ementa": source.get('ementa_texto'),
|
| 1139 |
+
"url_documento": source.get('inteiro_teor_url'),
|
| 1140 |
+
"score": hit.get('_score')
|
| 1141 |
+
}
|
| 1142 |
+
item = {k: v for k, v in item.items() if v is not None}
|
| 1143 |
+
resultados.append(item)
|
| 1144 |
+
|
| 1145 |
+
return jsonify({
|
| 1146 |
+
"q": query,
|
| 1147 |
+
"total": data.get('result', {}).get('hits', {}).get('total', {}).get('value', 0),
|
| 1148 |
+
"resultados": resultados
|
| 1149 |
+
})
|
| 1150 |
+
|
| 1151 |
+
@app.route('/busca1')
|
| 1152 |
+
def busca_simplificada1():
|
| 1153 |
"""
|
| 1154 |
Endpoint público para busca simplificada de jurisprudência.
|
| 1155 |
Usa o payload completo do curl (com boosts, aggs, highlight) e retorna apenas os campos essenciais.
|