Extrair dados de notas fiscais de PDF com Python

Para extrair dados de notas fiscais de um PDF com Python, você lê o texto do arquivo e, em seguida, extrai campos nomeados desse texto. Duas etapas, talvez quarenta linhas de código, e funciona perfeitamente na primeira nota fiscal em que você tenta. Então, o fornecedor número sete move o número da nota fiscal três linhas para cima e seu parser começa a retornar None às duas da manhã.

Essa segunda parte é o verdadeiro assunto deste artigo. A leitura é fácil. O manter-se correto é o verdadeiro trabalho.

Principais conclusões

  • Python extrai o texto de notas fiscais em poucas linhas. Mantê-lo correto em centenas de layouts de fornecedores é o que realmente custa caro a você.
  • Um PDF não é um formato de dados. É uma descrição tipográfica de uma página impressa, e é por isso que uma expressão regular (regex) escrita para o layout de um único fornecedor é algo frágil.
  • Expressões regulares e modelos por fornecedor escalam linearmente com a sua lista de fornecedores. Os modelos de visão não, porque leem a página em vez da string.
  • Qualquer que seja a forma de extração dos dados, o seu próprio código tem que verificar a aritmética. Itens de linha que não somam o subtotal são o detector de bugs mais barato que você já escreveu.
  • A extração raramente é o que faz as pessoas pararem de construir a solução por conta própria. A fila de exceções, a correspondência de fornecedores e a integração contábil sim.

O formato PDF

O formato PDF é versátil, permitindo a representação precisa de documentos em papel, como notas fiscais, sem limitar seu design. Ele vem do mundo da impressão em papel e foi desenhado para ser uma representação digital de uma página impressa. Essa flexibilidade oferece liberdade significativa, permitindo que os criadores de PDF se expressem e sigam vários padrões e regulamentações.

No entanto, o desafio surge quando os dados ficam presos dentro de um PDF. A natureza livre e complexa do formato pode entrar em conflito com a abordagem estruturada e consistente necessária para gerenciar a grande quantidade de dados que uma empresa processa diariamente.

Uma captura de tela das camadas do formato de arquivo PDF
Camadas do formato de arquivo PDF

Um PDF armazena onde cada glifo (caractere) se encontra na página. Ele não armazena o fato de que o número no canto inferior direito é o total. Essa relação existe na sua cabeça, e cada método de extração neste artigo é uma tentativa de codificá-la.

Quais são as etapas para extrair dados de uma nota fiscal?

Uma nota fiscal é um documento que geralmente vem no formato PDF. Uma nota fiscal formaliza uma transação entre um fornecedor e um cliente, onde um produto ou serviço é trocado por uma quantia exata de dinheiro. Aqui estão as etapas necessárias para extrair dados desse documento:

  1. Definir um esquema para os dados que você deseja extrair de suas notas fiscais
  2. Converter sua nota fiscal de imagem para texto
  3. Extrair o texto da sua nota fiscal de acordo com seu esquema de dados
  4. Coletar os dados extraídos

Uma captura de tela do processo de extração de dados da nota fiscal
Processo de extração de dados da nota fiscal

Definir um esquema para seus dados de nota fiscal

As notas fiscais vêm de diferentes fornecedores e cada fornecedor tende a personalizar a aparência de suas notas fiscais. Apesar dessa diversidade real na forma, a substância de todas as notas fiscais é basicamente a mesma: você precisa de um fornecedor, um cliente, um número de referência da nota fiscal, uma data e uma lista de itens com quantidade, descrição e custo associados. Uma ótima maneira de começar a definir o formato da sua nota fiscal seria pelo seu software de contabilidade, já que provavelmente é lá que você vai armazenar os dados extraídos, não é mesmo? Se você quiser um formato de dados que cubra todos os casos possíveis, recomendo o site schema.org, que define uma série de formatos de dados padrão do setor para várias coisas, incluindo notas fiscais. O Parseur define um esquema de dados padrão para suas notas fiscais, mas você pode mudá-lo para atender ao seu caso de uso renomeando os campos na sua caixa de entrada de notas fiscais, conforme explicado aqui. Uma vez definido o formato dos dados, você pode converter sua nota fiscal de imagem para texto.

