Como Criar uma API Local em Python para Extrair Produtos de Encartes em PDF
Encartes e tabloides de supermercado continuam sendo o principal canal de divulgação de ofertas no varejo físico. No entanto, para analistas de precificação e desenvolvedores, esses arquivos costumam ser um obstáculo técnico complexo: documentos PDF com dezenas de páginas, layouts dinâmicos, blocos visuais assimétricos e textos sobrepostos em imagens de alta resolução.
Extrair cada produto individualmente — associando nome, preço, unidade de medida e a respectiva foto recortada — exige muito mais do que simples bibliotecas de leitura de texto. Quando o volume envolve catálogos semanais de 40 páginas ou mais, o envio constante para APIs de visão computacional na nuvem gera custos proibitivos e dependência de latência externa.
A solução mais sustentável e escalável é estruturar uma pipeline local de processamento baseada em visão computacional e OCR, exposta como um microserviço em Python.
O Desafio Estrutural dos Encartes de Varejo
Documentos em PDF podem ser classificados em dois grupos principais: baseados em texto vetorial ou rasterizados (compostos puramente por imagens). Encartes de supermercado frequentemente misturam ambos ou são salvos diretamente de softwares gráficos como uma grande imagem por página.
Os principais gargalos incluem:
- Ausência de Linearidade: Textos não seguem a ordem convencional de leitura (esquerda para a direita, cima para baixo). O preço pode estar no canto superior direito de uma imagem, enquanto a descrição está centralizada abaixo.
- Isolamento de Ativos: Recortar a imagem correspondente de cada item exige detectar os limites exatos da caixa delimitadora (bounding box) do produto sem cortar pedaços do vizinho.
- Custo de Processamento: Processar 40 páginas em lote demanda controle rigoroso de memória RAM e GPU, evitando travamentos por Out of Memory (OOM).
Arquitetura da Solução: Pipeline em 4 Etapas
Para resolver este problema localmente, desenhamos uma arquitetura modular em Python dividida em quatro camadas principais:
[PDF Multipage]│
▼
- Rasterização & Otimização (PyMuPDF / pdf2image)
│
▼ - Detecção de Layout & Agrupamento Visual (YOLO / LayoutParser)
│
▼ - Extração Textual & Normalização (Tesseract OCR / PaddleOCR)
│
▼ - Exposição via API REST Local (FastAPI)
1. Rasterização Eficiente de Páginas
Em vez de carregar todas as páginas simultaneamente na memória, processamos o documento página a página como um gerador (generator). O PyMuPDF (fitz) oferece excelente desempenho para conversão de páginas em arrays NumPy.
python
import fitz
import numpy as np
import cv2
def extrairpaginas(caminhopdf: str, dpi: int = 200):
doc = fitz.open(caminhopdf)
for numeropagina in range(len(doc)):
pagina = doc[numeropagina]
pix = pagina.getpixmap(dpi=dpi)
img = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.h, pix.w, pix.n)
if pix.n == 4: # Converte RGBA para RGB
img = cv2.cvtColor(img, cv2.COLORRGBA2RGB)
yield numeropagina + 1, img
2. Segmentação Local de Produtos
Como especialista em IA e visão computacional, destaco que tentar extrair dados sem segmentar os blocos visuais primeiro resulta em associação incorreta de preços. O método mais robusto é treinar um detector leve (como YOLOv8 na categoria nano ou small) para identificar três classes fundamentais: produto_card, produto_imagem e tag_preco.
Uma vez identificada a área geral do card do produto, isolamos a região da imagem principal e salvamos em disco ou em memória codificada em Base64, pronta para consumo do banco de dados.
3. Extração e Validação com OCR Local
Com as regiões de interesse (ROIs) isoladas, aplicamos uma biblioteca de OCR local otimizada para o idioma português, como o PaddleOCR. Como os números de preços costumam ter fontes estilizadas, aplicamos pré-processamento com OpenCV (binarização adaptativa e remoção de ruídos) apenas na área do preço antes da inferência.
4. Empacotando em uma API com FastAPI
Para integrar essa rotina a outros sistemas da empresa, empacotamos o processo em um endpoint assíncrono via FastAPI com execução em segundo plano (background tasks):
python
from fastapi import FastAPI, UploadFile, File, BackgroundTasks
import shutil
import uuid
app = FastAPI(title=”Local PDF Product Extraction API”)
@app.post(“/api/v1/extrair-encarte”)
async def processarencarte(backgroundtasks: BackgroundTasks, arquivo: UploadFile = File(…)):
tarefaid = str(uuid.uuid4())
caminhotemporario = f”/tmp/{tarefa_id}.pdf”
with open(caminho_temporario, "wb") as buffer:
shutil.copyfileobj(arquivo.file, buffer)
background_tasks.add_task(executar_pipeline_extracao, caminho_temporario, tarefa_id)
return {
"status": "processando",
"tarefa_id": tarefa_id,
"mensagem": "O catálogo está sendo processado localmente."
}
Boas Práticas de Otimização e Performance
Para garantir que um catálogo de 40 páginas não sobrecarregue a infraestrutura interna do servidor:
- Controle de Resolução: Evite rasterizar em DPI excessivo. Uma configuração de 150 a 200 DPI já fornece densidade suficiente para OCR legível sem inflar a matriz de pixels.
- Batching: Processe as detecções visuais em batches na GPU ou em núcleos de CPU via OpenVINO/ONNX Runtime.
- Pós-processamento com Regex: Valide formatos de moedas (ex.:
R$ d+,d{2}) para filtrar ruídos residuais de leitura.
Próximos Passos na Automação do Seu Negócio
A migração da transcrição manual ou de APIs caras na nuvem para uma arquitetura local reduz custos de escala para zero e entrega total soberania sobre os dados da sua operação de varejo.
Se você busca construir ou otimizar pipelines locais de processamento de documentos com Visão Computacional e Python, conte com a experiência técnica de Thiago Programador. Entre em contato para avaliar a viabilidade da sua demanda e desenhar uma solução sob medida para sua empresa.


