Para extrair tabelas de balanços patrimoniais em PDF com Python e IA, separe leitura, interpretação e validação. Primeiro identifique se cada página contém texto utilizável ou apenas imagem. Depois preserve linhas, colunas, períodos e escala monetária. Use a IA para propor a estrutura quando o leiaute exigir interpretação, e só aprove valores após conferência com a evidência original.
O resultado precisa ser uma tabela rastreável, não apenas um JSON válido. Um balanço pode fechar aritmeticamente e ainda conter a empresa errada, uma coluna trocada ou valores multiplicados pela escala incorreta. A proposta abaixo é uma arquitetura de implementação e um exemplo de normalização; não substitui revisão contábil nem promete eliminar erros.
Resumo rápido
- Classifique páginas individualmente: um PDF pode misturar texto e digitalizações.
- Guarde valor original, valor normalizado, unidade, período e localização da célula.
- Use Decimal para números decimais e rejeite formatos ambíguos.
- Separe validação estrutural, aritmética e conferência documental.
- Encaminhe incertezas para revisão antes de exportar ou alimentar outro sistema.
1. Escolha a rota de extração pelo documento
Abra uma amostra representativa dos arquivos recebidos. Observe se é possível selecionar texto, se as colunas mantêm alinhamento e se cabeçalhos repetidos confundem a leitura. Não classifique todo o lote pelo primeiro documento: relatórios gerados por sistemas diferentes podem exigir rotas distintas, mesmo quando exibem o mesmo título.
O pdfplumber oferece extração de texto e tabelas e informa funcionar melhor com PDFs gerados digitalmente. A biblioteca não deve ser apresentada como um motor de OCR. OCR é o reconhecimento de caracteres em imagens; já um extrator de texto aproveita caracteres que existem no arquivo.
| Entrada observada | Rota inicial | O que conferir |
|---|---|---|
| Texto selecionável e colunas regulares | Extração de texto e tabela | Separação entre notas e saldos |
| Página digitalizada | OCR e reconstrução do leiaute | Sinais, dígitos e posição das colunas |
| Tabela com hierarquia visual difícil | Extração assistida por visão | Correspondência entre célula e evidência |
| Arquivo misto ou incompleto | Roteamento por página e revisão | Continuações e páginas ausentes |
Essa tabela orienta a triagem, sem atribuir notas universais de precisão. Compare as alternativas usando documentos que representem sua operação. Uma solução que lê bem linhas com bordas pode falhar quando o saldo aparece alinhado apenas por espaços.
2. Monte um pipeline que preserve a origem
Na ingestão, atribua um identificador ao documento, registre sua origem e calcule um hash do arquivo. O hash ajuda a verificar se os bytes mudaram; isoladamente, não comprova autoria, autenticidade ou cadeia de custódia. Preserve também a versão recebida, a data de processamento e o responsável pela liberação do uso.
Na triagem, procure títulos e cabeçalhos, mas não dependa exclusivamente deles. Uma página sem texto extraível pode conter o balanço inteiro. A documentação de OCR do PyMuPDF descreve integração com Tesseract e avaliação da necessidade de reconhecimento. Essa etapa precisa ser implementada explicitamente; abrir o PDF não executa OCR automaticamente.
Na extração, capture todas as páginas selecionadas e suas continuações. Guarde a ordem das linhas e não elimine cabeçalhos antes de identificar a qual coluna pertencem. Se uma tabela começa em uma página e termina na seguinte, reconstrua o conjunto antes de conferir subtotais. Remova repetições somente com uma regra verificável.
Na interpretação, peça à IA uma proposta de mapeamento das contas. O documento deve ser tratado como dado, inclusive quando contiver texto que pareça uma instrução para o modelo. A resposta deve permitir valores ausentes e registrar dúvidas. Não peça que o modelo complete saldos para fazer a demonstração fechar.
Na aprovação, apresente ao revisor o recorte da página ao lado dos campos extraídos. Registre correções separadamente, preservando o que a máquina produziu. Esse histórico ajuda a descobrir se a falha está no reconhecimento, no agrupamento das colunas ou na regra de conversão. O guia de extração e validação de documentos financeiros em Python complementa essa organização.
3. Defina um esquema antes de converter números
Uma linha de saída deve identificar documento, página, descrição original, conta normalizada, período, escopo da demonstração, unidade, valor bruto e valor convertido. Escopo distingue, por exemplo, informações individuais e consolidadas. A unidade distingue reais, milhares de reais e outras escalas declaradas pelo documento. Mantenha a referência de nota explicativa em um campo próprio.
Defina uma chave composta que impeça duplicidades sem colapsar informações distintas. A mesma conta pode aparecer em períodos diferentes; o mesmo período pode aparecer em escopos diferentes. Um identificador criado apenas a partir da descrição da conta costuma ser insuficiente para representar essas combinações.
O Pydantic permite validadores de campos e de modelos. Use-os para impor o contrato da aplicação, como exigir unidade reconhecida ou impedir datas ausentes na etapa de aprovação. A validação estrutural não confirma que a célula foi lida corretamente. Além disso, modos de conversão permissiva podem aceitar entradas que sua política deveria rejeitar.
Para a camada de IA, prefira distinguir transcrição e classificação: primeiro a representação fiel do que está escrito; depois a associação ao plano de contas escolhido. Registre a versão desse plano, pois mudanças de classificação alteram comparações históricas. O material sobre saídas estruturadas ajuda a separar formato de resposta e qualidade da informação.
4. Normalize com Decimal e valide sem esconder falhas
O trecho abaixo implementa apenas a conversão de números em uma convenção brasileira previamente confirmada. Ele não extrai PDFs nem detecta automaticamente a localidade. A biblioteca decimal do Python oferece aritmética decimal; construir Decimal a partir de texto evita introduzir a representação binária de um float no caminho.
from decimal import Decimal
import re
FORMATO = re.compile(r"(?:d{1,3}(?:.d{3})+|d+)(?:,d+)?")
def numero_br(texto: str) -> Decimal | None:
s = texto.strip()
if s in {"", "-", "–"}:
return None # significado depende da convenção do documento
parenteses = s.startswith("(") and s.endswith(")")
if parenteses:
s = s[1:-1].strip()
sinal = s.startswith("-")
if sinal:
s = s[1:]
if parenteses and sinal:
raise ValueError("Sinal duplicado")
if not FORMATO.fullmatch(s):
raise ValueError("Formato não reconhecido: revisar a célula")
valor = Decimal(s.replace(".", "").replace(",", "."))
return -valor if parenteses or sinal else valor
assert numero_br("(14.250)") == Decimal("-14250")
assert numero_br("-1.234,56") == Decimal("-1234.56")
assert numero_br("0") == Decimal("0")
assert numero_br("-") is None
O parser rejeita símbolos monetários, sinais duplicados e formatos inesperados em vez de apagar caracteres indiscriminadamente. Essa restrição é intencional. Se o documento usar outra convenção, crie uma regra explícita e testes próprios. Um texto como “ilegível” precisa interromper a conversão; retornar zero silenciosamente transforma uma falha técnica em informação financeira falsa.
Após converter, aplique a escala documentada em uma etapa separada e registre o fator utilizado. Um valor exibido como 14.250 em uma demonstração marcada em milhares não deve ser confundido com 14,25. Preserve também a forma impressa para que o revisor consiga reconstruir a decisão.
Nas conferências, separe obrigações de patrimônio líquido. Evite um campo chamado “passivo total” sem definição, pois diferentes apresentações podem induzir interpretações distintas. Compare ativo com obrigações somadas ao patrimônio líquido e confira os subtotais compatíveis com a estrutura extraída. Uma divergência deve gerar pendência, nunca redistribuição automática de valores.
Defina tolerância conforme a precisão apresentada e a quantidade de parcelas arredondadas. Documente a regra e mostre a diferença observada. Não adote uma tolerância fixa de um real para documentos com escalas diferentes. Também não conclua que um fechamento aritmético certifica a demonstração: duas colunas trocadas podem manter várias somas coerentes.
Exemplo: escritório contábil em Belo Horizonte
Considere um cenário ilustrativo, sem resultados medidos: um escritório de Belo Horizonte recebe balanços de fornecedores industriais para organizar uma análise documental. Parte chega como PDF digital e parte como imagem. O objetivo inicial é montar uma planilha revisável, sem emitir avaliação automática sobre a situação financeira das empresas.
A equipe separa documentos por leiaute e monta uma amostra conferida manualmente. Em um arquivo fictício, a página principal apresenta valores em milhares e duas colunas de exercícios; a continuação repete apenas os títulos abreviados. O pipeline conserva o vínculo entre as páginas e solicita confirmação quando não consegue associar uma coluna ao período.
Uma célula com traço permanece ausente até o revisor confirmar sua interpretação. Outra apresenta um número entre parênteses, preservado como negativo. Se o total não fechar, a interface mostra as linhas envolvidas e o recorte original. A discrepância não prova fraude nem revela sua causa: pode decorrer de leitura, arredondamento, classificação ou do próprio documento.
Antes de ampliar o uso, o escritório mede acerto por célula, associação correta de períodos, proporção de casos encaminhados para revisão e erros que passaram sem alerta. Avalia separadamente arquivos digitais e digitalizados. Assim identifica onde automatizar e onde manter leitura humana, sem anunciar ganhos de tempo que ainda não foram observados.
Erros comuns
- Tratar ausência como zero: preserve a diferença entre saldo explicitamente nulo, traço convencional e conteúdo não reconhecido.
- Processar somente a primeira página: confira continuações e notas necessárias para interpretar a tabela.
- Somar contas duplicadas: não adicione um subtotal e suas contas filhas na mesma soma.
- Confiar na confiança declarada pelo modelo: use evidências observáveis e avaliação com referência humana.
- Prometer sigilo porque tudo roda em memória: chamadas externas, logs, backups e permissões continuam relevantes.
Imponha limites de tamanho, tempo e quantidade de páginas para processar arquivos não confiáveis. Separe ambientes e restrinja a saída de rede quando não for necessária. Revise quais campos podem aparecer nos logs e qual prazo de retenção atende à operação. Antes de enviar documentos a um serviço externo, confirme autorização e condições contratuais aplicáveis.
Na exportação para planilhas, trate descrições como texto e impeça interpretação involuntária como fórmulas. Não use os campos extraídos diretamente em SQL ou comandos do sistema. Mesmo um documento visualmente inocente pode transportar conteúdo inesperado para a próxima etapa da automação.
Perguntas frequentes
É obrigatório usar IA para todo balanço?
Não. Documentos regulares podem ser resolvidos por extração de texto e regras. Use IA quando ela trouxer benefício demonstrado na amostra, mantendo o mesmo contrato de saída e as mesmas verificações.
Um JSON válido significa que os valores estão certos?
Não. Ele confirma apenas parte do formato esperado. A origem da célula, o período, a escala e a correspondência com o documento precisam de controles próprios.
Como lidar com números ilegíveis?
Registre a impossibilidade de leitura e encaminhe para revisão. Repetir a consulta ao modelo pode ajudar em casos específicos, mas não autoriza preencher um valor sem evidência.
Posso adaptar o fluxo para DRE?
Sim, com outro esquema e regras compatíveis com a demonstração. Não reutilize automaticamente a equação patrimonial para validar receitas, despesas e resultados.
Quando liberar a planilha final?
Quando todos os campos obrigatórios tiverem origem identificada, as pendências estiverem resolvidas e a revisão prevista pela organização estiver registrada. Preserve o arquivo original e a versão aprovada dos dados.