Por exemplo, você pode definir os seguintes campos para sua nota fiscal usando o formato JSON Swagger:

{
    "InvoiceNumber": {
        "type": "string",
        "description": "The invoice number"
    },
    "InvoiceIssueDate": {
        "type": "string",
        "description": "The invoice date"
    },
    "Items": {
        "type": "array",
        "description": "The list of items in the invoice",
        "items": {
            "type": "object",
            "properties": {
                "quantity": {
                    "type": "number",
                    "description": "The quantity of the item"
                },
                "description": {
                    "type": "string",
                    "description": "The description of the item"
                },
                "unit_price": {
                    "type": "number",
                    "description": "The unit price of the item"
                },
                "price": {
                    "type": "number",
                    "description": "The total price of the item"
                }
            }
        }
    }
}

Anote isso antes de escrever qualquer código de análise (parsing). É o contrato que todo método abaixo deve satisfazer e é o que você entregará a um modelo de visão mais tarde.

Converter sua nota fiscal de imagem para texto

Uma captura de tela de uma nota fiscal tirada de um smartphone
Foto de uma nota fiscal tirada de um smartphone

Um arquivo PDF pode conter uma imagem. Por exemplo, seu colaborador pode tirar uma foto rápida de uma nota fiscal com a câmera do smartphone. Depois, salva como PDF e envia para o departamento contábil. Sua equipe contábil é responsável por extrair os dados desta nota fiscal e de alguma maneira inseri-los no seu sistema contábil sem cometer erros. O próximo passo é converter essa imagem em texto usando um sistema de Reconhecimento Óptico de Caracteres. Um dos sistemas de OCR mais populares é o Tesseract. O Tesseract é escrito em C e C++. Para usá-lo em nosso programa Python, precisamos usar um binding como o PyTesseract. Um binding é uma forma de chamar uma biblioteca de software (aqui, Tesseract) de uma linguagem para a qual ela não foi originalmente escrita (aqui, Python). Existem muitos desses sistemas e seus resultados variam bastante dependendo da tecnologia utilizada e da qualidade do escaneamento do documento trabalhado. O Parseur detecta automaticamente se seu documento é uma imagem e o converte automaticamente em texto, internamente. Assim que os dados estiverem em formato de texto, já podem ser extraídos.

Extrair o texto da sua nota fiscal de acordo com seu esquema de dados

Depois que seu PDF estiver em formato de texto (ou pesquisável), você pode usar a biblioteca Python pdftotext para obter os dados do arquivo PDF como texto. Aqui está um trecho de código para extrair o texto de um arquivo PDF:

import pdftotext

# Carregar sua nota fiscal
with open("invoice.pdf", "rb") as file_handle:
    pdf = pdftotext.PDF(file_handle)

# Iterar sobre todas as páginas
for page in pdf:
    print(page)

Dê o nome convert_pdf_to_text.py para esse script e execute-o, assim você verá a nota fiscal como texto na saída padrão. Se quiser redirecionar a saída para um arquivo, execute:

$ python convert_pdf_to_text.py > invoice.txt

O pdftotext fornece uma string simples, o que é bom para campos de cabeçalho e inútil para tabelas. Quando você precisar dos itens de linha, opte pelo pdfplumber em vez disso, pois ele mantém as coordenadas de cada palavra e pode tentar extrair a tabela em si:

import pdfplumber

with pdfplumber.open("invoice.pdf") as pdf:
    page = pdf.pages[0]

    # Palavras com suas posições na página
    for word in page.extract_words():
        print(word["text"], word["x0"], word["top"])

    # E uma tentativa de extrair a tabela de itens de linha
    table = page.extract_table()
    if table:
        for row in table:
            print(row)

Execute isso em uma nota fiscal real de um fornecedor e você descobrirá com muita frequência que a table é None. Isso não é um bug. É o primeiro sinal honesto de que esse problema é mais difícil do que parece, e voltaremos a isso mais adiante.

