Imagine processar centenas de contratos em minutos!
IA para documentos automatiza tarefas que levariam dias: extrair dados, resumir conteúdo, encontrar informações específicas e muito mais.
Nesta aula, você vai transformar qualquer documento em dados estruturados e insights valiosos usando IA!
Problema: 500 contratos para revisar
Tempo manual: 2 semanas
Com IA: 2 horas
Problema: Extrair dados de prontuários
Tempo manual: 8 horas/dia
Com IA: 30 minutos
Problema: Analisar relatórios financeiros
Tempo manual: 3 dias
Com IA: 1 hora
Problema: Processar dissertações
Tempo manual: 1 semana
Com IA: 2 horas
Uma empresa que processa 100 documentos por dia pode economizar R$ 50.000 por mês automatizando com IA!
Converter PDFs, imagens e documentos em texto
Encontrar informações específicas
Categorizar documentos automaticamente
Criar resumos automáticos
pip install PyPDF2 pdfplumber pytesseract Pillow transformers langchain
Ferramentas para PDFs, OCR e IA
Windows: Baixe do GitHub oficial
Mac: brew install tesseract
Linux: sudo apt install tesseract-ocr
import PyPDF2
import pdfplumber
print("✅ Bibliotecas instaladas com sucesso!")
Vamos criar um sistema completo que processa qualquer tipo de documento e extrai insights valiosos!
import PyPDF2
import pdfplumber
import pytesseract
from PIL import Image
import re
import os
from datetime import datetime
import json
from transformers import pipeline
import pandas as pd
from typing import Dict, List, Any
import logging
class IntelligentDocumentProcessor:
def __init__(self):
"""Inicializa o processador de documentos inteligente"""
print("📄 Inicializando Processador Inteligente de Documentos...")
# Configurar logging
logging.basicConfig(level=logging.INFO)
self.logger = logging.getLogger(__name__)
# Carregar modelos de IA
try:
print("🤖 Carregando modelos de IA...")
self.summarizer = pipeline("summarization",
model="facebook/bart-large-cnn")
self.classifier = pipeline("sentiment-analysis")
self.ner = pipeline("ner",
model="dbmdz/bert-large-cased-finetuned-conll03-english")
print("✅ Modelos carregados com sucesso!")
except Exception as e:
print(f"⚠️ Erro ao carregar modelos: {e}")
self.summarizer = None
self.classifier = None
self.ner = None
# Padrões regex para extração de dados
self.patterns = {
'email': r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b',
'phone': r'(?:\+?55\s?)?(?:\(?[1-9][0-9]\)?\s?)?(?:[2-9][0-9]{3,4}[-\s]?[0-9]{4})',
'cpf': r'\b\d{3}\.?\d{3}\.?\d{3}[-.]?\d{2}\b',
'cnpj': r'\b\d{2}\.?\d{3}\.?\d{3}/?0001[-.]?\d{2}\b',
'date': r'\b(?:[0-3]?\d[/.-][01]?\d[/.-](?:19|20)?\d{2})\b',
'money': r'R\$\s?[\d.,]+|\$\s?[\d.,]+',
'cep': r'\b\d{5}[-.]?\d{3}\b'
}
print("🎯 Processador pronto para uso!")
def extract_text_from_pdf(self, pdf_path: str) -> Dict[str, Any]:
"""Extrai texto de PDF usando múltiplas técnicas"""
print(f"📖 Extraindo texto de: {pdf_path}")
result = {
'file_path': pdf_path,
'extracted_text': '',
'pages': [],
'method_used': '',
'success': False,
'error': None
}
try:
# Método 1: pdfplumber (melhor para PDFs com layout complexo)
with pdfplumber.open(pdf_path) as pdf:
full_text = []
for i, page in enumerate(pdf.pages):
page_text = page.extract_text()
if page_text:
full_text.append(page_text)
result['pages'].append({
'page_number': i + 1,
'text': page_text,
'word_count': len(page_text.split())
})
if full_text:
result['extracted_text'] = '\n'.join(full_text)
result['method_used'] = 'pdfplumber'
result['success'] = True
print(f"✅ Texto extraído com pdfplumber: {len(result['extracted_text'])} caracteres")
return result
except Exception as e:
print(f"⚠️ Erro com pdfplumber: {e}")
try:
# Método 2: PyPDF2 (fallback)
with open(pdf_path, 'rb') as file:
pdf_reader = PyPDF2.PdfReader(file)
full_text = []
for i, page in enumerate(pdf_reader.pages):
page_text = page.extract_text()
if page_text:
full_text.append(page_text)
result['pages'].append({
'page_number': i + 1,
'text': page_text,
'word_count': len(page_text.split())
})
if full_text:
result['extracted_text'] = '\n'.join(full_text)
result['method_used'] = 'PyPDF2'
result['success'] = True
print(f"✅ Texto extraído com PyPDF2: {len(result['extracted_text'])} caracteres")
return result
except Exception as e:
result['error'] = str(e)
print(f"❌ Erro ao extrair texto: {e}")
return result
def extract_structured_data(self, text: str) -> Dict[str, List[str]]:
"""Extrai dados estruturados usando regex"""
print("🔍 Extraindo dados estruturados...")
extracted_data = {}
for data_type, pattern in self.patterns.items():
matches = re.findall(pattern, text, re.IGNORECASE)
# Remover duplicatas mantendo ordem
unique_matches = list(dict.fromkeys(matches))
extracted_data[data_type] = unique_matches
if unique_matches:
print(f"📌 {data_type}: {len(unique_matches)} encontrado(s)")
return extracted_data
def extract_named_entities(self, text: str) -> Dict[str, List[str]]:
"""Extrai entidades nomeadas usando NER"""
if not self.ner:
return {}
print("👤 Extraindo entidades nomeadas...")
# Processar texto em chunks (NER tem limite de tokens)
max_length = 512
chunks = [text[i:i+max_length] for i in range(0, len(text), max_length)]
all_entities = {}
for chunk in chunks:
try:
entities = self.ner(chunk)
for entity in entities:
entity_type = entity['entity']
entity_text = entity['word']
if entity_type not in all_entities:
all_entities[entity_type] = []
if entity_text not in all_entities[entity_type]:
all_entities[entity_type].append(entity_text)
except Exception as e:
print(f"⚠️ Erro no NER: {e}")
continue
return all_entities
def classify_document(self, text: str) -> Dict[str, Any]:
"""Classifica o tipo de documento"""
print("📋 Classificando documento...")
# Palavras-chave para classificação
document_types = {
'contrato': ['contrato', 'contratante', 'contratado', 'cláusula', 'acordo'],
'relatório': ['relatório', 'análise', 'resultado', 'conclusão', 'dados'],
'fatura': ['fatura', 'cobrança', 'pagamento', 'valor', 'vencimento'],
'carta': ['carta', 'prezado', 'atenciosamente', 'cordialmente'],
'manual': ['manual', 'instruções', 'procedimento', 'passo', 'tutorial'],
'legal': ['lei', 'artigo', 'parágrafo', 'jurídico', 'tribunal'],
'financeiro': ['balanço', 'receita', 'despesa', 'lucro', 'investimento'],
'médico': ['paciente', 'diagnóstico', 'tratamento', 'medicamento', 'exame']
}
text_lower = text.lower()
scores = {}
for doc_type, keywords in document_types.items():
score = sum(1 for keyword in keywords if keyword in text_lower)
scores[doc_type] = score
# Encontrar tipo mais provável
best_type = max(scores, key=scores.get) if max(scores.values()) > 0 else 'genérico'
confidence = scores[best_type] / len(document_types[best_type]) if best_type != 'genérico' else 0
return {
'document_type': best_type,
'confidence': confidence,
'all_scores': scores
}
def generate_summary(self, text: str, max_length: int = 150) -> str:
"""Gera resumo automático do texto"""
if not self.summarizer:
return "Resumo não disponível (modelo não carregado)"
print("📝 Gerando resumo...")
try:
# Limitar texto para não sobrecarregar o modelo
max_input = 1024
if len(text) > max_input:
text = text[:max_input]
summary = self.summarizer(
text,
max_length=max_length,
min_length=30,
do_sample=False
)
return summary[0]['summary_text']
except Exception as e:
print(f"⚠️ Erro ao gerar resumo: {e}")
return "Erro ao gerar resumo"
def analyze_sentiment(self, text: str) -> Dict[str, Any]:
"""Analisa o sentimento do documento"""
if not self.classifier:
return {'sentiment': 'neutro', 'confidence': 0}
print("😊 Analisando sentimento...")
try:
# Usar apenas parte do texto para análise
sample_text = text[:512]
result = self.classifier(sample_text)[0]
return {
'sentiment': result['label'],
'confidence': result['score']
}
except Exception as e:
print(f"⚠️ Erro na análise de sentimento: {e}")
return {'sentiment': 'neutro', 'confidence': 0}
def process_document(self, pdf_path: str, output_dir: str = "./processed_documents") -> Dict[str, Any]:
"""Processa um documento completo"""
print(f"\n{'='*60}")
print(f"🚀 PROCESSANDO DOCUMENTO: {os.path.basename(pdf_path)}")
print(f"{'='*60}")
# Criar diretório de saída
os.makedirs(output_dir, exist_ok=True)
# Extrair texto
extraction_result = self.extract_text_from_pdf(pdf_path)
if not extraction_result['success']:
return {
'error': 'Falha na extração de texto',
'details': extraction_result['error']
}
text = extraction_result['extracted_text']
# Processar com IA
structured_data = self.extract_structured_data(text)
entities = self.extract_named_entities(text)
document_class = self.classify_document(text)
summary = self.generate_summary(text)
sentiment = self.analyze_sentiment(text)
# Compilar resultados
analysis_result = {
'file_info': {
'file_path': pdf_path,
'file_name': os.path.basename(pdf_path),
'processed_at': datetime.now().isoformat(),
'file_size': os.path.getsize(pdf_path),
'pages_count': len(extraction_result['pages'])
},
'extraction': {
'method_used': extraction_result['method_used'],
'text_length': len(text),
'word_count': len(text.split()),
'pages': extraction_result['pages']
},
'classification': document_class,
'structured_data': structured_data,
'named_entities': entities,
'summary': summary,
'sentiment_analysis': sentiment,
'extracted_text': text
}
# Salvar resultados
output_filename = f"{os.path.splitext(os.path.basename(pdf_path))[0]}_analysis.json"
output_path = os.path.join(output_dir, output_filename)
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(analysis_result, f, indent=2, ensure_ascii=False)
print(f"💾 Análise salva em: {output_path}")
# Gerar relatório visual
self.generate_report(analysis_result, output_dir)
return analysis_result
def generate_report(self, analysis: Dict[str, Any], output_dir: str):
"""Gera relatório visual da análise"""
report_content = f"""
# 📄 RELATÓRIO DE ANÁLISE DE DOCUMENTO
## 📁 Informações do Arquivo
- **Nome**: {analysis['file_info']['file_name']}
- **Tamanho**: {analysis['file_info']['file_size']:,} bytes
- **Páginas**: {analysis['file_info']['pages_count']}
- **Processado em**: {analysis['file_info']['processed_at']}
## 📋 Classificação do Documento
- **Tipo**: {analysis['classification']['document_type'].upper()}
- **Confiança**: {analysis['classification']['confidence']:.2%}
## 📝 Resumo Executivo
{analysis['summary']}
## 😊 Análise de Sentimento
- **Sentimento**: {analysis['sentiment_analysis']['sentiment'].upper()}
- **Confiança**: {analysis['sentiment_analysis']['confidence']:.2%}
## 📊 Dados Estruturados Encontrados
"""
for data_type, values in analysis['structured_data'].items():
if values:
report_content += f"- **{data_type.upper()}**: {len(values)} encontrado(s)\n"
for value in values[:5]: # Mostrar apenas os 5 primeiros
report_content += f" - {value}\n"
if len(values) > 5:
report_content += f" - ... e mais {len(values) - 5}\n"
if analysis['named_entities']:
report_content += "\n## 👤 Entidades Nomeadas\n"
for entity_type, entities in analysis['named_entities'].items():
if entities:
report_content += f"- **{entity_type}**: {', '.join(entities[:5])}\n"
report_content += f"\n## 📈 Estatísticas\n"
report_content += f"- **Caracteres**: {analysis['extraction']['text_length']:,}\n"
report_content += f"- **Palavras**: {analysis['extraction']['word_count']:,}\n"
report_content += f"- **Método de Extração**: {analysis['extraction']['method_used']}\n"
# Salvar relatório
report_filename = f"{analysis['file_info']['file_name']}_report.md"
report_path = os.path.join(output_dir, report_filename)
with open(report_path, 'w', encoding='utf-8') as f:
f.write(report_content)
print(f"📋 Relatório gerado: {report_path}")
def batch_process(self, documents_folder: str, output_dir: str = "./batch_processed"):
"""Processa múltiplos documentos em lote"""
print(f"\n{'='*60}")
print(f"🗂️ PROCESSAMENTO EM LOTE")
print(f"{'='*60}")
# Encontrar todos os PDFs na pasta
pdf_files = []
for file in os.listdir(documents_folder):
if file.lower().endswith('.pdf'):
pdf_files.append(os.path.join(documents_folder, file))
if not pdf_files:
print("❌ Nenhum PDF encontrado na pasta!")
return
print(f"📚 {len(pdf_files)} documentos encontrados")
# Processar cada documento
results = []
for i, pdf_path in enumerate(pdf_files, 1):
print(f"\n📄 Processando {i}/{len(pdf_files)}: {os.path.basename(pdf_path)}")
try:
result = self.process_document(pdf_path, output_dir)
results.append(result)
print(f"✅ Concluído: {os.path.basename(pdf_path)}")
except Exception as e:
print(f"❌ Erro ao processar {os.path.basename(pdf_path)}: {e}")
continue
# Gerar relatório consolidado
self.generate_batch_report(results, output_dir)
print(f"\n🎉 PROCESSAMENTO EM LOTE CONCLUÍDO!")
print(f"📁 Resultados em: {output_dir}")
return results
def generate_batch_report(self, results: List[Dict], output_dir: str):
"""Gera relatório consolidado do processamento em lote"""
if not results:
return
# Estatísticas gerais
total_files = len(results)
total_pages = sum(r['file_info']['pages_count'] for r in results)
total_words = sum(r['extraction']['word_count'] for r in results)
# Tipos de documento
doc_types = {}
for result in results:
doc_type = result['classification']['document_type']
doc_types[doc_type] = doc_types.get(doc_type, 0) + 1
# Criar DataFrame para análise
df_data = []
for result in results:
df_data.append({
'arquivo': result['file_info']['file_name'],
'tipo': result['classification']['document_type'],
'confianca_tipo': result['classification']['confidence'],
'paginas': result['file_info']['pages_count'],
'palavras': result['extraction']['word_count'],
'sentimento': result['sentiment_analysis']['sentiment'],
'confianca_sentimento': result['sentiment_analysis']['confidence']
})
df = pd.DataFrame(df_data)
# Salvar CSV
csv_path = os.path.join(output_dir, 'batch_analysis_summary.csv')
df.to_csv(csv_path, index=False)
print(f"📊 Resumo em CSV: {csv_path}")
# Relatório consolidado
consolidated_report = f"""
# 📊 RELATÓRIO CONSOLIDADO - PROCESSAMENTO EM LOTE
## 📈 Estatísticas Gerais
- **Total de Documentos**: {total_files}
- **Total de Páginas**: {total_pages:,}
- **Total de Palavras**: {total_words:,}
- **Média de Palavras por Documento**: {total_words // total_files:,}
## 📋 Distribuição por Tipo de Documento
"""
for doc_type, count in sorted(doc_types.items()):
percentage = (count / total_files) * 100
consolidated_report += f"- **{doc_type.upper()}**: {count} documentos ({percentage:.1f}%)\n"
consolidated_report += "\n## 📄 Resumo por Documento\n"
for result in results:
consolidated_report += f"""
### {result['file_info']['file_name']}
- **Tipo**: {result['classification']['document_type']}
- **Páginas**: {result['file_info']['pages_count']}
- **Sentimento**: {result['sentiment_analysis']['sentiment']}
- **Resumo**: {result['summary'][:100]}...
"""
# Salvar relatório consolidado
report_path = os.path.join(output_dir, 'consolidated_report.md')
with open(report_path, 'w', encoding='utf-8') as f:
f.write(consolidated_report)
print(f"📋 Relatório consolidado: {report_path}")
# Exemplo de uso
if __name__ == "__main__":
print("🚀 INICIANDO PROCESSADOR INTELIGENTE DE DOCUMENTOS")
print("="*60)
# Inicializar processador
processor = IntelligentDocumentProcessor()
# Exemplo 1: Processar um documento único
print("\n📄 EXEMPLO 1: DOCUMENTO ÚNICO")
# Substitua pelo caminho do seu PDF
pdf_path = "exemplo_contrato.pdf"
if os.path.exists(pdf_path):
result = processor.process_document(pdf_path)
print("\n🎯 RESUMO DA ANÁLISE:")
print(f"📋 Tipo: {result['classification']['document_type']}")
print(f"📊 Confiança: {result['classification']['confidence']:.2%}")
print(f"📝 Resumo: {result['summary']}")
# Mostrar dados encontrados
for data_type, values in result['structured_data'].items():
if values:
print(f"🔍 {data_type}: {len(values)} encontrado(s)")
else:
print(f"⚠️ Arquivo não encontrado: {pdf_path}")
print("📁 Criando PDF de exemplo...")
# Criar PDF de exemplo para demonstração
example_text = """
CONTRATO DE PRESTAÇÃO DE SERVIÇOS
Contratante: João Silva
CPF: 123.456.789-10
Email: joao@email.com
Telefone: (11) 99999-9999
Contratado: Empresa ABC LTDA
CNPJ: 12.345.678/0001-90
Valor: R$ 5.000,00
Data: 15/08/2025
Este contrato tem por objeto a prestação de serviços de consultoria
em tecnologia da informação, conforme especificações anexas.
O prazo para execução é de 30 dias corridos a partir da assinatura.
"""
print("📝 PDF de exemplo criado conceitualmente")
print("🎯 Use seus próprios PDFs para testar o sistema!")
# Exemplo 2: Processamento em lote
print(f"\n📁 EXEMPLO 2: PROCESSAMENTO EM LOTE")
print("Para usar o processamento em lote:")
print("1. Crie uma pasta com vários PDFs")
print("2. Execute: processor.batch_process('caminho/para/pasta')")
print(f"\n🎉 DEMONSTRAÇÃO CONCLUÍDA!")
print("💡 Agora você pode processar qualquer documento com IA!")
OCR (Optical Character Recognition)
Converte documentos escaneados, fotos e imagens em texto editável e pesquisável.
import pytesseract
from PIL import Image, ImageEnhance, ImageFilter
import cv2
import numpy as np
class OCRProcessor:
def __init__(self):
"""Inicializa processador OCR avançado"""
print("👁️ Inicializando OCR Processor...")
# Configurações do Tesseract
self.tesseract_config = r'--oem 3 --psm 6 -l por'
def preprocess_image(self, image_path: str) -> Image.Image:
"""Pré-processa imagem para melhor OCR"""
print("🔧 Pré-processando imagem...")
# Carregar imagem
img = cv2.imread(image_path)
# Converter para escala de cinza
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Reduzir ruído
denoised = cv2.medianBlur(gray, 5)
# Aumentar contraste
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
enhanced = clahe.apply(denoised)
# Binarização adaptativa
binary = cv2.adaptiveThreshold(
enhanced, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2
)
# Converter de volta para PIL
pil_image = Image.fromarray(binary)
return pil_image
def extract_text_from_image(self, image_path: str) -> str:
"""Extrai texto de imagem usando OCR"""
print(f"📸 Extraindo texto de: {image_path}")
try:
# Pré-processar imagem
processed_img = self.preprocess_image(image_path)
# Executar OCR
text = pytesseract.image_to_string(
processed_img,
config=self.tesseract_config
)
# Limpar texto
cleaned_text = text.strip().replace('\n\n', '\n')
print(f"✅ Texto extraído: {len(cleaned_text)} caracteres")
return cleaned_text
except Exception as e:
print(f"❌ Erro no OCR: {e}")
return ""
def process_scanned_pdf(self, pdf_path: str) -> str:
"""Processa PDF escaneado usando OCR"""
print(f"📄 Processando PDF escaneado: {pdf_path}")
# Converter PDF para imagens
import fitz # PyMuPDF
doc = fitz.open(pdf_path)
full_text = []
for page_num in range(doc.page_count):
page = doc[page_num]
# Converter página para imagem
pix = page.get_pixmap(matrix=fitz.Matrix(2, 2)) # Alta resolução
img_data = pix.tobytes("png")
# Salvar temporariamente
temp_img_path = f"temp_page_{page_num}.png"
with open(temp_img_path, "wb") as f:
f.write(img_data)
# Executar OCR
page_text = self.extract_text_from_image(temp_img_path)
full_text.append(page_text)
# Limpar arquivo temporário
os.remove(temp_img_path)
print(f"📄 Página {page_num + 1}/{doc.page_count} processada")
doc.close()
return '\n'.join(full_text)
# Exemplo de uso
ocr = OCRProcessor()
# Para imagem única
# text = ocr.extract_text_from_image("documento_escaneado.jpg")
# Para PDF escaneado
# text = ocr.process_scanned_pdf("documento_escaneado.pdf")
Objetivo: Revisar contratos automaticamente
ROI: 85% redução no tempo de análise
Objetivo: Digitalizar prontuários
ROI: 70% economia em tempo administrativo
Objetivo: Processar faturas e recibos
ROI: 90% redução em erros manuais
Objetivo: Analisar pesquisas e teses
ROI: 60% aceleração em revisões
OCR profissional na nuvem
from google.cloud import vision
Vantagem: Alta precisão, múltiplos idiomas
Especializado em formulários
from azure.ai.formrecognizer import DocumentAnalysisClient
Vantagem: Entende layout de documentos
Extração inteligente de dados
import boto3
textract = boto3.client('textract')
Vantagem: Tabelas e formulários complexos
Análise semântica avançada
import openai
openai.api_key = "sua-chave"
Vantagem: Compreensão de contexto
from concurrent.futures import ThreadPoolExecutor
import multiprocessing
def process_documents_parallel(pdf_list):
with ThreadPoolExecutor(max_workers=multiprocessing.cpu_count()) as executor:
futures = [executor.submit(process_document, pdf) for pdf in pdf_list]
results = [future.result() for future in futures]
return results
Melhoria: 3-4x mais rápido
import hashlib
import pickle
import os
def cache_result(func):
def wrapper(*args, **kwargs):
# Criar hash único do arquivo
file_path = args[0]
file_hash = hashlib.md5(open(file_path, 'rb').read()).hexdigest()
cache_file = f"cache_{file_hash}.pkl"
if os.path.exists(cache_file):
with open(cache_file, 'rb') as f:
return pickle.load(f)
result = func(*args, **kwargs)
with open(cache_file, 'wb') as f:
pickle.dump(result, f)
return result
return wrapper
Melhoria: Evita reprocessar arquivos
import time
import psutil
from datetime import datetime
class PerformanceMonitor:
def __init__(self):
self.start_time = None
self.start_memory = None
def start_monitoring(self):
self.start_time = time.time()
self.start_memory = psutil.Process().memory_info().rss / 1024 / 1024
print(f"🚀 Iniciando monitoramento...")
def end_monitoring(self):
end_time = time.time()
end_memory = psutil.Process().memory_info().rss / 1024 / 1024
duration = end_time - self.start_time
memory_used = end_memory - self.start_memory
print(f"⏱️ Tempo: {duration:.2f}s")
print(f"💾 Memória: {memory_used:.2f}MB")
Benefício: Acompanhar performance
Serviço: Implementação de processamento de documentos
Preço: R$ 50.000 - R$ 300.000 por projeto
Clientes: Empresas médias e grandes
Serviço: Plataforma online de processamento
Preço: R$ 500 - R$ 5.000 por mês
Clientes: Advogados, contadores, médicos
Serviço: Especialização em um setor
Preço: R$ 10.000 - R$ 100.000 por mês
Clientes: Hospitais, escritórios, bancos
Você acabou de criar um sistema profissional de processamento de documentos que pode revolucionar qualquer empresa!
Na próxima aula, vamos mergulhar no reconhecimento de imagens e visão computacional para criar sistemas que "vêem" e compreendem o mundo visual!
"Documentos são dados esperando para serem descobertos"
- Isaque Victor