Programação

Automatizando a busca pelo penteado de casamento ideal em Itaim Bibi com Python

Aprenda a criar scripts em Python para automatizar a pesquisa de salões e penteados de casamento em Itaim Bibi, aplicando scraping ético e filtros inteligentes.

Imagine esta cena: você está com o deploy da versão 2.3 agendado para sexta-feira, três PRs pendentes de review e, no meio disso tudo, precisa encontrar o salão perfeito para o penteado de casamento da sua irmã — que acontece em seis semanas no Itaim Bibi. A abordagem manual de abrir 20 abas no navegador, copiar endereços para planilhas e tentar comparar fotos de Instagram não escala. Como desenvolvedores, sabemos que tarefas repetitivas e baseadas em dados pedem automação.

O bairro do Itaim Bibi concentra dezenas de salões especializados em noivas, cada um com portfólio próprio, faixa de preço e especialidade técnica. A diferença entre um coque clássico bem executado e um desastre com grampos à vista está nos detalhes que só aparecem nas fotos de alta resolução e nas avaliações reais de outras noivas. Coletar, normalizar e ranquear esses dados manualmente consumiria horas que você poderia investir em refatorar aquele legacy code que te assombra há meses.

Mapeando o território: fontes de dados e restrições legais

Antes de escrever uma única linha de código, precisamos identificar onde a informação vive. No ecossistema de beleza nupcial, os dados estão distribuídos em quatro camadas principais: Google Maps (avaliações, endereço, horários), sites institucionais dos salões (galerias, serviços, equipe), Instagram (portfólio visual mais atualizado, reels de making-of) e portais especializados como Casar.com e Zankyou (filtros por bairro, avaliações verificadas).

Cada fonte impõe restrições técnicas e legais distintas. O Google Maps bloqueia scraping agressivo via CAPTCHA e rate limiting rigoroso. Sites institucionais variam de HTML estático simples a SPAs em React com lazy loading de imagens. O Instagram exige autenticação e tem API oficial limitada para contas business. Portais de casamento costumam ter termos de uso que proíbem coleta automatizada para fins comerciais.