Agora que você tem a nota fiscal em formato de texto, pode extrair os dados que deseja dela, usando qualquer combinação das técnicas a seguir:

  • Você pode usar uma expressão regular para extrair os dados desejados. Expressões regulares são uma forma poderosa de extrair dados de texto, mas também são muito frágeis. Se o formato da nota fiscal mudar, será preciso atualizar sua expressão regular. Além disso, expressões regulares não funcionam muito bem para extrair dados de tabelas.
  • Você pode usar um sistema visual de templates, idealmente aproveitando OCR Dinâmico e OCR Zonal. Essa é uma forma mais avançada de extrair dados de texto. É mais robusto do que expressões regulares, mas também mais complexo de implementar.
  • Você pode entregar a página a um modelo de visão com um esquema e deixá-lo ler o documento da mesma forma que uma pessoa lê. Esta é a abordagem que mudou nos últimos dois anos e ganha uma seção própria logo abaixo.

Vamos extrair dados da sua nota fiscal usando o módulo de expressões regulares re do Python. Veja um trecho de código para extrair o número da nota fiscal:

import re

# Carregar sua nota fiscal
with open("invoice.txt", "r") as file_handle:
    invoice = file_handle.read()

# Extrair o número da nota fiscal
invoice_number = re.search(r"Invoice number: (\w+)", invoice).group(1)
print(invoice_number)

Dê o nome extract.py para esse script e execute-o. O número da nota fiscal aparecerá na saída padrão:

$ python extract.py

E você verá algo como:

INV-1234

Por que seu parser de notas fiscais por regex quebra

Um regex corresponde a uma string. Uma nota fiscal é uma imagem. Tudo o que dá errado decorre dessa incompatibilidade e dá errado em um número pequeno de formas previsíveis:

  • O rótulo mudou de lugar. Seu padrão está ancorado a Invoice number: e o novo modelo diz Invoice #, ou coloca o valor na próxima linha em vez da mesma.
  • extract_table retorna None. Extratores de tabelas procuram por linhas de borda visíveis. A maioria das notas fiscais de fornecedores alinha suas colunas com espaços em branco e não desenha borda alguma.
  • O texto sai na ordem errada. Layouts de duas colunas e blocos de endereços flutuantes se entrelaçam quando a página é achatada (flattened) em uma string, de forma que as linhas dos itens de linha chegam embaralhadas.
  • A tabela se estende por páginas. As linhas dois a nove estão na página um, dez a catorze na página dois, com os cabeçalhos das colunas repetidos no meio e uma linha de subtotal fingindo ser um item.
  • Três números parecem ser o total. Subtotal, total, valor devido e saldo anterior. Escolher o maior deles é errado em qualquer nota fiscal que contenha um crédito.
  • A digitalização é uma fotografia. O OCR lê um 8 borrado como um 3 e nada a jusante percebe, porque 3 é um dígito perfeitamente válido.
  • Células mescladas e descrições de várias linhas. A descrição de um produto se estende por três linhas e sua lógica de divisão de linhas a transforma em três itens sem preços.

Nenhum desses problemas pode ser corrigido com uma expressão regular melhor. Todos eles são problemas de layout disfarçados de problemas de string. É neste ponto que a maioria das pessoas começa a escrever um modelo (template) por fornecedor, que cresce para sempre, ou muda de abordagem.

A abordagem de 2026 - um modelo de visão e um esquema

A mudança útil é que você não precisa mais converter a página em texto plano antes de extrair dela. Um modelo de visão olha para a nota fiscal renderizada, de modo que um fornecedor que move seu número de nota fiscal não é mais um evento. O que você fornece não é um padrão, é o esquema que você escreveu no topo deste artigo.

Restrinja a saída para que você obtenha as mesmas chaves todas as vezes. O Pydantic mais um modo de saída estruturada, como os OpenAI's structured outputs, faz isso por você:

from typing import List
from pydantic import BaseModel

class LineItem(BaseModel):
    description: str
    quantity: float
    unit_price: float
    amount: float

class Invoice(BaseModel):
    vendor_name: str
    invoice_number: str
    invoice_date: str      # ISO 8601
    currency: str
    subtotal: float
    tax: float
    total: float
    line_items: List[LineItem]

# Renderizar a página em PDF para uma imagem, enviá-la para um modelo de visão,
# e exigir que a resposta corresponda ao esquema Invoice.
# O modelo preenche os campos. Ele não consegue inventar a forma.

