Código não funciona, ajuda, por favor!

108 views
Skip to first unread message

Andrea Ribeiro Mattos

unread,
Apr 23, 2025, 7:32:17 PMApr 23
to Grupy-SP - Grupo de usuários Python na cidade de São Paulo
não consigo automatizar a busca em um site, podem me ajudar a solucionar o erro?
Esse é o código:
import requests
import pandas as pd
from datetime import datetime, timedelta

# Parâmetros de busca
palavras_chave = ["cartografia", "topografia", "geodésia"]
estado = "BA"
data_inicio = (datetime.today() - timedelta(days=7)).strftime('%Y-%m-%d')
data_fim = datetime.today().strftime('%Y-%m-%d')

URL = "https://pncp.gov.br/api/consulta/v1/contratacoes/consultarPeriodoRecebimentoPropostas"
HEADERS = {"Content-Type": "application/json"}

def buscar_editais_filtrados(estado, palavras_chave, data_inicio, data_fim):
resultados = []
pagina = 1

while True:
print(f"🔍 Página {pagina}...")

payload = {
"uf": estado,
"dataInicioRecebimentoProposta": data_inicio,
"dataFimRecebimentoProposta": data_fim,
"pagina": pagina,
"tamanhoPagina": 100
}

resposta = requests.post(URL, headers=HEADERS, json=payload)

if resposta.status_code != 200:
print(f"⚠️ Erro ao buscar dados: {resposta.status_code}")
break

dados = resposta.json()
registros = dados.get("contratacoes", [])

for edital in registros:
objeto = edital.get("objeto", "").lower()
if any(palavra in objeto for palavra in palavras_chave):
resultados.append({
"Objeto": edital.get("objeto", ""),
"Modalidade": edital.get("modalidade", ""),
"Data Fim Proposta": edital.get("dataFimRecebimentoProposta", ""),
"Órgão": edital.get("orgao", {}).get("nome", ""),
"Município": edital.get("municipio", ""),
"UF": edital.get("uf", ""),
"Link PNCP": edital.get("urlPNCP", "")
})

if dados.get("ultimaPagina", True):
break
pagina += 1

return resultados

# Executa a busca e exibe os resultados filtrados
editais_filtrados = buscar_editais_filtrados(estado, palavras_chave, data_inicio, data_fim)
df = pd.DataFrame(editais_filtrados)

print(f"\n✅ Total de editais encontrados com palavras-chave: {len(df)}")
df.head(10)

Por favor, me ajudem! Angry

Pearson Tech

unread,
Apr 24, 2025, 6:58:26 AMApr 24
to grup...@googlegroups.com
Olá analisei e resolvi criar minha versão para lhe ajudar:

Ai olha o que encontrei:
  • Tratamento da resposta da API: Não há um tratamento específico para verificar a estrutura da resposta antes de processá-la.
  • Formato das datas: O formato de data pode não coincidir com o esperado pela API.
  • Autenticação: A API pode exigir autenticação que não está sendo fornecida.
  • Estrutura de resposta: A verificação dados.get("ultimaPagina", True) assume uma estrutura específica de resposta que pode não corresponder à realidade.
  • Rate limiting: A API pode estar limitando o número de requisições.



    Corrigindo:
  1. Tratamento robusto de erros para requisições e parsing JSON
  2. Sistema de retry para lidar com falhas temporárias
  3. Verificação mais detalhada da estrutura de resposta
  4. Headers de navegador para simular um cliente real
  5. Pausas entre requisições para evitar rate limiting
  6. Análise e salvamento dos resultados em um arquivo Excel
  7. Logging mais detalhado para facilitar a depuração

Para solucionar seu problema específico, é importante verificar:

  1. Se o site permite esse tipo de scraping automatizado
  2. Se o formato correto da API está sendo usado (pode ter mudado)
  3. Se há necessidade de autenticação ou token de acesso
  4. Se você consegue fazer uma requisição manual com sucesso usando ferramentas como Postman

Olhe também se a resposta da API contém a estrutura esperada, como "contratacoes" e "ultimaPagina". A API pode ter mudado ou pode retornar outras informações.






import requests
import pandas as pd
from datetime import datetime, timedelta
import time
import json


# Parâmetros de busca
palavras_chave = ["cartografia", "topografia", "geodésia"]
estado = "BA"
data_inicio = (datetime.today() - timedelta(days=7)).strftime('%Y-%m-%d')
data_fim = datetime.today().strftime('%Y-%m-%d')

URL = "https://pncp.gov.br/api/consulta/v1/contratacoes/consultarPeriodoRecebimentoPropostas"
HEADERS = {
    "Content-Type": "application/json",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}