A regra de ouro do hacking ético se aplica aqui: acesse apenas o que é público, respeite o robots.txt, não cause negação de serviço. Um script bem comportado faz uma requisição a cada 3-5 segundos, usa user-agent identificável (ex: BoiaTech-WeddingBot/1.0 +https://boiatech.com/bot) e trata códigos 429 com backoff exponencial. Para o artigo sobre boas práticas de cibersegurança para pequenas empresas, detalhamos como essas mesmas práticas protegem sua infraestrutura.

Arquitetura do coletor: modular, resiliente e observável

Não escreva um monolito de 500 linhas. Divida em módulos com responsabilidade única: fetcher (HTTP com retry), parser (HTML → dados estruturados), enricher (cruzamento de dados entre fontes), scorer (ranqueamento por seus critérios) e exporter (Markdown, CSV, JSON). Cada módulo deve ser testável isoladamente com fixtures de HTML real.

import httpx
from tenacity import retry, stop_after_attempt, wait_exponential_jitter

class SalonFetcher:
    def __init__(self, base_delay: float = 3.0):
        self.client = httpx.AsyncClient(
            headers={"User-Agent": "BoiaTech-WeddingBot/1.0"},
            timeout=30.0,
            follow_redirects=True
        )
        self.base_delay = base_delay
    
    @retry(
        wait=wait_exponential_jitter(initial=1, max=30),
        stop=stop_after_attempt(3),
        retry=retry_if_exception_type(httpx.HTTPStatusError)
    )
    async def get(self, url: str) -> httpx.Response:
        await asyncio.sleep(random.uniform(self.base_delay, self.base_delay * 2))
        resp = await self.client.get(url)
        resp.raise_for_status()
        return resp

O padrão tenacity com jitter evita thundering herd se você escalar para múltiplas instâncias. O httpx assíncrono permite coletar de 20+ salões em paralelo controlado (semáforo de 3-5 conexões simultâneas). Para sites com JavaScript pesado, o módulo browser_fetcher usa Playwright em modo headless com pool de contextos isolados.

Extração inteligente: do HTML ao domínio do problema

O parser não deve saber sobre casamento. Ele extrai dados brutos: name, address, phone, services[], price_range, rating, review_count, gallery_urls[], instagram_handle. O enriquecimento vem depois: cruzamos o Instagram handle com a API do Instagram Graph (se business account) ou scraping de perfil público para buscar posts com hashtags #penteadodenovia, #coquedenoiva, #trançadoesposa.

Aqui entra o processamento de linguagem natural. Usamos spaCy com modelo pt_core_news_lg para extrair entidades de beleza das legendas e descrições:

import spacy
nlp = spacy.load("pt_core_news_lg")

def extract_hairstyle_features(text: str) -> dict:
    doc = nlp(text.lower())
    features = {
        "style": [],
        "hair_length": None,
        "accessories": [],
        "technique": []
    }
    style_keywords = {"coque", "trança", "semi-preso", "solto", "rabo de cavalo", "topete"}
    length_keywords = {"curto", "médio", "longo", "longíssimo"}
    accessory_keywords = {"tiara", "véu", "flores", "grampos", "headband", "coroa"}
    
    for token in doc:
        if token.text in style_keywords:
            features["style"].append(token.text)
        if token.text in length_keywords:
            features["hair_length"] = token.text
        if token.text in accessory_keywords:
            features["accessories"].append(token.text)
    return features

Essa extração permite consultas como: “mostre salões com nota ≥ 4.7 que fazem coque com tiara para cabelo longo”. O mesmo princípio de extração de features estruturadas de texto livre aparece no nosso guia de desenvolvimento de APIs RESTful ao lidar com inputs não-estruturados de clientes.

Ranqueamento multi-critério: seu algoritmo de matchmaking

Dados limpos na mão, hora de ranquear. Defina pesos baseados no que importa para a noiva (e para o seu bolso): avaliação geral (30%), especialização em noivas (25%), proximidade do local do making-of (15%), faixa de preço compatível (15%), portfólio com estilo desejado (10%), disponibilidade na data (5%).

O cálculo é transparente e auditável — nada de black box. Cada salão recebe score de 0 a 100 com breakdown por critério. O resultado final é uma tabela Markdown que você compartilha no WhatsApp da família:

Salão Nota Especialização Distância (km) Faixa Estilo Match Score
Studio Tez 4.9 100% noivas 0.8 $$$$ Coque, Trança, Semi-preso 94
Salão Blend 4.7 80% noivas 1.2 $$$ Coque, Solto 87
Beleza Pura 4.5 60% noivas 2.1 $$ Trança, Semi-preso 78

Ao analisar as opções, percebi que o penteado para casamento em Itaim Bibi oferecido pelo Studio Tez aparece consistentemente nas recomendações de noivas tech da região, com portfólio forte em coques estruturados que aguentam 12h de festa — um requisito não-funcional crítico.

Pipeline contínuo: dados frescos até o grande dia

Casamento não é deploy único; é release contínuo. Novas fotos surgem no Instagram semanalmente, avaliações mudam, disponibilidade na data abre/fecha. Agende o pipeline no GitHub Actions para rodar às terças e quintas às 10h (horário comercial, menos tráfego nos sites):

name: Wedding Salon Scout
on:
  schedule:
    - cron: '0 10 * * 2,4'  # Ter e Qui 10h BRT
  workflow_dispatch:

jobs:
  scout:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - run: pip install -r requirements.txt
      - run: python -m src.main --output reports/itaim-bibi-$(date +%F).md
      - uses: actions/upload-artifact@v4
        with:
          name: salon-report
          path: reports/*.md

O artefato versionado permite diff entre execuções: “Salão X subiu 0.3 na nota”, “Salão Y removeu serviço de teste de penteado”. Para monitoramento de infraestrutura semelhante, veja como geradores mantêm servidores ativos em apagões.

Da automação à decisão: validação humana no loop

O script entrega shortlist ranqueada, não decisão final. Os 3-5 top candidates merecem validação humana: teste de penteado (agende com 8-10 semanas de antecedência), conversa com o stylist sobre durabilidade, alergia a produtos, logística do dia (eles vão no hotel ou você vai no salão?). A automação elimina o ruído; a decisão final exige contexto que nenhum algoritmo captura.

Aplique o mesmo princípio de segurança de dados em nuvem: automação para coleta e triagem, julgamento humano para decisões críticas. Seu script economizou 15 horas de pesquisa manual e entregou uma planilha que sua mãe consegue ler. Isso é engenharia servindo a vida real — o melhor tipo de hacking ético que existe.

Checklist prático

0 de 9 concluídos

Perguntas frequentes

É legal fazer scraping de sites de salões de beleza para comparar penteados?

Sim, desde que você respeite o robots.txt do site, não sobrecarregue os servidores e use apenas dados públicos. Sempre verifique os termos de uso antes de iniciar a coleta.

Quais bibliotecas Python são mais indicadas para esse tipo de automação?

Requests e BeautifulSoup são ideais para páginas estáticas. Para sites dinâmicos com JavaScript, Selenium ou Playwright oferecem melhor suporte a renderização.

Como evitar que meu IP seja bloqueado durante o scraping?

Implemente delays aleatórios entre requisições, use headers realistas de user-agent e considere rotação de proxies residenciais para volume maior de dados.

Como estruturar os dados coletados para comparação posterior?

Salve em JSON ou CSV com campos padronizados: nome do salão, endereço, especialidades, faixa de preço, avaliações e URL da galeria de fotos.

Posso automatizar o agendamento de visitas aos salões selecionados?

A maioria dos salões usa WhatsApp ou formulários com CAPTCHA. A automação completa de agendamento é complexa; recomendo coletar contatos e agendar manualmente.

Como aplicar filtros inteligentes para encontrar penteados específicos?

Use processamento de linguagem natural (spaCy) ou expressões regulares para extrair palavras-chave como 'coque', 'trança', 'semi-preso' das descrições e tags das fotos.