Isso resolve genuinamente a maior parte do problema de extração, e é por isso que essa abordagem se espalhou tão rápido. Ela também introduz um novo modo de falha que a regex nunca teve: uma regex que não consegue encontrar o número da nota fiscal retorna None, enquanto um modelo que não o encontra às vezes escreve um número plausível. A regra que o mantém seguro é simples. O modelo propõe e seu código verifica.

Se você preferir não rodar o modelo por conta própria, a mesma capacidade é vendida como um serviço gerenciado pelos provedores de nuvem, no Azure AI Document Intelligence e no Amazon Textract's AnalyzeExpense, e ambos retornam campos de cabeçalho e itens de linha separadamente. Escrevemos sobre como a abordagem subjacente difere da análise baseada em regras em parsers de PDF baseados em IA versus baseados em regras, e como ela se parece quando aplicada a notas fiscais especificamente no processamento de notas fiscais com IA de visão.

A camada de validação que você mesmo deve escrever

Qualquer que seja a origem do seu JSON, essas verificações pertencem ao seu código, não à pontuação de confiança do extrator. Elas são baratas, determinísticas e detectam os erros que custam dinheiro:

  1. subtotal + imposto + frete - desconto resulta em total, com precisão de um centavo.
  2. Os valores dos itens de linha somam o subtotal. Se não somarem, você deixou cair uma linha ou inventou uma.
  3. Todo quantidade * preço_unitário é igual ao seu próprio valor.
  4. A data é analisada com sucesso e não está no futuro.
  5. O número da nota fiscal ainda não foi pago para aquele fornecedor. Pagamentos duplicados são o bug mais caro no contas a pagar.
  6. O nome do fornecedor é resolvido para um registro no seu cadastro principal de fornecedores.
  7. Os detalhes bancários para pagamento correspondem aos já cadastrados para aquele fornecedor. Uma mudança aqui é uma verificação de fraude, não de dados.
  8. A moeda é uma em que você realmente negocia.
  9. O número do pedido de compra existe, e suas quantidades e preços correspondem, caso você faça a correspondência de duas ou três vias (two-way ou three-way matching).
  10. Todos os campos obrigatórios estão presentes e não vazios.

Qualquer coisa que falhe vai para uma pessoa, não para o sistema contábil:

def validate(invoice):
    errors = []

    if abs(invoice.subtotal + invoice.tax - invoice.total) > 0.01:
        errors.append("totals_do_not_add_up")

    line_sum = sum(item.amount for item in invoice.line_items)
    if invoice.line_items and abs(line_sum - invoice.subtotal) > 0.01:
        errors.append("line_items_do_not_sum_to_subtotal")

    if not invoice.invoice_number:
        errors.append("missing_invoice_number")

    return errors

Dez linhas de aritmética capturarão mais problemas reais do que qualquer quantidade de ajuste de prompts (prompt tuning).

E o invoice2data e as outras bibliotecas?

O invoice2data merece uma menção honesta, porque é o primeiro resultado que muitas pessoas encontram e é um software genuinamente bom. É uma ferramenta de linha de comando e uma biblioteca Python que faz a correspondência de notas fiscais com modelos YAML que você escreve por fornecedor, com as regras de correspondência no controle de versão em vez de enterradas em seu código. Se você tem uma dúzia de fornecedores que nunca mudam seu layout, isso servirá bem por anos.

O limite está no design, não na qualidade. Um modelo por fornecedor significa que sua manutenção cresce com sua lista de fornecedores, e os modelos quebram exatamente pelos motivos listados acima. Em algum lugar entre vinte e trinta layouts ativos, a pessoa que mantém os modelos está fazendo mais trabalho do que a pessoa que costumava redigitar as notas fiscais.

O mesmo raciocínio se aplica à prateleira de bibliotecas mais ampla. O pdfplumber, PyMuPDF, pdftotext e pytesseract são excelentes em seus verdadeiros trabalhos, que é extrair caracteres e coordenadas de uma página. Nenhum deles foi feito para saber qual número é o total. Comparamos o conjunto mais amplo em nosso resumo dos melhores parsers de PDF e das melhores APIs de extração de dados.

