Como extrair tabelas de PDFs em ETL: passo a passo
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.