Biblioteca Python para parsing de preços de scraping, cálculo de descontos e análise estatística de histórico de preços.
Project description
notify-utils
Biblioteca Python completa para análise de preços de e-commerce: parsing, validação, cálculo de descontos reais e detecção de promoções falsas através de análise estatística de histórico.
🎯 Funcionalidades
- Parser de Preços: Normaliza strings de preços de diferentes formatos (BR, US)
- Parsers de Lojas: Extração automática de produtos de APIs/HTML específicas (Nike, Maze Shop, Beleza na Web)
- Cálculo de Descontos Inteligente: Detecta descontos reais vs anunciados usando histórico
- Análise Estatística Avançada: Média, mediana, tendências, volatilidade e confiança
- Sistema de Validação de Preços: Estratégias inteligentes para validar preços antes de adicionar ao histórico
- Ajuste Automático de Período: Garante inclusão de histórico mais recente
- Filtro de Ruído: Ignora dados voláteis recentes (scraping com erros)
- Notificações Discord: Envio de alertas de preço via webhook (opcional)
Instalação
pip install notify-utils
Uso Básico
Parsing de Preços
from notify_utils import parse_price
preco = parse_price("R$ 1.299,90") # → 1299.90
preco = parse_price("$1,299.90") # → 1299.90
Cálculo de Desconto com Histórico
from notify_utils import Price, get_discount_info
from datetime import datetime, timedelta
# Histórico de preços
precos = [
Price(value=1299.90, date=datetime.now() - timedelta(days=60)),
Price(value=1199.90, date=datetime.now() - timedelta(days=30)),
]
# Calcular desconto real baseado no histórico
info = get_discount_info(
current_price=899.90,
price_history=precos,
period_days=30
)
print(f"Desconto real: {info.discount_percentage:.2f}%")
print(f"É desconto real? {info.is_real_discount}")
Análise de Tendência
from notify_utils import calculate_price_trend
trend = calculate_price_trend(precos, days=30)
print(f"Direção: {trend.direction}") # 'increasing', 'decreasing', 'stable'
print(f"Mudança: {trend.change_percentage:.2f}%")
print(f"Confiança: {trend.confidence}")
Validação de Preços com Estratégias
from notify_utils import PriceHistory, Price, PriceAdditionStrategy, PriceAction
history = PriceHistory(product_id="PROD123", prices=precos)
# Estratégia SMART: aceita quedas imediatas, aumentos após 24h
novo_preco = Price(value=899.90, date=datetime.now())
result = history.add_price(
novo_preco,
strategy=PriceAdditionStrategy.SMART,
min_hours_for_increase=24
)
# Integração com banco de dados
if result.action == PriceAction.ADDED:
db.insert_price(product_id, result.affected_price)
print(f"✅ Preço adicionado: R$ {result.affected_price.value:.2f}")
elif result.action == PriceAction.REJECTED:
print(f"⏭️ Ignorado: {result.reason}")
Ajuste Automático de Período e Filtro de Ruído
from notify_utils import get_discount_info
# Ajusta período automaticamente + ignora 3 dias mais recentes
info = get_discount_info(
current_price=899.90,
price_history=precos,
period_days=30,
auto_adjust_period=True, # Inclui histórico mais recente
skip_recent_days=3 # Ignora ruído de 0-2 dias
)
print(f"Período solicitado: {info.period_days} dias")
print(f"Período ajustado: {info.adjusted_period_days} dias")
print(f"Dias ignorados: {info.skip_recent_days}")
print(f"Amostras usadas: {info.samples_count}")
Parser HTML - Beleza na Web
from notify_utils import ParserFactory, StoresParserEnum
# Obter parser para Beleza na Web (HTML)
parser = ParserFactory.get_parser(StoresParserEnum.BELEZA_NA_WEB_HTML)
# Parse HTML (deduplica automaticamente produtos repetidos em carrosséis)
with open('beleza.html', 'r', encoding='utf-8') as f:
html = f.read()
products = parser.from_html(html)
# Processar produtos extraídos
for product in products:
print(f"{product.name}")
print(f" Preço atual: R$ {product.current_price_float:.2f}")
if product.old_price_float > 0:
desconto_pct = ((product.old_price_float - product.current_price_float) / product.old_price_float) * 100
print(f" Desconto: {desconto_pct:.1f}%")
Características:
- ✅ Parse híbrido (JSON embedded no data-event + HTML estruturado)
- ✅ Deduplicação automática por SKU (carrosséis repetem produtos)
- ✅ Extrai ~36 produtos únicos de ~430 repetições no HTML
- ✅ Preços, URLs, imagens e metadados completos
Notificações Discord
from notify_utils import Product, DiscordEmbedBuilder
produto = Product(
product_id="PROD123",
name="Notebook Gamer",
url="https://loja.com/produto"
)
builder = DiscordEmbedBuilder()
embed = builder.build_embed(produto, info, precos)
# Enviar via webhook Discord
📊 Estratégias de Validação
A biblioteca oferece 4 estratégias para adicionar preços ao histórico:
| Estratégia | Comportamento | Uso Recomendado |
|---|---|---|
ALWAYS |
Sempre adiciona | Testes, coleta sem filtro |
ONLY_DECREASE |
Apenas quedas | Alertas de promoção |
SMART ⭐ |
Quedas imediatas + aumentos após tempo mínimo | Produção (padrão) |
UPDATE_ON_EQUAL |
Atualiza timestamp se preço igual | Rastreamento de estabilidade |
🔧 Casos de Uso
1. Sistema de Scraping com Parsers e Validação
from notify_utils import (
ParserFactory, StoresParserEnum,
PriceHistory, Price, PriceAdditionStrategy, PriceAction
)
# 1. Extrair produtos da API da loja
parser = ParserFactory.get_parser(StoresParserEnum.MAZE_API_JSON)
products = parser.from_json(api_response)
# 2. Processar cada produto
for product in products:
# Carregar histórico do banco
prices_from_db = db.get_prices(product.product_id)
history = PriceHistory(product_id=product.product_id, prices=prices_from_db)
# Validar e adicionar novo preço
novo_preco = Price(value=product.current_price, date=datetime.now())
result = history.add_price(novo_preco, strategy=PriceAdditionStrategy.SMART)
if result.action == PriceAction.ADDED:
db.insert_price(product.product_id, result.affected_price)
# Notificar se queda >= 10%
if result.status.value == "decreased" and abs(result.percentage_difference) >= 10:
notifier.send_price_alert(product, discount_info, history.prices)
2. Pipeline Completo: API → Validação → Notificação
# Fluxo completo automatizado
def pipeline_completo(store: StoresParserEnum, api_data: dict):
# Passo 1: Parsing
parser = ParserFactory.get_parser(store)
products = parser.from_json(api_data)
for product in products:
# Passo 2: Validação com histórico
history = PriceHistory(product_id=product.product_id,
prices=db.get_prices(product.product_id))
novo_preco = Price(value=product.current_price, date=datetime.now())
result = history.add_price(novo_preco, strategy=PriceAdditionStrategy.SMART)
# Passo 3: Persistência
if result.action == PriceAction.ADDED:
db.insert_price(product.product_id, result.affected_price)
# Passo 4: Análise de desconto
info = get_discount_info(
current_price=product.current_price,
price_history=history.prices,
period_days=30
)
# Passo 5: Notificação se desconto real
if info.is_real_discount and info.discount_percentage >= 15:
discord_notifier.send_price_alert(product, info, history.prices)
3. Detecção de Promoções Falsas
# Loja anuncia "De R$ 1.999 por R$ 899" (50% off!)
# Mas histórico mostra que preço real era R$ 1.299
info = get_discount_info(
current_price=899.90,
price_history=precos_historicos,
advertised_old_price=1999.90 # IGNORADO quando há histórico!
)
print(f"Desconto anunciado: 55%")
print(f"Desconto REAL: {info.discount_percentage:.2f}%") # ~31% (vs R$ 1.299)
print(f"Estratégia: {info.strategy}") # 'history' (priorizou histórico)
4. Análise de Melhor Momento para Comprar
trend = calculate_price_trend(precos, days=30)
if trend.is_decreasing() and trend.has_high_confidence():
print("✅ Tendência de queda com alta confiança - BOM momento!")
elif trend.is_increasing() and trend.is_accelerating:
print("⚠️ Preço subindo rápido - compre agora ou espere próxima promoção")
📚 Documentação Completa
Para mais detalhes e exemplos avançados, consulte:
- CLAUDE.md - Documentação completa com arquitetura e exemplos
- notify_utils/ - Código fonte com docstrings detalhadas
🛠️ Requisitos
- Python >= 3.12
- discord-webhook >= 1.4.1 (opcional, apenas para notificações)
📝 Changelog
v0.2.3 (2026-02-05)
- 🏪 SephoraAPIJSONParser Completo: Parser para API Linx Impulse da Sephora Brasil
- 🔄 Expansão de SKUs: 1 produto com N variações → N produtos únicos (36 → 105 SKUs)
- 📦 Nome Combinado: Formato
{nome_produto} - {tamanho}para cada variação - ✅ Validações Avançadas: Ignora SKUs indisponíveis ou com preço inválido
- 🖼️ URLs Completas: Conversão automática de URLs relativas e imagens
- 📊 Testes Completos: Suite em test_sephora_parser.py com 10 validações
- 📚 Documentação: Seção completa em PARSERS.md com casos de uso
v0.2.2 (2026-02-04)
- ✅ BelezaNaWebHTMLParser Completo: Implementação finalizada com parse híbrido JSON+HTML
- 🔍 Extração Avançada: Parse de
data-eventJSON embedded + fallback HTML estruturado - 🧹 Deduplicação por SKU: Remove ~430 produtos repetidos → 36 únicos (carrosséis)
- 🏷️ Preço Antigo: Extração automática de
.item-price-maxcom parse_price - 🖼️ URLs Completas: Conversão automática de URLs relativas para absolutas
- ⚡ Performance: Parser otimizado com lxml (fallback html.parser)
- ✅ Validações Robustas: Ignora produtos sem SKU/preço com logs detalhados
- 🧪 Testes Completos: Suite de testes com validações de campos e estatísticas
v0.2.1 (2026-02-03)
- 🏪 Parsers de Lojas: Maze API, Nike API e Beleza na Web HTML (inicial)
- 🔍 Parser HTML: Extração de produtos de páginas HTML com BeautifulSoup
- 🧹 Deduplicação Automática: Remove produtos duplicados por SKU
- 🏭 Factory Pattern: Sistema extensível para adicionar novos parsers
- 🎨 Type Hints Completos: Melhor experiência com IDEs e linters
v0.1.0 (2026-02-03)
- ✨ Sistema de validação de preços com estratégias
- 📊 Ajuste automático de período histórico
- 🔇 Filtro de ruído de dados recentes
- 📈 Análise de tendências com volatilidade
- 🎯 Novos modelos tipados e enums
Veja o changelog completo no CLAUDE.md
📄 Licença
MIT - veja LICENSE para detalhes.
👥 Contribuindo
Contribuições são bem-vindas! Abra issues ou pull requests no repositório.
⭐ Agradecimentos
Desenvolvido para ajudar consumidores a identificar promoções reais vs falsas no e-commerce brasileiro.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file notify_utils-0.3.3.tar.gz.
File metadata
- Download URL: notify_utils-0.3.3.tar.gz
- Upload date:
- Size: 40.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a8a2a2ded9c202e887821e9ed08cbc85bf499fee64b67fecc7b6ded65dbbc05
|
|
| MD5 |
317cc501d463488e18acf6f777f69f94
|
|
| BLAKE2b-256 |
918c8d60e4195356592e35e6d1b39a296916c485f3d9ad007742658fde0f6a73
|
File details
Details for the file notify_utils-0.3.3-py3-none-any.whl.
File metadata
- Download URL: notify_utils-0.3.3-py3-none-any.whl
- Upload date:
- Size: 41.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d6e47e273dfc947f0d8733ceb08210c55e53491c0585e726b9843d8d56ccdeb0
|
|
| MD5 |
0d5dadec13eea7c14a2a848409fc9e97
|
|
| BLAKE2b-256 |
ccee134fbf7ea9881c0a05f55ef7e6d85a70ff7b50410b06257c9ec36641804f
|