(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Como extrair tabelas de PDFs em ETL: passo a passo

João Barros 05 de November de 2026 4 min de leitura

Extrair tabelas de PDFs é comum quando fontes de dados chegam em relatórios estáticos. Este tutorial mostra como extrair, limpar e transformar tabelas de PDFs para CSV/Parquet — útil para integrar em pipelines ETL e automatizar a ingestão de relatórios.

Pré-requisitos

  • Python 3.8+ e bibliotecas: tabula-py, pandas, camelot (opcional), pyarrow.
  • Java instalado (necessário para tabula-py).
  • Um PDF com tabelas de exemplo (páginas com tabelas regulares).
  • Editor de código e linha de comandos.

Passo 1: Entender o formato da tabela no PDF

Antes de codificar, abre o PDF e verifica: as tabelas têm linhas bem definidas (grid) ou são tabelas baseadas em alinhamento de texto? Saber isto ajuda a escolher a biblioteca: tabula-py funciona bem para tabelas com grid; camelot também é útil. Anota as páginas e as colunas esperadas.

Passo 2: Instalar dependências

Instala as bibliotecas necessárias e confirma que o Java está acessível. Usamos tabula-py + pandas neste exemplo porque é simples e fiável para muitos PDFs tabulares.

pip install tabula-py pandas pyarrow
# (opcional) pip install camelot-py[cv]
# Certifica-te de que 'java -version' funciona na tua linha de comandos

Passo 3: Extrair tabelas do PDF com tabula-py

Usa tabula-py para extrair todas as tabelas de uma página específica ou de todo o documento. O output inicial será uma lista de DataFrame pandas.

from tabula import read_pdf
import pandas as pd

pdf_path = 'relatorio_exemplo.pdf'
# Extrai todas as tabelas do PDF (pages='all' ou número específico)
tables = read_pdf(pdf_path, pages='all', multiple_tables=True)
print(f'Tabelas extraídas: {len(tables)}')

Passo 4: Inspecionar e limpar cada tabela

Verifica o conteúdo de cada DataFrame: colunas desordenadas, cabeçalhos duplicados, linhas de total. Faz limpeza padrão: normalizar nomes de colunas, remover linhas vazias e converter tipos.

def clean_table(df: pd.DataFrame) -> pd.DataFrame:
    # Remove linhas totalmente vazias
    df = df.dropna(how='all')
    # Promove a primeira linha para cabeçalho se detectar cabeçalho incorreto
    if df.columns.tolist() == list(range(len(df.columns))):
        df.columns = df.iloc[0].astype(str).str.strip()
        df = df[1:]
    # Trim em colunas de texto
    df = df.applymap(lambda x: x.strip() if isinstance(x, str) else x)
    # Exemplo: converter coluna 'Valor' para float
    if 'Valor' in df.columns:
        df['Valor'] = (df['Valor']
                        .astype(str)
                        .str.replace('\u00A0', '')
                        .str.replace(',', '.')
                        .str.replace('[^0-9.\-]', '', regex=True))
        df['Valor'] = pd.to_numeric(df['Valor'], errors='coerce')
    return df.reset_index(drop=True)

cleaned_tables = [clean_table(t) for t in tables]

Passo 5: Conciliar tabelas e padronizar esquema

Se o PDF tem tabelas por página com o mesmo esquema, combina-as. Se os esquemas diferirem, mapeia colunas para um esquema canónico para o ETL.

# Exemplo: juntar tabelas com as mesmas colunas
combined = pd.concat(cleaned_tables, ignore_index=True, sort=False)
# Selecionar e renomear para esquema canónico
canonical_cols = {'Data':'date', 'Descrição':'description', 'Valor':'amount'}
combined = combined.rename(columns=canonical_cols)
combined = combined[['date','description','amount']]

Passo 6: Validar e tratar erros comuns

Erros comuns: tabelas não detetadas, colunas partidas, números com separadores locais. Regista exceções, valida tipos e linhas-chave, e cria fallback (por ex., tentar camelot se tabula falhar).

# Validações simples
if combined.empty:
    raise ValueError('Nenhuma linha válida extraída do PDF')
# Exemplos de checks
if combined['amount'].isna().sum() > 0:
    print('Atenção: valores sem conversão encontrados')

Passo 7: Exportar para CSV ou Parquet para pipeline ETL

Guarda o resultado num formato eficiente para consumo pelas etapas seguintes do ETL: CSV para compatibilidade, Parquet para desempenho em Big Data.

combined.to_csv('relatorio_tabelas.csv', index=False)
combined.to_parquet('relatorio_tabelas.parquet', index=False)

Verificar o resultado

Abre o CSV/Parquet produzido e confirma: número de linhas esperado, colunas corretas, tipos (date, amount). Faz uma amostra e compara com o PDF original para garantir que os valores coincidem. Verifica também os logs de avisos para linhas que falharam na conversão.

Conclusão

Ao extrair tabelas de PDFs em ETL consegues automatizar a ingestão de relatórios e preparar dados para análises. Próximos passos: integrar este script num job agendado, adicionar testes unitários e criar retries/fallback para PDFs problemáticos. Dica: quando uma biblioteca falha numa página, tenta alternar entre tabula-py e camelot para melhores resultados.