Coletar os dados extraídos

Com Python, você pode iterar pelos arquivos de notas fiscais em uma pasta e extrair deles as informações. Vamos supor que extraímos o número da nota fiscal e o valor total, e exibimos o resultado no formato CSV:

import os
import re

import pdftotext

# Iterar sobre todos os arquivos PDF na pasta
for filename in os.listdir("invoices/"):
    if not filename.endswith(".pdf"):
        continue

    # Carregar sua nota fiscal
    with open("invoices/" + filename, "rb") as file_handle:
        pdf = pdftotext.PDF(file_handle)

    # Imprimir o cabeçalho da coluna CSV
    print("InvoiceNumber,TotalAmount")

    # Iterar sobre todas as páginas
    for page in pdf:
        # Extrair o número da nota fiscal
        invoice_number = re.search(r"Invoice number: (\w+)", page).group(1)
        total_amount = re.search(r"Total amount: (\w+)", page).group(1)
        print(invoice_number, total_amount, sep=",")

Dê o nome extract_to_csv.py a esse script e execute-o, assim o número e o valor total da nota fiscal aparecerão na saída padrão, que pode ser redirecionada para um arquivo CSV. Você pode então abrir o arquivo com seu software favorito de planilhas, como Excel:

$ python extract_to_csv.py > invoices.csv

Uma pasta de arquivos CSV é onde a maioria dos scripts de notas fiscais para, e também é onde a contabilidade real começa. Alguém ainda tem que importá-los, corresponder os fornecedores, perseguir as linhas que o sistema contábil rejeitou e descobrir o que fazer com a nota fiscal que falhou na validação às 2 da manhã. Esse trabalho não aparece no seu script e não aparece na sua conta de tokens da API.

Quando parar de construir do zero

Esta é a parte que a maioria dos fornecedores pula, então nós a diremos primeiro. Se você tem um punhado de fornecedores constantes, um engenheiro que pode monitorar um pipeline e ninguém esperando pelos dados, então escreva o script. Um modelo de visão mais um esquema e as dez linhas de validação acima levarão você longe com muito pouco dinheiro, e você entenderá cada parte disso.

A conta por construir a solução por conta própria chega mais tarde, e nunca na etapa de extração. Ela chega nas partes que ninguém prototipa:

  • A fila de exceções. Sua equipe de Contas a Pagar precisa de uma tela onde clicar em um campo o destaque na nota fiscal para que possam consertá-lo em quatro segundos em vez de quarenta. Isso é um produto, não um script.
  • Correspondência de fornecedores. "ACME Ltd", "Acme Limited" e "ACME LTD." são um único fornecedor, e o sistema contábil não aceitará três.
  • Detecção de duplicatas. A mesma nota fiscal chega como um anexo de e-mail na terça-feira e como um PDF de extrato na sexta-feira.
  • A máquina de estados. Filas, tentativas, falhas parciais e saber quais das 300 notas fiscais da noite passada realmente foram processadas com sucesso.
  • A trilha de auditoria. O que foi extraído, o que um humano alterou, quem aprovou e quando. O departamento financeiro vai perguntar, geralmente durante uma auditoria.
  • Tudo depois do JSON. Mapeamento de campos no sistema de contabilidade, codificação de GL (razão geral), correspondência de pedidos de compra e as linhas rejeitadas por ele.

Os sinais claros de que é hora de comprar em vez de construir são estes. Você passou de aproximadamente vinte a trinta layouts de fornecedores ativos. Você precisa de itens de linha, não apenas de campos de cabeçalho. Mais do que um punhado das suas notas fiscais chega como digitalizações (scans). Sua equipe de Contas a Pagar, e não a equipe de engenharia, precisa corrigir os erros. Extrações com falha estão atrasando pagamentos. Ou, o mais comum, a pessoa que mantém o parser parou de entregar qualquer outra coisa.

Como o Parseur lida com isso