def buscar_editais_filtrados(estado, palavras_chave, data_inicio, data_fim, max_tentativas=3):

    resultados = []
    pagina = 1
   
    while True:
        print(f"Buscando página {pagina}...")

       
        payload = {
            "uf": estado,
            "dataInicioRecebimentoProposta": data_inicio,
            "dataFimRecebimentoProposta": data_fim,
            "pagina": pagina,
            "tamanhoPagina": 100
        }
       
        # Tentativas com retry em caso de falha
        tentativas = 0
        while tentativas < max_tentativas:
            try:
                resposta = requests.post(URL, headers=HEADERS, json=payload, timeout=30)
               
                # Verificar se a resposta foi bem-sucedida
                if resposta.status_code == 200:
                    break
                else:
                    print(f"Erro na tentativa {tentativas+1}: Status code {resposta.status_code}")
                    if resposta.status_code == 429:  # Too Many Requests
                        wait_time = 10 * (tentativas + 1)
                        print(f"Rate limit atingido. Aguardando {wait_time} segundos...")
                        time.sleep(wait_time)
                    else:
                        time.sleep(2)
            except requests.exceptions.RequestException as e:
                print(f"Erro na requisição (tentativa {tentativas+1}): {e}")
                time.sleep(5)
           
            tentativas += 1
       
        # Se todas as tentativas falharam
        if tentativas == max_tentativas:
            print("Número máximo de tentativas atingido. Encerrando busca.")
            break
           
        # Tentativa de parsing do JSON
        try:
            dados = resposta.json()
        except json.JSONDecodeError:
            print(f"Erro ao decodificar JSON na página {pagina}. Resposta: {resposta.text[:200]}...")
            break
           
        # Verificar se a estrutura esperada está presente
        if "contratacoes" not in dados:
            print(f"Estrutura de dados inesperada na página {pagina}. Chaves disponíveis: {list(dados.keys())}")
            # Exibir uma amostra da resposta para debug
            print(f"Amostra da resposta: {json.dumps(dados)[:300]}...")
            break

           
        registros = dados.get("contratacoes", [])
        print(f"Encontrados {len(registros)} registros na página {pagina}")
       
        if not registros:
            print("Nenhum registro encontrado nesta página.")
            break
           
        # Processar os registros
        for edital in registros:
            objeto = edital.get("objeto", "").lower() if edital.get("objeto") else ""
            if any(palavra.lower() in objeto for palavra in palavras_chave):

                resultados.append({
                    "Objeto": edital.get("objeto", ""),
                    "Modalidade": edital.get("modalidade", ""),
                    "Data Fim Proposta": edital.get("dataFimRecebimentoProposta", ""),
                    "Órgão": edital.get("orgao", {}).get("nome", "") if edital.get("orgao") else "",

                    "Município": edital.get("municipio", ""),
                    "UF": edital.get("uf", ""),
                    "Link PNCP": edital.get("urlPNCP", "")
                })
               
        # Verificar se é a última página
        if dados.get("ultimaPagina") or pagina >= dados.get("totalPaginas", 1):
            print("Última página alcançada.")
            break
           
        pagina += 1
        # Pausa para evitar sobrecarga no servidor
        time.sleep(1)
       
    print(f"Busca finalizada. Total de {len(resultados)} editais correspondentes encontrados.")
    return resultados

# Execução principal
try:
    print(f"Iniciando busca de editais para UF: {estado}")
    print(f"Palavras-chave: {', '.join(palavras_chave)}")
    print(f"Período: {data_inicio} a {data_fim}")

   
    editais_filtrados = buscar_editais_filtrados(estado, palavras_chave, data_inicio, data_fim)
   
    if editais_filtrados:
        # Criação do DataFrame
        df = pd.DataFrame(editais_filtrados)
       
        # Formatação de data se necessário
        if "Data Fim Proposta" in df.columns:
            try:
                df["Data Fim Proposta"] = pd.to_datetime(df["Data Fim Proposta"]).dt.strftime('%d/%m/%Y')
            except:
                print("Não foi possível formatar a coluna de data.")
       
        print(f"\nTotal de editais encontrados com as palavras-chave: {len(df)}")
       
        # Salvar em Excel
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        arquivo_excel = f"editais_pncp_{estado}_{timestamp}.xlsx"
        df.to_excel(arquivo_excel, index=False)
        print(f"Resultados salvos em {arquivo_excel}")
       
        # Exibir as primeiras linhas
        print("\nPrimeiros registros encontrados:")
        print(df.head().to_string())
    else:
        print("Nenhum edital encontrado com os filtros especificados.")
       
except Exception as e:
    print(f"Erro durante a execução: {str(e)}")




--
Você recebeu essa mensagem porque está inscrito no grupo "Grupy-SP - Grupo de usuários Python na cidade de São Paulo" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para grupy-sp+u...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/grupy-sp/b30b28d6-86b1-4aef-9778-1de32b116180n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages