WEB_SCRAPER (MONITOR) - Monitoramento Inteligente de Mudanças
O que é este Node?
O WEB_SCRAPER (MONITOR) é o node responsável por monitorar páginas web e detectar mudanças no conteúdo, alertando automaticamente quando algo importante muda. Ideal para acompanhar preços, vagas de emprego, notícias, disponibilidade de produtos e atualizações de sites.
Por que este Node existe?
Verificar manualmente se algo mudou em um site é tedioso e ineficiente. O WEB_SCRAPER (MONITOR) existe para:
- Automatizar vigilância: Checar páginas periodicamente sem intervenção manual
- Detectar mudanças: Identificar quando conteúdo relevante foi alterado
- Alertar proativamente: Notificar instantaneamente quando mudanças ocorrem
- Economizar tempo: Eliminar necessidade de checagens manuais repetitivas
- Capturar oportunidades: Ser o primeiro a saber quando algo importante muda
Como funciona internamente?
Quando o WEB_SCRAPER (MONITOR) é executado, o sistema:
- Carrega estado anterior: Busca último conteúdo conhecido da página (hash, texto, screenshot)
- Faz nova extração: Busca conteúdo atual da página
- Compara versões: Analisa diferenças entre versão anterior e atual
- Detecta mudanças: Identifica se houve alterações significativas
- Aplica filtros: Ignora mudanças irrelevantes (timestamps, ads dinâmicos)
- Calcula diferenças: Determina o que especificamente mudou
- Salva novo estado: Atualiza estado para próxima comparação
- Dispara alertas: Se mudança detectada, notifica conforme configurado
- Retorna resultado: Informa se houve mudança e detalhes do que mudou
Código interno (web-scraper-executor.service.ts:95-197 - adaptado para monitoramento):
async execute(data: WebScraperNodeData, context: ExecutionContext): Promise<ExecutionResult> {
const startTime = Date.now();
// Get previous state from context or storage
const previousState = await this.getPreviousState(data.url, context);
// Scrape current content
const currentResult = await this.scrapeUrl(data.url, data);
// Compare states
const changes = this.detectChanges(previousState, currentResult, data);
// Save new state for next comparison
await this.saveState(data.url, currentResult, context);
return {
success: true,
data: {
hasChanged: changes.detected,
changes: changes.details,
previous: previousState,
current: currentResult,
timestamp: new Date().toISOString()
},
executionTime: Date.now() - startTime
};
}
private detectChanges(previous: any, current: any, config: WebScraperNodeData): any {
// Implement change detection logic
// Can compare: text content, HTML structure, specific selectors, images, etc.
if (!previous) {
return { detected: true, details: 'First monitoring - no previous state' };
}
const textChanged = previous.text !== current.text;
const titleChanged = previous.title !== current.title;
return {
detected: textChanged || titleChanged,
details: {
textChanged,
titleChanged,
textDiff: this.calculateDiff(previous.text, current.text)
}
};
}
Quando você DEVE usar este Node?
Use WEB_SCRAPER (MONITOR) sempre que precisar detectar mudanças automaticamente:
Casos de uso
- Monitor de preços: "Me avise quando o preço do iPhone cair abaixo de R$ 4.000"
- Novas vagas de emprego: "Alerta quando uma vaga de 'Senior Developer' for publicada"
- Disponibilidade de produtos: "Notifique quando o produto voltar ao estoque"
- Atualizações de blog: "Avise quando um novo artigo for publicado"
- Mudanças em termos legais: "Detecte alterações em termos de uso ou políticas"
Quando NÃO usar WEB_SCRAPER (MONITOR)
- Sites com API de webhook: Use webhook nativo ao invés de polling
- Conteúdo altamente dinâmico: Anúncios, timestamps, contadores mudam sempre
- Monitoramento em tempo real: Scraping tem delay, use WebSockets para tempo real
- Sites que bloqueiam scraping: Use serviços oficiais ou APIs
Parâmetros Detalhados
monitorInterval (number, opcional)
O que é: Intervalo em minutos entre verificações. Quanto menor, mais rápido detecta mudanças mas consome mais recursos.
Padrão: 60 (1 hora)
Mínimo recomendado: 5 minutos
Flow completo para testar:
{
"name": "Monitor de Preço - Check a cada 10min",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "schedule_1",
"type": "schedule",
"position": { "x": 300, "y": 100 },
"data": {
"label": "A cada 10 minutos",
"parameters": {
"cron": "*/10 * * * *"
}
}
},
{
"id": "scraper_1",
"type": "web_scraper",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Monitor Preço",
"parameters": {
"operation": "monitor",
"url": "https://www.amazon.com.br/dp/B08N5WRWNW",
"mode": "manual",
"selectors": {
"preco": ".a-price-whole"
},
"monitorInterval": 10,
"changeThreshold": 0.01
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Mudou?",
"parameters": {
"condition": "{{scraper_1.data.hasChanged}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 900, "y": 50 },
"data": {
"label": "Alerta Mudança",
"parameters": {
"message": "🔔 Preço mudou!\nAntes: {{scraper_1.data.previous.text}}\nAgora: {{scraper_1.data.current.text}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1100, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "schedule_1" },
{ "source": "schedule_1", "target": "scraper_1" },
{ "source": "scraper_1", "target": "condition_1" },
{ "source": "condition_1", "target": "message_1", "label": "true" },
{ "source": "condition_1", "target": "end_1", "label": "false" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Verifica preço a cada 10 minutos e alerta se mudar.
changeThreshold (number, opcional)
O que é: Percentual mínimo de mudança (0-1) para considerar alteração significativa. Útil para ignorar pequenas variações irrelevantes.
Padrão: 0.05 (5%)
Flow completo para testar:
{
"name": "Monitor com Threshold de Mudança",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "scraper_1",
"type": "web_scraper",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Monitor Página",
"parameters": {
"operation": "monitor",
"url": "https://news.ycombinator.com",
"mode": "auto",
"extractText": true,
"changeThreshold": 0.1,
"ignoreSelectors": [".timestamp", ".score"]
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Mudança Significativa?",
"parameters": {
"condition": "{{scraper_1.data.hasChanged && scraper_1.data.changes.percentageChanged > 0.1}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 50 },
"data": {
"label": "Alerta",
"parameters": {
"message": "Mudança detectada: {{(scraper_1.data.changes.percentageChanged * 100).toFixed(1)}}% do conteúdo mudou"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "scraper_1" },
{ "source": "scraper_1", "target": "condition_1" },
{ "source": "condition_1", "target": "message_1", "label": "true" },
{ "source": "condition_1", "target": "end_1", "label": "false" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Só alerta se mais de 10% do conteúdo mudou.
ignoreSelectors (array de strings, opcional)
O que é: Lista de seletores CSS de elementos que devem ser ignorados na comparação. Útil para elementos que sempre mudam (timestamps, contadores, ads).
Padrão: []
Flow completo para testar:
{
"name": "Monitor Ignorando Elementos Dinâmicos",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "scraper_1",
"type": "web_scraper",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Monitor Notícias",
"parameters": {
"operation": "monitor",
"url": "https://www.bbc.com/news",
"mode": "auto",
"extractText": true,
"ignoreSelectors": [
".timestamp",
".ad",
".social-share",
".trending-now",
"[data-timestamp]"
]
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Nova Notícia?",
"parameters": {
"condition": "{{scraper_1.data.hasChanged}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 50 },
"data": {
"label": "Alerta Nova Notícia",
"parameters": {
"message": "📰 Nova notícia publicada!\n\nMudanças:\n{{scraper_1.data.changes.textDiff}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "scraper_1" },
{ "source": "scraper_1", "target": "condition_1" },
{ "source": "condition_1", "target": "message_1", "label": "true" },
{ "source": "condition_1", "target": "end_1", "label": "false" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Ignora timestamps e ads, detectando apenas mudanças reais no conteúdo.
compareMethod (string, opcional)
O que é: Método de comparação: "text" (compara texto), "hash" (compara hash do HTML), "visual" (compara screenshot).
Padrão: "text"
Valores aceitos: "text", "hash", "visual", "selector"
Flow completo para testar:
{
"name": "Monitor com Comparação por Hash",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "scraper_1",
"type": "web_scraper",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Monitor por Hash",
"parameters": {
"operation": "monitor",
"url": "https://example.com/terms",
"compareMethod": "hash",
"saveHtml": true,
"includeMetadata": true
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 500, "y": 100 },
"data": {
"label": "HTML Mudou?",
"parameters": {
"condition": "{{scraper_1.data.hasChanged}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 50 },
"data": {
"label": "Alerta Mudança Legal",
"parameters": {
"message": "⚠️ Termos de uso foram alterados!\n\nHash anterior: {{scraper_1.data.previous.hash}}\nHash atual: {{scraper_1.data.current.hash}}\n\nHTML salvo para comparação."
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "scraper_1" },
{ "source": "scraper_1", "target": "condition_1" },
{ "source": "condition_1", "target": "message_1", "label": "true" },
{ "source": "condition_1", "target": "end_1", "label": "false" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Compara hash SHA256 do HTML para detectar QUALQUER mudança, por menor que seja.
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| operation | string | Sim | Tipo de operação ("monitor") |
| url | string | Sim | URL da página a monitorar |
| monitorInterval | number | Não | Intervalo em minutos (padrão: 60) |
| changeThreshold | number | Não | Threshold de mudança 0-1 (padrão: 0.05) |
| ignoreSelectors | string[] | Não | Elementos a ignorar na comparação |
| compareMethod | string | Não | Método: "text", "hash", "visual", "selector" |
| mode | string | Não | Modo de extração |
| selectors | string/object | Não | Seletores específicos a monitorar |
| saveHistory | boolean | Não | Salvar histórico de mudanças (padrão: true) |
| alertOnFirstRun | boolean | Não | Alertar na primeira execução (padrão: false) |
Exemplo 1: Monitor de Preços Inteligente
Objetivo: Alertar quando preço de produto cai abaixo de valor específico
JSON para Importar
{
"name": "Monitor de Preços com Alerta de Queda",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "schedule_1",
"type": "schedule",
"position": { "x": 300, "y": 100 },
"data": {
"label": "A cada 30 minutos",
"parameters": {
"cron": "*/30 * * * *"
}
}
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Produtos Monitorados",
"parameters": {
"variableName": "produtos",
"value": [
{
"nome": "iPhone 15 Pro",
"url": "https://www.amazon.com.br/dp/B0CXXXXXXXXX",
"preco_alvo": 7000,
"seletor_preco": ".a-price-whole"
},
{
"nome": "MacBook Pro M3",
"url": "https://www.amazon.com.br/dp/B0CYYYYYYYYY",
"preco_alvo": 15000,
"seletor_preco": ".a-price-whole"
}
]
}
}
},
{
"id": "loop_1",
"type": "loop",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Cada Produto",
"parameters": {
"items": "{{produtos}}",
"itemVariable": "produto"
}
}
},
{
"id": "scraper_1",
"type": "web_scraper",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Monitor Preço",
"parameters": {
"operation": "monitor",
"url": "{{produto.url}}",
"mode": "manual",
"selectors": "{{produto.seletor_preco}}",
"monitorInterval": 30,
"saveHistory": true
}
}
},
{
"id": "variable_2",
"type": "variable",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "Extrair Preço",
"parameters": {
"variableName": "preco_atual",
"value": "{{parseFloat(scraper_1.data.current.text.replace('R$', '').replace('.', '').replace(',', '.'))}}"
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 1300, "y": 100 },
"data": {
"label": "Preço Caiu?",
"parameters": {
"condition": "{{scraper_1.data.hasChanged && preco_atual <= produto.preco_alvo}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 1500, "y": 50 },
"data": {
"label": "Alerta Oportunidade",
"parameters": {
"message": "🎯 OPORTUNIDADE! Preço caiu!\n\nProduto: {{produto.nome}}\nPreço anterior: R$ {{scraper_1.data.previous.text}}\nPreço atual: R$ {{scraper_1.data.current.text}}\nMeta: R$ {{produto.preco_alvo}}\n\nLink: {{produto.url}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "schedule_1" },
{ "source": "schedule_1", "target": "variable_1" },
{ "source": "variable_1", "target": "loop_1" },
{ "source": "loop_1", "target": "scraper_1" },
{ "source": "scraper_1", "target": "variable_2" },
{ "source": "variable_2", "target": "condition_1" },
{ "source": "condition_1", "target": "message_1", "label": "true" },
{ "source": "condition_1", "target": "end_1", "label": "false" },
{ "source": "message_1", "target": "end_1" }
]
}
Saída esperada:
Sistema: 🎯 OPORTUNIDADE! Preço caiu!
Produto: iPhone 15 Pro
Preço anterior: R$ 7.499,00
Preço atual: R$ 6.999,00
Meta: R$ 7.000,00
Link: https://www.amazon.com.br/dp/B0CXXXXXXXXX
Exemplo 2: Monitor de Vagas de Emprego
Objetivo: Detectar quando novas vagas são publicadas em site de RH
JSON para Importar
{
"name": "Detector de Novas Vagas",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "schedule_1",
"type": "schedule",
"position": { "x": 300, "y": 100 },
"data": {
"label": "A cada hora",
"parameters": {
"cron": "0 * * * *"
}
}
},
{
"id": "scraper_1",
"type": "web_scraper",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Monitor Vagas",
"parameters": {
"operation": "monitor",
"url": "https://careers.company.com/jobs?location=brazil&department=engineering",
"mode": "manual",
"selectors": {
"vagas": ".job-listing",
"titulos": ".job-title",
"localizacoes": ".job-location"
},
"ignoreSelectors": [".apply-date", ".views-count"],
"changeThreshold": 0.01,
"compareMethod": "text"
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Novas Vagas?",
"parameters": {
"condition": "{{scraper_1.data.hasChanged}}"
}
}
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 900, "y": 50 },
"data": {
"label": "Analisar Mudanças",
"parameters": {
"variableName": "mudancas_detectadas",
"value": "{{scraper_1.data.changes.textDiff}}"
}
}
},
{
"id": "ai_1",
"type": "ai",
"position": { "x": 1100, "y": 50 },
"data": {
"label": "Extrair Novas Vagas",
"parameters": {
"prompt": "Analise as mudanças detectadas e extraia apenas as NOVAS vagas que foram adicionadas. Retorne em formato JSON array com: titulo, localizacao.\n\nMudanças detectadas:\n{{mudancas_detectadas}}",
"model": "gpt-4",
"variableName": "novas_vagas"
}
}
},
{
"id": "loop_1",
"type": "loop",
"position": { "x": 1300, "y": 50 },
"data": {
"label": "Cada Nova Vaga",
"parameters": {
"items": "{{JSON.parse(novas_vagas)}}",
"itemVariable": "vaga"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 1500, "y": 50 },
"data": {
"label": "Alerta Vaga",
"parameters": {
"message": "💼 Nova vaga publicada!\n\nTítulo: {{vaga.titulo}}\nLocalização: {{vaga.localizacao}}\n\nAplicar: https://careers.company.com/jobs"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "schedule_1" },
{ "source": "schedule_1", "target": "scraper_1" },
{ "source": "scraper_1", "target": "condition_1" },
{ "source": "condition_1", "target": "variable_1", "label": "true" },
{ "source": "condition_1", "target": "end_1", "label": "false" },
{ "source": "variable_1", "target": "ai_1" },
{ "source": "ai_1", "target": "loop_1" },
{ "source": "loop_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Saída esperada:
Sistema: 💼 Nova vaga publicada!
Título: Senior Full Stack Developer
Localização: São Paulo, Brazil (Remote)
Aplicar: https://careers.company.com/jobs
Sistema: 💼 Nova vaga publicada!
Título: DevOps Engineer
Localização: Rio de Janeiro, Brazil
Aplicar: https://careers.company.com/jobs
Exemplo 3: Monitor de Disponibilidade de Produto
Objetivo: Alertar quando produto esgotado volta ao estoque
JSON para Importar
{
"name": "Monitor de Estoque - Alerta de Disponibilidade",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "schedule_1",
"type": "schedule",
"position": { "x": 300, "y": 100 },
"data": {
"label": "A cada 15 minutos",
"parameters": {
"cron": "*/15 * * * *"
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 500, "y": 100 },
"data": {
"label": "URL do Produto",
"parameters": {
"message": "Cole a URL do produto que deseja monitorar:",
"variableName": "product_url",
"saveToContext": true
}
}
},
{
"id": "scraper_1",
"type": "web_scraper",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Monitor Disponibilidade",
"parameters": {
"operation": "monitor",
"url": "{{product_url}}",
"mode": "manual",
"selectors": {
"titulo": "#productTitle",
"disponibilidade": "#availability span",
"preco": ".a-price-whole"
},
"monitorInterval": 15,
"compareMethod": "selector"
}
}
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Parsear Dados",
"parameters": {
"variableName": "produto",
"value": "{{JSON.parse(scraper_1.data.current.text)}}"
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "Voltou ao Estoque?",
"parameters": {
"condition": "{{scraper_1.data.hasChanged && (produto.disponibilidade.includes('Em estoque') || produto.disponibilidade.includes('In stock'))}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 1300, "y": 50 },
"data": {
"label": "Alerta Disponível",
"parameters": {
"message": "🎉 PRODUTO DISPONÍVEL!\n\nProduto: {{produto.titulo}}\nStatus: {{produto.disponibilidade}}\nPreço: R$ {{produto.preco}}\n\nCOMPRE AGORA: {{product_url}}"
}
}
},
{
"id": "whatsapp_1",
"type": "send_message",
"position": { "x": 1500, "y": 50 },
"data": {
"label": "Enviar WhatsApp",
"parameters": {
"to": "+5511999999999",
"message": "🎉 O produto {{produto.titulo}} VOLTOU AO ESTOQUE! Preço: R$ {{produto.preco}} - Compre: {{product_url}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "schedule_1" },
{ "source": "schedule_1", "target": "input_1" },
{ "source": "input_1", "target": "scraper_1" },
{ "source": "scraper_1", "target": "variable_1" },
{ "source": "variable_1", "target": "condition_1" },
{ "source": "condition_1", "target": "message_1", "label": "true" },
{ "source": "condition_1", "target": "end_1", "label": "false" },
{ "source": "message_1", "target": "whatsapp_1" },
{ "source": "whatsapp_1", "target": "end_1" }
]
}
Saída esperada:
Sistema: Cole a URL do produto que deseja monitorar:
Usuário: https://www.amazon.com.br/dp/B08N5WRWNW
[15 minutos depois]
Sistema: 🎉 PRODUTO DISPONÍVEL!
Produto: Echo Dot (4ª Geração)
Status: Em estoque
Preço: R$ 349,00
COMPRE AGORA: https://www.amazon.com.br/dp/B08N5WRWNW
[Enviado via WhatsApp para +5511999999999]
Resposta do Node
{
"success": true,
"data": {
"hasChanged": true,
"changes": {
"detected": true,
"percentageChanged": 0.12,
"textChanged": true,
"titleChanged": false,
"textDiff": "- Preço: R$ 3.499,00\n+ Preço: R$ 3.199,00"
},
"previous": {
"url": "https://example.com/product",
"title": "Produto XYZ",
"text": "Preço: R$ 3.499,00",
"timestamp": "2025-10-13T12:00:00.000Z",
"hash": "a8b9c0d1e2f3..."
},
"current": {
"url": "https://example.com/product",
"title": "Produto XYZ",
"text": "Preço: R$ 3.199,00",
"timestamp": "2025-10-13T12:30:00.000Z",
"hash": "f3e2d1c0b9a8..."
},
"timestamp": "2025-10-13T12:30:00.000Z"
},
"executionTime": 2456
}
Boas Práticas
✅ SIM:
- Use
ignoreSelectorspara elementos dinâmicos (timestamps, contadores, ads) - Defina
changeThresholdadequado para evitar alertas de mudanças irrelevantes - Combine com SCHEDULE para verificações periódicas automáticas
- Salve histórico para análise de tendências (saveHistory: true)
- Use método "hash" para detectar QUALQUER mudança em páginas legais
- Configure
monitorIntervalbalanceando detecção rápida x consumo de recursos - Use CONDITION para filtrar apenas mudanças relevantes
❌ NÃO:
- Monitor com intervalo muito curto (< 5 minutos) sem necessidade
- Ignorar elementos dinâmicos (causa falsos positivos)
- Esquecer de tratar primeira execução (alertOnFirstRun: false)
- Monitorar páginas que mudam conteúdo constantemente
- Não validar se mudança é realmente relevante antes de alertar
- Monitor sem limite de threshold (alerta para mudanças mínimas)
Dicas
💡 Dica 1: Combine monitor com AI para analisar se a mudança detectada é realmente importante antes de alertar.
💡 Dica 2: Use compareMethod: "hash" para páginas onde QUALQUER mudança importa (termos legais, configurações críticas).
💡 Dica 3: Para monitor de preços, extraia o número e compare numericamente ao invés de comparar texto.
💡 Dica 4: Salve estado anterior em banco de dados ao invés de memória para suportar restarts do sistema.
💡 Dica 5: Use changeThreshold de 0.05-0.10 (5-10%) para páginas normais, evitando alertas para mudanças triviais.
💡 Dica 6: Combine com WEBHOOK ou SEND_MESSAGE para notificações em tempo real quando mudanças ocorrem.
💡 Dica 7: Para produtos esgotados, monitore seletor de disponibilidade específico ao invés de página inteira.
Próximo Node
→ WEB_SCRAPER (SCRAPE) - Extração simples sem monitoramento → WEB_SCRAPER (SCREENSHOT) - Comparação visual de mudanças → SCHEDULE - Agendar verificações periódicas → CONDITION - Filtrar mudanças relevantes → AI - Analisar mudanças com inteligência artificial