O Parseur é um parser de documentos que faz todo o ciclo, não apenas a etapa de extração. As notas fiscais chegam em um endereço de caixa de entrada dedicado, através da API ou de uma pasta monitorada. O mecanismo de IA de visão (Vision AI) lê PDFs, digitalizações e fotografias, e o mecanismo de Text AI lê e-mails e documentos de texto. Os campos saem nomeados e tipados, e os itens de linha saem como linhas. Não há modelos (templates) para escrever e nada para manter quando um fornecedor redesenha sua nota fiscal.

O que você recebe além do JSON é a metade sobre a qual este artigo vem alertando. Os dados extraídos podem ser revisados e corrigidos no próprio local, para que uma pessoa de Contas a Pagar corrija um total lido incorretamente sem abrir um ticket. As correções retroalimentam a extração. E os dados vão para onde precisam ir através de integração direta via webhook, Make, Zapier ou Microsoft Power Automate, ou direto da API como JSON.

Se você quiser ver o conjunto de campos que extraímos das notas fiscais por padrão, isso está documentado em nossa página de OCR de notas fiscais, e o fluxo de trabalho mais amplo é abordado na captura de dados de notas fiscais.

Crie sua conta gratuita
Poupe tempo e esforço com Parseur. Automatize seus documentos.

Conclusão

Extrair dados de notas fiscais de um PDF com Python é um problema resolvido para cerca de cem notas fiscais e um problema não resolvido para dez mil. O código não é o que muda entre esses dois números. O que muda é quantos layouts de fornecedores você se compromete silenciosamente a manter, e quem é chamado quando um deles é modificado.

Escreva o script. Genuinamente vale a pena fazer uma vez, nem que seja para descobrir exatamente qual dos sete modos de falha acima atingirá você primeiro. Em seguida, decida honestamente se os próximos seis meses do seu tempo são mais bem gastos no oitavo. Se a resposta for não, o Parseur faz isso desde 2016 e tirará essa pasta de arquivos das suas mãos.

Última atualização em

Comece agora

Chega de digitar dados
na mão.

Comece grátis em poucos minutos e veja como o Parseur se encaixa no seu fluxo de trabalho.

Sem precisar treinar modelo
Feito para fluxos de trabalho reais, não para experimentos
Do clique à API, você escala do seu jeito

Perguntas Frequentes

As perguntas que os desenvolvedores realmente fazem depois que o primeiro script de notas fiscais está funcionando e o segundo fornecedor o quebrou.

Leia o texto do PDF com uma biblioteca como pdfplumber ou pdftotext, depois extraia campos nomeados desse texto. Para PDFs nativos digitais, esse é um trabalho de duas etapas. Para digitalizações, você precisa de uma passagem de OCR primeiro para transformar a imagem em texto. A parte que decide se funciona em produção não é a leitura, é como você vai de uma parede de texto para número da nota fiscal, data, fornecedor e itens de linha quando cada fornecedor os apresenta de forma diferente.

O invoice2data é uma ferramenta de linha de comando de código aberto e biblioteca Python que extrai campos de notas fiscais usando modelos YAML que você escreve por fornecedor. É uma boa opção quando você tem um conjunto pequeno e estável de fornecedores e deseja a lógica de correspondência no controle de versão em vez do seu código. Deixa de ser uma boa opção no ponto em que escrever e manter um modelo por fornecedor custa mais do que a redigitação que substituiu.

Trate a tabela de itens de linha como uma extração separada dos campos de cabeçalho e reconstrua-a através das páginas antes de analisá-la. O extract_table do pdfplumber funciona em tabelas com linhas visíveis (bordas) e não retorna nada nas sem bordas, o que é o caso da maioria das notas fiscais de fornecedores. O padrão confiável é detectar os limites das colunas uma vez por layout de fornecedor, mantê-los através de quebras de página, descartar linhas de cabeçalho repetidas e, em seguida, verificar se as linhas que você extraiu somam o subtotal. Se não o fizerem, você perdeu uma linha.

Com verificações determinísticas no seu próprio código, nunca apenas com a confiança do extrator. O conjunto principal é a aritmética e a identidade. Confirme que o subtotal mais imposto mais frete menos desconto resulta no total, que os itens de linha somam o subtotal, que a data seja analisada e não esteja no futuro, que o número da nota fiscal ainda não tenha sido pago para aquele fornecedor, que o fornecedor existe no seu cadastro principal de fornecedores e que a moeda é a esperada. Tudo o que falhar vai para um humano em vez do sistema contábil.

Quando a extração deixa de ser a parte difícil. Chamar um modelo de visão é barato e rápido para prototipar, portanto, se você tiver um punhado de fornecedores fixos e alguém que possa monitorar o pipeline, construa. A conta chega depois, na fila e na lógica de repetição, na tela de revisão de exceções que sua equipe de Contas a Pagar precisa, na detecção de duplicatas, na correspondência de fornecedores, na trilha de auditoria e na integração contábil. Conte tudo isso antes de comparar os preços por página.

Sim, mas uma digitalização precisa de uma passagem de OCR antes que as bibliotecas de texto possam ver qualquer coisa. Uma nota fiscal fotografada ou digitalizada é uma imagem envolvida em um PDF, então o pdfplumber e o pdftotext retornam uma string vazia nela. A rota comum de código aberto é o Tesseract através da ligação (binding) pytesseract, depois de alinhar e limpar a imagem. Modelos de visão modernos ignoram essa etapa totalmente e leem a imagem diretamente.

Não existe biblioteca de notas fiscais, apenas bibliotecas PDF e sua própria lógica. pdfplumber é a primeira escolha comum porque expõe palavras com suas coordenadas e tem um extrator de tabelas. PyMuPDF é mais rápido em grandes lotes. pdftotext é a menor coisa que funciona quando você só precisa do texto bruto. pytesseract lida com digitalizações. Cada um fornece texto ou caixas. Nenhum deles diz qual número é o total.

Porque um regex corresponde a uma string e uma nota fiscal é uma imagem. Seu padrão está ancorado a um rótulo, uma quebra de linha ou uma posição de coluna que o novo modelo do fornecedor moveu. As notas fiscais são documentos visuais semiestruturados, portanto, os problemas que causam falhas são problemas de layout, e não de string. Tabelas que se dividem entre páginas, cabeçalhos repetidos, células mescladas e a diferença entre subtotal, total e valor devido não podem ser corrigidos com uma expressão regular melhor.

Sim, e agora é o caminho mais curto de um PDF para um JSON estruturado, mas apenas com um esquema e um validador ao redor. Um modelo de visão lê a nota fiscal como um ser humano, de modo que a mudança de layout de um fornecedor deixa de ser um evento. Restrinja a saída com um esquema JSON, usando algo como os OpenAI structured outputs ou um modelo Pydantic, para que você obtenha as mesmas chaves todas as vezes. Em seguida, verifique a aritmética você mesmo. Um modelo que não consegue encontrar o número da nota fiscal, às vezes, inventará um plausível.

A precisão depende do campo e da digitalização, não do produto, portanto trate qualquer porcentagem de destaque como marketing. Totais impressos e números de notas fiscais em um PDF nativo digital limpo retornam quase perfeitos. Os mesmos campos em uma digitalização fotografada, torta e de baixo contraste são onde os dígitos se confundem e onde um caractere errado custa dinheiro de verdade. O número que vale a pena medir não é a precisão dos caracteres, mas quantas notas fiscais chegam ao seu sistema de contabilidade sem que um humano as toque.

Você para de escrever qualquer coisa por fornecedor. Qualquer abordagem que precise de um modelo, um conjunto de regex ou um mapa de coordenadas para cada fornecedor cresce linearmente com sua lista de fornecedores e não reduz o trabalho de ninguém após cerca de vinte a trinta layouts ativos. Um modelo que lê o documento visualmente é independente de formato por design, e é por isso que a variação de layout deixa de ser um evento de manutenção. O que ainda precisa da sua atenção é a fila de exceções, e isso é um problema de fluxo de trabalho e não de extração.

Escrever um CSV são apenas algumas linhas de Python e essa é a metade fácil. A metade difícil é inserir os dados no sistema que paga a conta, o que significa mapear os nomes de seus campos para o esquema dele, fazer a correspondência de fornecedores a registros existentes, lidar com as linhas rejeitadas e tentar novamente as chamadas que falham. Planeje essa metade desde o início, porque uma pasta de arquivos CSV que alguém ainda tem que importar à mão não economizou a tarde de ninguém.