diff --git a/.gitignore b/.gitignore index aaea57d..4b3b1ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,25 @@ -dfimoveis_data \ No newline at end of file +# Banco e arquivos transitórios +*.sqlite +*.sqlite3 +*.db +*.sqlite-wal +*.sqlite-shm + +# Dados coletados +/dfimoveis_data/photos/ +/dfimoveis_data/raw/ +/dfimoveis_data/browser-profile/ + +# Derivações grandes +/data/derived/ +/exports/ + +# Python +__pycache__/ +*.py[cod] +.venv/ + +# Segredos e sessões +.env +.env.* +*.cookies.json diff --git a/AGENTS.md b/AGENTS.md index 870de41..10a9d3a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,191 +1,200 @@ # AGENTS.md — Busca de Imóveis DF -## Finalidade +## Missão -Este repositório apoia a coleta, organização e análise histórica de anúncios imobiliários do Distrito Federal para uma decisão residencial de longo prazo. +Apoiar uma decisão de compra residencial de longo prazo no Distrito Federal usando o banco histórico de anúncios, as fotografias e os critérios pessoais consolidados do usuário. -Antes de trabalhar no projeto, leia integralmente: +O trabalho deve ser cético, reproduzível e orientado a evitar uma compra ruim. Não maximizar apenas preço por metro quadrado, valorização ou número de atributos anunciados. +## Leitura obrigatória + +Antes de analisar imóveis ou alterar scripts, leia: + +- `docs/CURRENT_STATE.md` - `docs/PROJECT_CONTEXT.md` +- `docs/LOCATION_CRITERIA.md` - `docs/PROPERTY_CRITERIA.md` +- `docs/FINANCIAL_STRATEGY.md` +- `docs/SCRAPER_OPERATIONS.md` - `docs/DATA_MODEL.md` - `docs/ANALYSIS_RULES.md` -Esses documentos são a referência operacional do projeto. Quando houver conflito: +Quando houver conflito, use esta precedência: -1. uma instrução explícita e recente do usuário prevalece; -2. depois, prevalecem estes documentos; -3. por último, hipóteses inferidas a partir dos dados. +1. instrução explícita e recente do usuário; +2. `docs/CURRENT_STATE.md`; +3. documento especializado do tema; +4. snapshot ou relatório datado; +5. contexto histórico e inferências. -Nunca trate uma hipótese como preferência confirmada. +Nunca transforme inferência, relato de corretor, percepção de morador ou padrão do banco em preferência confirmada. -Para auxiliar no entendimento e contexto, as plantas das casas dos Jardins Mangueiral estão em: +--- -- `resources/plans` +## Prioridade regional vigente -Para auxiliar no entendimento e contexto, foram feitas capturas dos mapas dos Jardins Mangueiral, que foram salvas na em: +- **Prioridade principal:** Jardins Mangueiral. +- **Alternativa secundária e oportunística:** Cruzeiro, especialmente Cruzeiro Novo. -- `resources/maps` +O ranking interno de quadras do Cruzeiro continua sendo usado para avaliar apartamentos concretos, mas não torna o Cruzeiro prioritário sobre o Mangueiral. --- -## Banco de dados +## Regras pessoais obrigatórias -O banco principal deve ser tratado como **estritamente somente leitura**. +### Jardins Mangueiral -### Regras obrigatórias +- Considerar somente casas com **planta original de três quartos**. +- Excluir plantas originalmente de dois quartos, mesmo que tenham sido adaptadas. +- Não penalizar automaticamente o fechamento do quintal. +- Avaliar se a conversão cria espaço social útil, iluminado, ventilado e sem redundância funcional. +- Usar a hierarquia de QCs de `LOCATION_CRITERIA.md`, sem ignorar a posição exata da casa. +- Avaliar explicitamente ruído de vizinhos, animais, música, áreas sociais, ruas e equipamentos comuns. +- Dar preferência a casas reformadas, com bom espaço na cozinha. -- Nunca execute `INSERT`, `UPDATE`, `DELETE`, `DROP`, `ALTER`, `CREATE`, `REPLACE`, `VACUUM`, `REINDEX`, `ATTACH` ou comandos equivalentes contra o banco original. -- Não substitua, mova, compacte, migre ou renomeie o arquivo original. -- Não remova arquivos `-wal` ou `-shm` sem uma instrução explícita. -- Não execute scripts de scraping contra o banco durante uma análise sem autorização. -- Use `LIMIT` em consultas exploratórias. -- Não imprima tabelas inteiras no terminal. -- Prefira agregações, amostras pequenas e exportações derivadas. -- Salve resultados em `reports/`, `exports/` ou `data/derived/`. -- Nunca grave resultados derivados dentro do banco original. -- Antes de qualquer análise, confirme o caminho do banco e abra-o em modo somente leitura. +### Cruzeiro -### Abertura recomendada em Python +- Tratar como oportunidade secundária. +- Usar o ranking interno Ouro/Prata/Bronze de `LOCATION_CRITERIA.md`. +- Uma unidade fora da faixa superior pode vencer pela combinação de reforma, silêncio, planta, andar, elevador, garagem e preço. +- Ausência de elevador e garagem é concessão relevante. +- Confirmar se os três quartos são utilizáveis e coerentes com a planta. +- Inspecionar sistemas antigos, condomínio, fachada, prumadas, elétrica, hidráulica e obras previstas. -```python -import sqlite3 +--- -DB_PATH = "data/imoveis.sqlite" +## Banco principal -connection = sqlite3.connect( - f"file:{DB_PATH}?mode=ro&immutable=1", - uri=True, -) -connection.execute("PRAGMA query_only = ON") +Caminho esperado: + +```text +dfimoveis_data/dfimoveis.sqlite3 ``` -Se o banco estiver sendo atualizado por outro processo, não use `immutable=1`; mantenha `mode=ro` e confirme a consistência do snapshot antes de analisar. +O banco original é **estritamente somente leitura durante análises**. -### Cliente de linha de comando +### Proibições -```bash -sqlite3 -readonly data/imoveis.sqlite -``` +Nunca executar contra o banco original: ---- +- `INSERT` +- `UPDATE` +- `DELETE` +- `DROP` +- `ALTER` +- `CREATE` +- `REPLACE` +- `VACUUM` +- `REINDEX` +- `ATTACH` -## Fluxo inicial obrigatório +Não mover, substituir, compactar, migrar ou renomear o banco sem instrução explícita. Não remover arquivos `-wal` ou `-shm` arbitrariamente. -Ao iniciar uma nova tarefa de análise: +### Abertura recomendada -1. Identifique o arquivo SQLite correto e seu tamanho. -2. Leia `sqlite_master` para listar tabelas, views, índices e triggers. -3. Examine o esquema real antes de escrever consultas analíticas. -4. Conte registros por tabela. -5. Identifique campos de data, preço, área, quartos, localização, URL, anunciante e identificadores. -6. Verifique valores nulos, duplicidades, formatos inconsistentes e possíveis quebras de coleta. -7. Descubra se os dados representam: - - anúncios; - - imóveis físicos; - - observações históricas do mesmo anúncio; - - execuções do scraper. -8. Documente qualquer ambiguidade antes de produzir conclusões. +```python +import sqlite3 -Não presuma que o modelo lógico descrito em `docs/DATA_MODEL.md` já existe fisicamente. +DB_PATH = "dfimoveis_data/dfimoveis.sqlite3" +connection = sqlite3.connect(f"file:{DB_PATH}?mode=ro", uri=True) +connection.execute("PRAGMA query_only = ON") +``` + +Use `immutable=1` somente em cópia ou snapshot que não esteja sendo atualizado pelo scraper. --- -## Princípios de análise - -- Diferencie sempre **anúncio**, **imóvel físico** e **observação histórica**. -- Um mesmo imóvel pode aparecer em vários anúncios, portais, corretores ou datas. -- Um mesmo anúncio pode mudar de preço, descrição, área informada ou status. -- Preço anunciado não é preço efetivamente negociado. -- Ausência de anúncio não prova venda. -- Remoção de anúncio não prova fechamento de negócio. -- Campo preenchido pelo anunciante não deve ser considerado confiável sem validação. -- Não calcule preço por metro quadrado quando a área não for comparável ou confiável. -- Não misture área privativa, útil, construída e total sem separar os conceitos. -- Não compare períodos sem verificar mudanças no universo coletado. -- Não compare regiões sem controlar tipologia, quartos, área, garagem, estado e padrão do imóvel. -- Sempre informe tamanho da amostra, cobertura temporal, filtros e limitações. -- Prefira mediana, percentis e intervalos interquartis a médias isoladas. -- Mostre a sensibilidade das conclusões a outliers, duplicidades e dados ausentes. +## Separação entre scraper e análise + +- Não executar coleta e análise pesada simultaneamente no mesmo arquivo SQLite sem avaliar bloqueios e consistência. +- Para análise longa, preferir uma cópia/snapshot consistente ou conexão read-only. +- Resultados derivados devem ir para `reports/`, `exports/` ou `data/derived/`. +- Nunca gravar rankings, notas ou tabelas derivadas dentro do banco original sem autorização. --- -## Segurança e desempenho +## Fluxo analítico obrigatório -- Nunca exponha credenciais, cookies, tokens, chaves, sessões ou dados pessoais em relatórios. -- Não envie o banco ou grandes amostras para serviços externos sem autorização explícita. -- Não tente contornar mecanismos de proteção de sites. -- Respeite limites de requisição, termos aplicáveis e regras definidas para o scraper. -- Evite consultas que façam varreduras desnecessárias repetidas em tabelas grandes. -- Use `EXPLAIN QUERY PLAN` em consultas lentas. -- Sugira índices apenas como recomendação; não os crie no banco original. -- Para transformações pesadas, crie um banco derivado ou arquivos Parquet/CSV separados. +0. Verificar se a primeira foto do anúncio não demonstra que ele foi vendido. +1. Confirmar o snapshot e a cobertura temporal. +2. Ler o esquema real. +3. Identificar anúncios, observações históricas, fotos e execuções de coleta. +4. Verificar falhas de coleta e mudanças do scraper. +5. Separar anúncio, observação e imóvel físico provável. +6. Deduplicar republicações sem apagar registros originais. +7. Auditar a primeira foto e a descrição para “VENDIDO”, “negócio fechado” ou equivalente. +8. Colocar inconsistências em quarentena, sem exclusão silenciosa. +9. Avaliar fotografias; CSV isolado não é evidência suficiente para planta e conservação. +10. Registrar amostra, filtros, exclusões, limitações e método. --- -## Código +## Regras analíticas essenciais -- Escreva scripts reproduzíveis, parametrizados e idempotentes. -- Use caminhos relativos ao repositório. -- Evite constantes escondidas. -- Registre os filtros e premissas usados. -- Inclua tratamento de erros. -- Use consultas SQL parametrizadas. -- Adicione testes para regras de normalização, deduplicação e cálculo. -- Não altere arquivos sem relação com a tarefa. -- Não faça refatorações amplas sem necessidade. -- Não invente significado para colunas pouco claras; documente a dúvida. +- Preço anunciado não é preço negociado. +- Desaparecimento do anúncio não prova venda. +- Selo de vendido é evidência operacional, não prova registral. +- Não misturar área privativa, útil, construída, total e terreno. +- Não usar preço por m² quando a área não for comparável ou confiável. +- Não multiplicar republicações visualmente equivalentes. +- Não considerar “reformado” como prova de renovação elétrica, hidráulica ou estrutural. +- Não atribuir causalidade à QC ou quadra sem controlar tipologia e qualidade. +- Não inferir liquidez com uma janela curta de coleta. +- Rankings servem para ordenar investigação e visitas, não para automatizar a compra. --- -## Saídas esperadas +## Finanças -Relatórios analíticos devem, sempre que aplicável, conter: +Antes de recomendar compra ou preço máximo, leia `FINANCIAL_STRATEGY.md`. -1. pergunta respondida; -2. período e universo analisados; -3. filtros e exclusões; -4. tamanho da amostra; -5. método de deduplicação; -6. qualidade dos dados; -7. resultados; -8. limitações; -9. implicações para a decisão de compra; -10. consultas ou scripts usados para reproduzir o resultado. +Regras fixas: -Use gráficos apenas quando eles melhorarem a interpretação. Todo gráfico deve ter título, unidade, período, tamanho da amostra e definição da métrica. +- preservar pelo menos R$ 50.000 de reserva líquida após compra, custos e adequações; +- não tratar FGTS como reserva de emergência; +- excluir Pró-Cotista e MCMV Faixa 4 das simulações atuais; +- distinguir entrada, custos de compra, reforma, reserva e amortizações futuras; +- comparar financiamento, consórcio e aluguel com premissas datadas; +- não usar taxas antigas como atuais; +- incorporar fatores psicológicos sem convertê-los em justificativa para um imóvel inadequado. --- -## Contexto imobiliário prioritário +## Código e relatórios -As regiões prioritárias são: +- Escrever scripts reproduzíveis, parametrizados e idempotentes. +- Usar SQL parametrizado. +- Não imprimir milhares de linhas no terminal. +- Usar `LIMIT` na exploração. +- Usar `EXPLAIN QUERY PLAN` quando necessário. +- Sugerir índices sem criá-los no banco original. +- Preservar HTML bruto, fotos e dados originais. +- Toda conclusão deve separar fato, inferência, percepção e pendência. -1. Cruzeiro, especialmente Cruzeiro Novo; -2. Jardins Mangueiral. +Um relatório deve conter: -Não exclua outras regiões de uma análise exploratória quando forem úteis como referência, mas não desvie o projeto de seu objetivo principal sem instrução. - -Para Jardins Mangueiral: - -- considerar somente casas com planta original de três quartos; -- não penalizar automaticamente o fechamento do quintal; -- avaliar a funcionalidade real da conversão; -- considerar as preferências de QC descritas em `docs/PROPERTY_CRITERIA.md`; -- tratar relatos de moradores como evidência anedótica, não como fato conclusivo. +1. pergunta; +2. snapshot e período; +3. universo e amostra; +4. filtros e quarentenas; +5. método de deduplicação; +6. avaliação fotográfica; +7. resultados; +8. limitações; +9. implicação prática; +10. consultas e scripts para reprodução. --- ## Atualização do contexto -Não altere estes documentos apenas porque encontrou um padrão no banco. - -Atualize-os somente quando: +Atualizar os documentos somente quando: - o usuário corrigir uma premissa; - uma preferência for explicitamente confirmada; -- um valor financeiro for atualizado; -- uma regra metodológica for aprovada; -- o esquema real do projeto for consolidado. +- houver nova visita relevante; +- um snapshot substituir o anterior; +- uma regra financeira ou operacional mudar; +- o esquema real for documentado. -Ao atualizar uma premissa financeira, registre a data de referência e preserve o histórico em Git. +Registrar a mudança em `docs/CONTEXT_CHANGELOG.md` com data e motivo. diff --git a/README.md b/README.md index 0d38a33..cf17ae6 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,7 @@ Projeto pessoal para coletar, organizar e analisar anúncios imobiliários do Distrito Federal, com foco em uma decisão residencial de longo prazo. -As regiões prioritárias são: - -1. Cruzeiro, especialmente Cruzeiro Novo; -2. Jardins Mangueiral. +A prioridade operacional atual é o Jardins Mangueiral. O Cruzeiro permanece apenas como histórico e alternativa oportunística; sua URL foi removida da coleta corrente. O objetivo não é identificar simplesmente o menor preço anunciado. A análise considera funcionalidade, estado do imóvel, risco de reforma, localização, liquidez, custos de aquisição e manutenção e adequação à vida familiar. @@ -21,8 +18,8 @@ O repositório contém: Relatórios principais: -- [Top 10 — Cruzeiro Novo](reports/cruzeiro_top10/README.md) -- [Top 10 — Jardins Mangueiral](reports/mangueiral_top10/README.md) +- [Top 15 — Cruzeiro Novo](reports/cruzeiro_top15/README.md) +- [Top 15 — Jardins Mangueiral](reports/mangueiral_top15/README.md) - [Cruzeiro Novo x Jardins Mangueiral](reports/cruzeiro_vs_mangueiral/README.md) Os rankings são prioridades de investigação, não recomendações automáticas de compra nem estimativas de preço negociado. @@ -82,10 +79,7 @@ As ferramentas de similaridade fotográfica usam Pillow, incluído no arquivo de ## Configuração das buscas -O arquivo [search_list.txt](search_list.txt) contém uma URL completa por linha. Atualmente ele cobre: - -- apartamentos de três quartos no Cruzeiro Novo; -- casas anunciadas com três ou quatro quartos no Jardins Mangueiral. +O arquivo [search_list.txt](search_list.txt) contém uma URL completa por linha. Atualmente ele cobre casas anunciadas com três ou quatro quartos no Jardins Mangueiral. A busca do Mangueiral inclui quatro quartos para ampliar a coleta, mas esses imóveis são excluídos da análise regional. Mesmo três quartos anunciados não comprovam a planta original. @@ -138,6 +132,8 @@ dfimoveis_data/dfimoveis.sqlite3 Ele deve ser tratado como estritamente somente leitura durante análises. Nunca grave resultados derivados dentro dele. +O schema v2 preserva os valores brutos e oferece campos normalizados, quarentenas e visões auditáveis. Consultas de fotos devem preferir `v_primary_photos`; a migração idempotente está em `scripts/migrate_dfimoveis_schema_v2.py`. + Quando não houver processo de coleta e não existir WAL relevante: ```python @@ -180,15 +176,15 @@ reports// Extração tabular somente leitura: ```powershell -.\.venv-scraper\Scripts\python.exe .\reports\cruzeiro_top10\analysis.py -.\.venv-scraper\Scripts\python.exe .\reports\mangueiral_top10\analysis.py +.\.venv-scraper\Scripts\python.exe .\reports\cruzeiro_top15\analysis.py +.\.venv-scraper\Scripts\python.exe .\reports\mangueiral_top15\analysis.py ``` Triagem de possíveis duplicatas por similaridade visual: ```powershell -.\.venv-scraper\Scripts\python.exe .\reports\cruzeiro_top10\photo_similarity.py -.\.venv-scraper\Scripts\python.exe .\reports\mangueiral_top10\photo_similarity.py +.\.venv-scraper\Scripts\python.exe .\reports\cruzeiro_top15\photo_similarity.py +.\.venv-scraper\Scripts\python.exe .\reports\mangueiral_top15\photo_similarity.py ``` Similaridade de imagem é apenas um sinal para revisão humana, nunca prova automática de que dois anúncios representam o mesmo imóvel. diff --git a/__pycache__/dfimoveis_scraper.cpython-314.pyc b/__pycache__/dfimoveis_scraper.cpython-314.pyc index 97f8133..accb37e 100644 Binary files a/__pycache__/dfimoveis_scraper.cpython-314.pyc and b/__pycache__/dfimoveis_scraper.cpython-314.pyc differ diff --git a/dfimoveis_data/dfimoveis.sqlite3-shm b/dfimoveis_data/dfimoveis.sqlite3-shm new file mode 100644 index 0000000..fe9ac28 Binary files /dev/null and b/dfimoveis_data/dfimoveis.sqlite3-shm differ diff --git a/dfimoveis_data/dfimoveis.sqlite3-wal b/dfimoveis_data/dfimoveis.sqlite3-wal new file mode 100644 index 0000000..e69de29 diff --git a/dfimoveis_scraper.py b/dfimoveis_scraper.py index 27b697a..779d9ae 100644 --- a/dfimoveis_scraper.py +++ b/dfimoveis_scraper.py @@ -138,6 +138,44 @@ def safe_name(value: str) -> str: return re.sub(r"[^a-zA-Z0-9._-]+", "_", value).strip("_")[:120] or "unnamed" +def normalize_creci(value: str | None) -> str | None: + """Return only the registration number, preserving the raw portal value elsewhere.""" + if not value: + return None + match = re.search(r"(? str | None: + """Build a conservative location label without retaining portal UI text.""" + slug = urlparse(url).path.lower().replace("-", " ") + qc = re.search(r"\bqc\s*(\d{1,2})\b", slug) + street = re.search(r"\brua\s+([a-z0-9]+)\b", slug) + parts = ["Jardins Mangueiral"] if "jardins mangueiral" in slug else [] + if qc: + parts.append(f"QC {int(qc.group(1))}") + if street: + parts.append(f"Rua {street.group(1).upper()}") + if parts: + return " - ".join(parts) + # JSON-LD addresses are normally short. Reject known UI-contaminated fallbacks. + cleaned = clean_text(address) + return cleaned if cleaned and len(cleaned) <= 250 else None + + +def normalize_description_for_hash(value: str | None) -> str | None: + cleaned = clean_text(value) + if not cleaned: + return None + cleaned = re.sub( + r"(?:última|ultima)\s+atualiza(?:ção|cao)\s*:\s*\d{2}/\d{2}/\d{2,4}\s+\d{2}:\d{2}", + "última atualização: ", + cleaned, + flags=re.I, + ) + return cleaned + + @dataclasses.dataclass(slots=True) class Config: searches: list[str] @@ -245,35 +283,109 @@ class Database: status TEXT NOT NULL, stats_json TEXT NOT NULL DEFAULT '{}' ); + CREATE TABLE IF NOT EXISTS availability_observations ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + listing_id TEXT NOT NULL, + observed_at TEXT NOT NULL, + portal_active INTEGER, + classification TEXT NOT NULL, + source TEXT NOT NULL, + evidence TEXT, + run_id INTEGER, + FOREIGN KEY (listing_id) REFERENCES listings(listing_id), + FOREIGN KEY (run_id) REFERENCES crawl_runs(id) + ); + CREATE TABLE IF NOT EXISTS data_quality_issues ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + listing_id TEXT, + issue_code TEXT NOT NULL, + severity TEXT NOT NULL, + evidence TEXT, + first_seen_at TEXT NOT NULL, + last_seen_at TEXT NOT NULL, + status TEXT NOT NULL DEFAULT 'open', + UNIQUE(listing_id, issue_code), + FOREIGN KEY (listing_id) REFERENCES listings(listing_id) + ); + CREATE TABLE IF NOT EXISTS listing_change_events ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + listing_id TEXT NOT NULL, + captured_at TEXT NOT NULL, + event_type TEXT NOT NULL, + changes_json TEXT NOT NULL, + stable_content_hash TEXT NOT NULL, + run_id INTEGER, + FOREIGN KEY (listing_id) REFERENCES listings(listing_id), + FOREIGN KEY (run_id) REFERENCES crawl_runs(id) + ); + """ + ) + self._ensure_column("listings", "address_normalized", "TEXT") + self._ensure_column("listings", "neighborhood_normalized", "TEXT") + self._ensure_column("listings", "creci_normalized", "TEXT") + self._ensure_column("listings", "raw_content_hash", "TEXT") + self._ensure_column("listings", "stable_content_hash", "TEXT") + self._ensure_column("photos", "discovery_source", "TEXT") + self._ensure_column("photos", "is_primary_gallery", "INTEGER NOT NULL DEFAULT 1") + self._ensure_column("photos", "review_status", "TEXT NOT NULL DEFAULT 'unreviewed'") + self._ensure_column("crawl_runs", "searches_json", "TEXT NOT NULL DEFAULT '[]'") + self._ensure_column("crawl_runs", "config_json", "TEXT NOT NULL DEFAULT '{}'") + self._ensure_column("crawl_runs", "scope_complete", "INTEGER") + self.conn.execute("CREATE INDEX IF NOT EXISTS idx_listings_creci_normalized ON listings(creci_normalized)") + self.conn.execute("CREATE INDEX IF NOT EXISTS idx_listings_inactive_at ON listings(inactive_at)") + self.conn.execute("CREATE INDEX IF NOT EXISTS idx_photos_primary ON photos(listing_id,is_primary_gallery,ordinal)") + self.conn.execute("CREATE INDEX IF NOT EXISTS idx_change_events_listing ON listing_change_events(listing_id,captured_at)") + self.conn.executescript( + """ + CREATE VIEW IF NOT EXISTS v_primary_photos AS + SELECT * FROM photos WHERE is_primary_gallery=1; + CREATE VIEW IF NOT EXISTS v_open_data_quality_issues AS + SELECT * FROM data_quality_issues WHERE status='open'; + CREATE VIEW IF NOT EXISTS v_listing_current_availability AS + SELECT l.listing_id,l.url,(l.inactive_at IS NULL) AS portal_active,l.inactive_at, + a.classification,a.source,a.evidence,a.observed_at + FROM listings AS l + LEFT JOIN availability_observations AS a ON a.id=( + SELECT a2.id FROM availability_observations AS a2 + WHERE a2.listing_id=l.listing_id ORDER BY a2.observed_at DESC,a2.id DESC LIMIT 1 + ); """ ) self.conn.commit() - def start_run(self) -> int: + def _ensure_column(self, table: str, column: str, declaration: str) -> None: + existing = {row[1] for row in self.conn.execute(f"PRAGMA table_info({table})")} + if column not in existing: + self.conn.execute(f"ALTER TABLE {table} ADD COLUMN {column} {declaration}") + + def start_run(self, searches: list[str], config: dict[str, Any]) -> int: cur = self.conn.execute( - "INSERT INTO crawl_runs(started_at,status) VALUES(?,?)", (now_utc(), "running") + "INSERT INTO crawl_runs(started_at,status,searches_json,config_json,scope_complete) VALUES(?,?,?,?,?)", + (now_utc(), "running", json.dumps(searches, ensure_ascii=False), json.dumps(config, ensure_ascii=False), 0), ) self.conn.commit() return int(cur.lastrowid) def finish_run(self, run_id: int, status: str, stats: dict[str, Any]) -> None: self.conn.execute( - "UPDATE crawl_runs SET finished_at=?, status=?, stats_json=? WHERE id=?", - (now_utc(), status, json.dumps(stats, ensure_ascii=False), run_id), + "UPDATE crawl_runs SET finished_at=?, status=?, stats_json=?, scope_complete=? WHERE id=?", + (now_utc(), status, json.dumps(stats, ensure_ascii=False), int(status == "ok" and stats.get("details_failed", 0) == 0), run_id), ) self.conn.commit() - def upsert_listing(self, data: dict[str, Any], search_url: str) -> bool: + def upsert_listing(self, data: dict[str, Any], search_url: str, run_id: int | None = None) -> bool: ts = now_utc() existing = self.conn.execute( - "SELECT content_hash FROM listings WHERE listing_id=?", (data["listing_id"],) + "SELECT * FROM listings WHERE listing_id=?", (data["listing_id"],) ).fetchone() - changed = not existing or existing["content_hash"] != data["content_hash"] + changed = not existing or existing["stable_content_hash"] != data["stable_content_hash"] cols = [ "listing_id", "url", "title", "description", "transaction_type", "property_type", "price_brl", "condominium_brl", "iptu_brl", "area_m2", "bedrooms", "suites", "parking_spaces", "address", "neighborhood", "city", "state", "advertiser_name", - "advertiser_code", "creci", "latitude", "longitude", "published_at", "content_hash", + "advertiser_code", "creci", "address_normalized", "neighborhood_normalized", + "creci_normalized", "latitude", "longitude", "published_at", "content_hash", + "raw_content_hash", "stable_content_hash", "raw_html_path", "extra_json" ] values = [data.get(c) for c in cols] @@ -300,24 +412,64 @@ class Database: snapshot = {k: v for k, v in data.items() if k not in {"raw_html_path"}} self.conn.execute( "INSERT OR IGNORE INTO listing_history(listing_id,captured_at,content_hash,data_json) VALUES(?,?,?,?)", - (data["listing_id"], ts, data["content_hash"], json.dumps(snapshot, ensure_ascii=False)), + (data["listing_id"], ts, data["stable_content_hash"], json.dumps(snapshot, ensure_ascii=False)), ) + tracked = [ + "url", "title", "description", "transaction_type", "property_type", "price_brl", + "condominium_brl", "iptu_brl", "area_m2", "bedrooms", "suites", "parking_spaces", + "address_normalized", "neighborhood_normalized", "advertiser_name", "creci_normalized", + "latitude", "longitude", "published_at", + ] + changes = ( + {key: {"before": existing[key], "after": data.get(key)} for key in tracked if existing[key] != data.get(key)} + if existing else {"listing": {"before": None, "after": "created"}} + ) + event_type = "new_listing" if not existing else ("price_change" if "price_brl" in changes else "content_change") + self.conn.execute( + """INSERT INTO listing_change_events + (listing_id,captured_at,event_type,changes_json,stable_content_hash,run_id) + VALUES(?,?,?,?,?,?)""", + (data["listing_id"], ts, event_type, json.dumps(changes, ensure_ascii=False), data["stable_content_hash"], run_id), + ) + self._record_automatic_quality_issues(data, ts) self.conn.commit() return changed + def _record_automatic_quality_issues(self, data: dict[str, Any], ts: str) -> None: + checks: list[tuple[str, str, str]] = [] + if data.get("price_brl") and data["price_brl"] > 20_000_000: + checks.append(("implausible_price", "high", str(data["price_brl"]))) + if data.get("area_m2") and data["area_m2"] < 10: + checks.append(("implausible_area", "high", str(data["area_m2"]))) + description = (data.get("description") or "").lower() + if "procuro casa para comprar" in description: + checks.append(("source_mismatch_buyer_request", "high", "description declares a purchase request")) + if "quarto adaptado" in description or "escritório adaptado" in description: + checks.append(("adapted_room", "medium", "description mentions an adapted room")) + for code, severity, evidence in checks: + self.conn.execute( + """INSERT INTO data_quality_issues(listing_id,issue_code,severity,evidence,first_seen_at,last_seen_at) + VALUES(?,?,?,?,?,?) ON CONFLICT(listing_id,issue_code) DO UPDATE SET + severity=excluded.severity,evidence=excluded.evidence,last_seen_at=excluded.last_seen_at,status='open'""", + (data["listing_id"], code, severity, evidence, ts, ts), + ) + def upsert_photo(self, listing_id: str, ordinal: int, url: str, **meta: Any) -> None: ts = now_utc() self.conn.execute( """ - INSERT INTO photos(listing_id,ordinal,source_url,sha256,mime_type,bytes,local_path,first_seen_at,last_seen_at) - VALUES(?,?,?,?,?,?,?,?,?) + INSERT INTO photos(listing_id,ordinal,source_url,sha256,mime_type,bytes,local_path,first_seen_at,last_seen_at,discovery_source,is_primary_gallery,review_status) + VALUES(?,?,?,?,?,?,?,?,?,?,?,?) ON CONFLICT(listing_id,source_url) DO UPDATE SET ordinal=excluded.ordinal, sha256=COALESCE(excluded.sha256,photos.sha256), mime_type=COALESCE(excluded.mime_type,photos.mime_type), bytes=COALESCE(excluded.bytes,photos.bytes), - local_path=COALESCE(excluded.local_path,photos.local_path), last_seen_at=excluded.last_seen_at + local_path=COALESCE(excluded.local_path,photos.local_path), last_seen_at=excluded.last_seen_at, + discovery_source=COALESCE(excluded.discovery_source,photos.discovery_source), + is_primary_gallery=excluded.is_primary_gallery """, - (listing_id, ordinal, url, meta.get("sha256"), meta.get("mime_type"), meta.get("bytes"), meta.get("local_path"), ts, ts), + (listing_id, ordinal, url, meta.get("sha256"), meta.get("mime_type"), meta.get("bytes"), meta.get("local_path"), ts, ts, + meta.get("discovery_source", "listing_id_url"), int(meta.get("is_primary_gallery", True)), meta.get("review_status", "unreviewed")), ) self.conn.commit() @@ -329,7 +481,9 @@ class Database: def mark_inactive(self, search_url: str, seen_ids: set[str], run_started_at: str) -> int: rows = self.conn.execute( - "SELECT listing_id FROM listing_searches WHERE search_url=? AND last_seen_at < ?", + """SELECT s.listing_id FROM listing_searches AS s + JOIN listings AS l USING(listing_id) + WHERE s.search_url=? AND s.last_seen_at < ? AND l.inactive_at IS NULL""", (search_url, run_started_at), ).fetchall() stale = [r[0] for r in rows if r[0] not in seen_ids] @@ -926,8 +1080,14 @@ class Parser: for match in IMAGE_URL_RE.finditer(page_html.replace("\\/", "/")): image_urls[html.unescape(match.group(0))] = None - # Exclude common site chrome and tiny assets based on URL hints. - photos = [u for u in image_urls if not re.search(r"logo|favicon|sprite|icon|avatar|banner", u, re.I)] + # The portal renders recommendations on the same page. Only URLs whose + # /fotos// owner matches this listing belong to the primary gallery. + owner_re = re.compile(r"/fotos/(\d+)/", re.I) + photos = [] + for image_url in image_urls: + owner = owner_re.search(urlparse(image_url).path) + if owner and owner.group(1) == listing_id: + photos.append(image_url) data = { "listing_id": listing_id, @@ -956,8 +1116,35 @@ class Parser: "raw_html_path": raw_path, "extra_json": json.dumps({"json_ld": ld}, ensure_ascii=False), } - stable = {k: v for k, v in data.items() if k not in {"content_hash", "raw_html_path"}} - data["content_hash"] = hashlib.sha256(json.dumps(stable, sort_keys=True, ensure_ascii=False).encode()).hexdigest() + data["address_normalized"] = normalize_listing_address(data["url"], data["address"]) + data["neighborhood_normalized"] = "Jardins Mangueiral" if "jardins-mangueiral" in data["url"] else clean_text(data["neighborhood"]) + data["creci_normalized"] = normalize_creci(data["creci"]) + raw_payload = {k: v for k, v in data.items() if k not in {"content_hash", "raw_html_path"}} + data["raw_content_hash"] = hashlib.sha256(json.dumps(raw_payload, sort_keys=True, ensure_ascii=False).encode()).hexdigest() + stable_payload = { + "url": data["url"], + "title": data["title"], + "description": normalize_description_for_hash(data["description"]), + "transaction_type": data["transaction_type"], + "property_type": data["property_type"], + "price_brl": data["price_brl"], + "condominium_brl": data["condominium_brl"], + "iptu_brl": data["iptu_brl"], + "area_m2": data["area_m2"], + "bedrooms": data["bedrooms"], + "suites": data["suites"], + "parking_spaces": data["parking_spaces"], + "address_normalized": data["address_normalized"], + "neighborhood_normalized": data["neighborhood_normalized"], + "advertiser_name": data["advertiser_name"], + "creci_normalized": data["creci_normalized"], + "latitude": data["latitude"], + "longitude": data["longitude"], + "published_at": data["published_at"], + } + data["stable_content_hash"] = hashlib.sha256(json.dumps(stable_payload, sort_keys=True, ensure_ascii=False).encode()).hexdigest() + # Retain the legacy column for compatibility, but give it the stable meaning from schema v2 onward. + data["content_hash"] = data["stable_content_hash"] return data, photos @@ -1007,7 +1194,7 @@ class Scraper: page_html, body, final_url = await self.fetcher.get_html(url) raw_path = self.save_raw("listing", listing_id_from_url(url) or "unknown", body) if self.cfg.save_raw_html else None data, photos = Parser.detail(final_url, page_html, raw_path) - changed = self.db.upsert_listing(data, search_url) + changed = self.db.upsert_listing(data, search_url, self.run_id) self.stats["details_ok"] += 1 self.stats["changed"] += int(changed) logging.info("Listing %s: %s; %d photos", data["listing_id"], "changed" if changed else "unchanged", len(photos)) @@ -1049,7 +1236,18 @@ class Scraper: logging.exception("Failed photo for %s: %s", listing_id, url) async def run(self) -> dict[str, Any]: - run_id = self.db.start_run() + run_config = { + "max_pages": self.cfg.max_pages, + "concurrency": self.cfg.concurrency, + "photo_concurrency": self.cfg.photo_concurrency, + "download_photos": self.cfg.download_photos, + "save_raw_html": self.cfg.save_raw_html, + "use_playwright": self.cfg.use_playwright, + "browser_channel": self.cfg.browser_channel, + "attach_chrome": self.cfg.attach_chrome, + } + run_id = self.db.start_run(self.cfg.searches, run_config) + self.run_id = run_id status = "ok" try: for search_url in self.cfg.searches: @@ -1212,4 +1410,4 @@ def main() -> None: if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/docs/ACTUAL_SCHEMA.md b/docs/ACTUAL_SCHEMA.md index b80e3fe..6cd2b48 100644 --- a/docs/ACTUAL_SCHEMA.md +++ b/docs/ACTUAL_SCHEMA.md @@ -1,23 +1,24 @@ # Esquema físico do banco `dfimoveis.sqlite3` +> **Atualização de 22/07/2026:** as seções históricas deste documento descrevem o schema v1. A migração aditiva v2 descrita na seção final prevalece para consultas atuais. + ## 1. Escopo e identificação do snapshot -Este documento descreve o esquema observado em 13 de julho de 2026. Ele não altera o modelo conceitual de `docs/DATA_MODEL.md` e não atribui significado não comprovado às colunas. +Este documento descreve o esquema observado e revalidado em 21 de julho de 2026. Ele não altera o modelo conceitual de `docs/DATA_MODEL.md` e não atribui significado não comprovado às colunas. | Item | Valor | |---|---| | Caminho | `dfimoveis_data/dfimoveis.sqlite3` | -| Tamanho | 5.017.600 bytes | -| SHA-256 | `1ce3128b488c50c993d7328ac6e24b5905f083a7e04e3f636407eea1edd02b9d` | -| Modificação do arquivo | `2026-07-13 14:20:34.601285975 -03:00` | -| SQLite | 3.45.1 | +| Tamanho | 9.478.144 bytes | +| SHA-256 | `bfbbdd09e88f76afd917ebd981b848b9321aeb5fc0602f712645d33e1a5ea76c` | +| Data de referência | `2026-07-21` | | Codificação | UTF-8 | | `journal_mode` persistido | WAL | -| Páginas | 1.225 páginas de 4.096 bytes; `freelist_count = 0` | +| Páginas | 2.314 páginas de 4.096 bytes; `freelist_count = 2` | | `user_version` / `application_id` | 0 / 0 | -| Método de abertura | `sqlite3 -readonly` e URI `mode=ro&immutable=1`, sempre com `PRAGMA query_only = ON` | +| Método de abertura | URI `mode=ro`, `PRAGMA query_only = ON` e transação de leitura | -Não havia arquivo `-wal` ou `-shm` nem processo com o banco aberto na verificação inicial. Isso permitiu tratar o conteúdo como snapshot imutável. `PRAGMA quick_check` retornou `ok` e `PRAGMA foreign_key_check` não retornou violações. Na validação final, o cliente SQLite havia criado os sidecars de runtime `dfimoveis.sqlite3-shm` (32.768 bytes) e `dfimoveis.sqlite3-wal` (vazio), comportamento possível ao abrir em leitura um banco configurado em WAL. Eles não foram removidos. O arquivo principal manteve tamanho, `mtime` e SHA-256 idênticos. +Como este arquivo é atualizado pelo scraper, não foi usado `immutable=1`. `PRAGMA quick_check` retornou `ok` e `PRAGMA foreign_key_check` não retornou violações. Nenhum sidecar foi removido. ## 2. Visão geral @@ -72,21 +73,21 @@ erDiagram | Tabela | Linhas | Interpretação física | |---|---:|---| -| `crawl_runs` | 4 | Execuções do coletor | -| `listings` | 156 | Identidades de anúncios e seu estado corrente | -| `listing_history` | 156 | Estados distintos dos anúncios por hash | -| `listing_searches` | 156 | Vínculos entre anúncio e URL de busca | -| `photos` | 5.386 | Mídias associadas diretamente aos anúncios | +| `crawl_runs` | 20 | Execuções do coletor | +| `listings` | 161 | Identidades de anúncios e seu estado corrente | +| `listing_history` | 562 | Estados distintos dos anúncios por hash | +| `listing_searches` | 161 | Vínculos entre anúncio e URL de busca | +| `photos` | 7.363 | Mídias associadas diretamente aos anúncios | | `sqlite_sequence` | 2 | Sequências internas de tabelas `AUTOINCREMENT` | No snapshot avaliado: -- cada anúncio possui exatamente um registro em `listing_history`; - cada anúncio está ligado a exatamente uma URL de busca; -- cada anúncio possui de 5 a 61 linhas em `photos`; +- cada anúncio possui de 1 a 4 registros em `listing_history`; +- cada anúncio possui de 5 a 79 linhas em `photos`; - não há órfãos nas três relações com `listings`; -- os 156 hashes de `listing_history` coincidem com o hash corrente em `listings`; -- `captured_at` coincide com `first_seen_at` nos 156 anúncios. +- o hash corrente de cada anúncio possui registro correspondente no histórico; +- grande parte dos snapshots adicionais reflete instabilidade de campos contaminados, sobretudo `creci`, e não mudança imobiliária real. ## 3. Dicionário de tabelas @@ -99,10 +100,10 @@ Representa execuções técnicas do coletor. Não registra fonte, versão do scr | `id` | INTEGER | Não | PK, `AUTOINCREMENT` | Identificador da execução; a PK inteira atribui um valor quando omitido | | `started_at` | TEXT | Não | — | Início em ISO 8601, observado em UTC | | `finished_at` | TEXT | Sim | — | Término em ISO 8601 | -| `status` | TEXT | Não | — | Estado textual da execução; somente `ok` na amostra | +| `status` | TEXT | Não | — | Estado textual da execução; `ok` e `failed` foram observados | | `stats_json` | TEXT | Não | `'{}'` | Contadores técnicos em JSON | -As quatro estruturas JSON são válidas. As chaves presentes são `search_pages`, `listing_urls`, `details_ok`, `details_failed`, `changed`, `photos_ok`, `photos_failed` e `inactive`, todas inteiras. +As estruturas JSON observadas são válidas. Além das chaves originais, execuções recentes também registram `photos_skipped`. ### 3.2 `listings` @@ -219,20 +220,64 @@ As FKs de `listing_history`, `listing_searches` e `photos` apontam para `listing 1. `listing_id` identifica um **anúncio no portal**, não um imóvel físico. 2. Uma linha de `listing_history` é um **estado de conteúdo distinto**, não prova de que o anúncio foi observado somente uma vez. Observações idênticas são condensadas em `last_seen_at`. -3. O banco ainda não contém histórico suficiente para preços ou permanência: há um snapshot por anúncio e todos os anúncios têm `first_seen_at = last_seen_at`. +3. O banco ainda não contém histórico suficiente para liquidez: há quatro dias efetivos de observação e a maioria das transições é ruído de campos contaminados. 4. Anúncios diferentes com preço, área ou fotos semelhantes permanecem anúncios distintos. Não há chave de endereço/unidade nem tabela de candidatos físicos. 5. `area_m2` não deve ser usada para preço por m² até que o conceito de área seja validado por tipologia e fonte. 6. `bedrooms` é a quantidade anunciada. Ela não comprova a planta original de três quartos exigida para Jardins Mangueiral. -7. Datas com sufixo `+00:00` são tratadas como UTC. A cobertura observada é de um único dia. +7. Datas com sufixo `+00:00` são tratadas como UTC. A cobertura observada vai de 13 a 21/07/2026. 8. Os campos textuais contaminados devem ser reextraídos do HTML bruto em uma camada derivada; os valores atuais não devem ser silenciosamente normalizados como se fossem corretos. ## 7. Problemas conhecidos do snapshot -- 146 de 156 endereços têm mais de 300 caracteres; 154 de 156 bairros têm mais de 100 caracteres. Os dois bairros curtos também não formam valores confiáveis. +- 150 de 161 endereços têm mais de 300 caracteres; 159 de 161 bairros têm mais de 100 caracteres. - `city`, `state`, `latitude`, `longitude`, `published_at` e `advertiser_name` estão integralmente ausentes. -- 98 códigos de anunciante e 153 valores de CRECI são longos demais para o significado esperado, indicando extração contaminada. +- 99 códigos de anunciante e 157 valores de CRECI são longos demais para o significado esperado, indicando extração contaminada. - Há um preço de R$ 570.000.000 e uma área de 0,11 m², ambos candidatos fortes a erro de extração/escala. -- O JSON-LD reservado em `extra_json` é um array vazio em todos os anúncios e não oferece uma fonte estruturada alternativa no snapshot. -- Três downloads de foto falharam e deixaram linhas sem hash, MIME, tamanho e caminho local. -- Hashes de foto idênticos aparecem em muitos anúncios, inclusive um hash presente nos 156; isso demonstra a presença de ativos genéricos e impede usar igualdade de hash como prova isolada de imóvel duplicado. +- O JSON-LD reservado em `extra_json` é um array vazio em todos os 161 anúncios e não oferece uma fonte estruturada alternativa no snapshot. +- As 7.363 linhas de foto têm hash e caminho local preenchidos; isso não garante que toda imagem pertença ao imóvel. +- Hashes de foto idênticos aparecem em muitos anúncios; isso demonstra a presença de ativos genéricos e impede usar igualdade de hash como prova isolada de imóvel duplicado. +- Das 401 transições históricas, 398 alteram `creci`; somente três anúncios apresentam mudança real de preço. O histórico precisa de normalização antes de análises temporais. - Não há como ligar formalmente anúncio/snapshot a `crawl_runs`, nem distinguir por chave a fonte se uma segunda fonte for incorporada. + +--- + +## 12. Schema v2 — 22/07/2026 + +A migração foi autorizada explicitamente, executada após backup consistente e não removeu linhas ou colunas antigas. + +Contagens preservadas na migração: + +| Tabela legada | Linhas | +|---|---:| +| `listings` | 162 | +| `listing_searches` | 162 | +| `listing_history` | 637 | +| `photos` | 7.457 | +| `crawl_runs` | 21 | + +Novas colunas: + +- `listings`: `address_normalized`, `neighborhood_normalized`, `creci_normalized`, `raw_content_hash`, `stable_content_hash`; +- `photos`: `discovery_source`, `is_primary_gallery`, `review_status`; +- `crawl_runs`: `searches_json`, `config_json`, `scope_complete`. + +Novas tabelas: + +- `availability_observations`: evidência datada e sua fonte, sem converter selo visual em prova registral; +- `data_quality_issues`: quarentenas reversíveis, com severidade, evidência e estado; +- `listing_change_events`: eventos materiais produzidos pelo hash estável nas futuras coletas. + +Novas visões: + +- `v_primary_photos`; +- `v_open_data_quality_issues`; +- `v_listing_current_availability`. + +Auditoria inicial: + +- 3.521 fotos pertencem à galeria do próprio anúncio; +- 3.286 registros legados apontam para `/fotos//` e vieram de recomendações do portal; +- 650 registros restantes são ativos visuais do site ou URLs sem proprietário de anúncio; +- os 3.936 registros não primários foram preservados e marcados, não apagados; +- 15 anúncios foram normalizados para o CRECI `26903`; +- `PRAGMA quick_check` retornou `ok` após a migração. diff --git a/docs/ANALYSIS_RULES.md b/docs/ANALYSIS_RULES.md index 7bd3e70..7573507 100644 --- a/docs/ANALYSIS_RULES.md +++ b/docs/ANALYSIS_RULES.md @@ -1,490 +1,283 @@ # Regras de análise -## 1. Objetivo metodológico +## 1. Unidade de análise -Produzir análises reproduzíveis e úteis para decisão de compra, sem transformar dados de anúncios em uma falsa precisão de mercado. +Definir explicitamente: -Toda conclusão deve distinguir: - -- o que os dados mostram; -- o que foi inferido; -- o que permanece desconhecido; -- o que depende de visita, documentação ou negociação. - ---- - -## 2. Unidade de análise - -Definir antes de calcular: - -- anúncio único; -- snapshot de anúncio; +- anúncio; +- observação; - imóvel físico provável; -- imóvel físico confirmado; - região; -- tipologia; -- período. - -Não misturar unidades. - -Exemplo de erro: - -> Contar cada snapshot mensal como um imóvel diferente. - -Exemplo correto: +- período; +- snapshot. -> Para estoque histórico, usar um anúncio ativo por data; para oferta única, deduplicar anúncios e imóveis prováveis. +Não contar cada observação como imóvel novo. --- -## 3. Cobertura e consistência temporal - -Antes de comparar meses: +## 2. Cobertura -- verificar dias coletados; -- verificar fontes ativas; -- verificar falhas; -- verificar mudanças do scraper; -- verificar novos filtros; -- verificar alterações no site; -- verificar interrupções; -- verificar mudanças de campos. +Antes de comparar períodos: -Uma queda no número de anúncios pode ser falha de coleta. +- conferir dias coletados; +- falhas e 403; +- fontes e pesquisas ativas; +- mudanças do scraper; +- cobertura de fotos; +- inatividade artificial. -Relatórios temporais devem exibir cobertura. +O snapshot de 13–21/07/2026 não permite inferir liquidez. --- -## 4. Limpeza +## 3. Limpeza -### 4.1 Preços inválidos +### Preço -Identificar: +Colocar em quarentena: - zero; -- preço mensal; -- preço de aluguel em anúncio de venda; -- valor parcial; +- preço de aluguel em venda; - erro de escala; -- preço simbólico; -- preço por fração; -- moeda incorreta; -- preço inconsistente com descrição. +- valor simbólico; +- valor incompatível com descrição; +- casos como R$ 570 milhões quando o contexto sugere erro. -Não remover silenciosamente. Registrar regra e contagem. +### Área -### 4.2 Áreas inválidas +Verificar: -Identificar: +- conceito da área; +- casa ampliada; +- terreno versus área construída; +- erro de decimal; +- divergência entre campos e descrição. -- zero; -- área total usada como privativa; -- área do terreno; -- área multiplicada; -- vírgula decimal interpretada incorretamente; -- área do condomínio; -- área incompatível com a tipologia. - -### 4.3 Quartos e tipologia +### Planta -Verificar divergências entre: +Cruzar: - título; - campos estruturados; - descrição; -- planta; -- fotografias; -- tipologia original. - -Para Jardins Mangueiral, não aceitar tipologia anunciada como prova da planta original. +- fotos; +- planta padrão; +- endereço e implantação. --- -## 5. Preço por metro quadrado - -Calcular somente quando: - -- o preço é válido; -- a área é válida; -- a área representa conceito comparável; -- o imóvel pertence a uma tipologia comparável. - -Registrar a área usada. +## 4. Preço por metro quadrado -Não comparar diretamente: +Não usar como métrica principal no estado atual do banco. -- área privativa com área total; -- casa com apartamento; -- imóvel reformado com imóvel para reforma sem controle; -- dois quartos com três quartos apenas pela média regional; -- cobertura com unidade padrão; -- casa ampliada com planta original sem ajustar a área. +Somente calcular quando: -Estatísticas mínimas: +- preço é válido; +- área é validada e comparável; +- tipologia é homogênea; +- ampliação é tratada corretamente. -- número de observações; -- mediana; -- percentil 25; -- percentil 75; -- mínimo e máximo após validação; -- proporção excluída. +Os rankings de 21/07/2026 não usaram preço por m² porque os campos de área não eram uniformes. --- -## 6. Outliers +## 5. Fotografias -Não excluir outliers apenas porque são extremos. +A avaliação deve incluir: -Investigar se representam: - -- erro; -- imóvel premium; -- reforma; -- venda urgente; -- leilão; -- área incorreta; -- anúncio duplicado; -- preço desatualizado; -- unidade atípica. +- primeira foto; +- galeria completa; +- coerência de planta; +- condição aparente; +- iluminação e ventilação; +- qualidade da reforma; +- ampliação e cobertura; +- duplicatas visuais; +- selo de vendido. -Apresentar resultados com e sem outliers quando a conclusão mudar. +Registrar limitações quando a galeria for curta ou não mostrar toda a planta. -Métodos permitidos: +--- -- IQR; -- MAD; -- limites específicos por tipologia; -- inspeção manual; -- modelos robustos. +## 6. Duplicatas -Não usar corte automático sem explicar. +- identificar grupos de republicação; +- contar como um imóvel provável no ranking; +- preservar todos os anúncios no histórico; +- definir anúncio de referência; +- registrar divergências de endereço, área e preço; +- testar sensibilidade quando a deduplicação for incerta. --- -## 7. Duplicidades +## 7. Ranking de imóveis + +O ranking serve para ordenar investigação. -Relatar: +Critérios comuns: -- duplicatas dentro da mesma fonte; -- duplicatas entre fontes; -- snapshots repetidos; -- imóveis anunciados por vários corretores; -- anúncios republicados com novo identificador. +- quartos utilizáveis; +- planta; +- funcionalidade; +- condição aparente; +- iluminação e ventilação; +- localização; +- acessibilidade; +- elevador; +- garagem; +- custo; +- regularidade; +- qualidade da evidência. -Para preço de oferta atual, escolher uma regra explícita, por exemplo: +### Mangueiral -- menor preço vigente por imóvel provável; -- anúncio mais recente; -- anúncio primário; -- mediana entre anúncios do mesmo imóvel. +Adicionar: -Testar sensibilidade da conclusão à regra. +- planta original de três quartos; +- QC; +- conversão do quintal; +- calor e ventilação; +- cobertura, drenagem e impermeabilização; +- regularidade da ampliação; +- ruído de vizinhos e áreas comuns. + +Aplicar também as preferências confirmadas: + +- favorecer cozinha funcional e gourmet conectado ao uso cotidiano; +- favorecer conservação e mudança com poucas intervenções; +- tratar piscina, jacuzzi e banheira como incompatibilidades funcionais, não amenidades positivas; +- penalizar cubas de vidro, marcenaria degradada, gourmet isolado e área externa sem uso coerente; +- testar calor e ventilação em fechamentos envidraçados; +- distinguir nota dada diretamente pelo usuário de aderência inferida pelo analista; +- quando novo feedback alterar o funil de entrada, reprocessar o universo completo em vez de apenas reordenar a shortlist existente. ---- +### Cruzeiro -## 8. Histórico de anúncios +Adicionar: -Para cada anúncio ou imóvel provável, tentar identificar: +- ranking interno da quadra; +- andar; +- elevador; +- garagem; +- posição do bloco; +- sistemas do prédio; +- reforma real versus estética. -- primeira aparição; -- última aparição; -- tempo observado; -- mudanças de preço; -- períodos de ausência; -- republicação; -- alteração de corretor; -- alteração de descrição; -- alteração de área ou quartos. +Não criar pesos secretos. Se houver pontuação, documentar pesos e sensibilidade. -Não concluir “vendido” apenas porque desapareceu. +--- -Estados possíveis: +## 8. Outliers -- ativo; -- ausente na coleta; -- removido; -- republicado; -- provável venda; -- status desconhecido. +Investigar antes de excluir: -“Provável venda” exige sinais adicionais. +- erro; +- imóvel premium; +- reforma; +- venda urgente; +- leilão; +- área incorreta; +- duplicata; +- preço desatualizado. + +Apresentar resultados com e sem outliers quando a conclusão mudar. --- ## 9. Comparáveis -Um conjunto de comparáveis deve controlar, quando possível: +Controlar, quando possível: -- região; -- quadra, bloco ou QC; -- tipo de imóvel; +- região e micro-localização; +- tipo; - planta original; - quartos; -- área; +- área validada; - garagem; - elevador; - andar; -- posição; -- reforma; -- conservação; +- estado; +- ampliação; - data; - condomínio; -- situação de ocupação. - -Quando não for possível controlar, declarar a limitação. +- ocupação. -Nunca usar uma média ampla do bairro como avaliação definitiva de uma unidade específica. +Média ampla do bairro não define preço justo de unidade específica. --- -## 10. Tendências +## 10. Tendência e liquidez -Para avaliar tendência de preço: +Para tendência: -- usar imóveis comparáveis; -- controlar mudanças no mix; -- ponderar cobertura; -- evitar média simples; -- usar mediana e regressões robustas quando necessário; -- separar preço de entrada, preço atual e último preço; -- mostrar intervalo de confiança ou dispersão; -- evitar extrapolação longa. +- aumentar a janela histórica; +- controlar mudança de mix; +- usar mediana e métodos robustos; +- separar entrada, preço atual e último preço; +- mostrar dispersão. -Uma alta no preço mediano pode ocorrer porque imóveis menores desapareceram da amostra. - ---- +Para liquidez: -## 11. Estoque e liquidez - -Métricas úteis: - -- anúncios ativos; -- imóveis prováveis ativos; -- entradas; -- saídas; -- republicações; +- entradas e saídas; - tempo observado; +- republicações; - reduções de preço; -- percentual com múltiplas reduções; -- concentração por corretor; -- dispersão de preços; -- taxa de reposição do estoque. - -Limitações: - -- tempo observado não é tempo real no mercado quando a coleta começou depois; -- retirada não confirma venda; -- republicação pode reiniciar o relógio artificialmente. - ---- - -## 12. Análise financeira - -### 12.1 Premissas obrigatórias - -Toda simulação deve declarar: - -- preço; -- entrada em dinheiro; -- FGTS; -- reserva preservada; -- custos de aquisição; -- reforma; -- valor financiado; -- taxa efetiva; -- CET, se disponível; -- sistema; -- prazo; -- seguros e tarifas; -- condomínio; -- IPTU; -- manutenção; -- reajuste do aluguel; -- retorno líquido dos investimentos; -- inflação; -- valorização; -- horizonte; -- custos de venda; -- estratégia de amortização. - -### 12.2 Liquidez - -Separar: - -- dinheiro; -- investimentos com liquidez; -- FGTS; -- patrimônio imobiliário; -- reserva mínima. - -Não tratar FGTS como reserva de emergência. - -### 12.3 Compra versus aluguel - -Comparar: - -- fluxo mensal; -- patrimônio líquido; -- custo de oportunidade; -- risco; -- liquidez; -- flexibilidade; -- estabilidade; -- manutenção; -- impostos; -- custos de transação. - -Mostrar cenários: - -- conservador; -- central; -- otimista. - -Não decidir apenas pelo patrimônio final médio. - -### 12.4 Estresse - -Testar: - -- juros maiores; -- renda menor; -- despesas extraordinárias; -- reforma acima do orçamento; -- vacância ou dificuldade de revenda; -- valorização baixa; -- investimento com retorno menor; -- manutenção elevada; -- redução da capacidade de poupança. - ---- +- anúncios ativos; +- imóveis prováveis ativos. -## 13. Consórcio - -Para analisar um grupo: - -- usar histórico do próprio grupo; -- registrar assembleias; -- lances vencedores; -- lance livre; -- lance fixo; -- lance embutido; -- número de contemplações; -- saldo; -- reajuste da carta; -- taxa de administração; -- fundo de reserva; -- seguros; -- regras de uso; -- prazo; -- valor total pago. - -Não inferir probabilidade de contemplação usando apenas média histórica. - -Analisar: - -- distribuição; -- percentis; -- sazonalidade; -- número de concorrentes; -- mudanças de regra; -- eventos de renda; -- concentração de lances; -- sensibilidade ao valor ofertado. - -Relatos de gerente são hipóteses a testar. +Retirada não confirma venda. --- -## 14. Relatórios por região - -### Cruzeiro +## 11. Integração financeira -Separar por: +Não recomendar imóvel apenas pelo ranking físico. -- Cruzeiro Novo e Velho; -- quadra; -- bloco; -- tipologia; -- área; -- elevador; -- garagem; -- andar; -- conservação; -- reforma. +Calcular: -### Jardins Mangueiral +- preço provável negociado; +- custos de compra; +- reforma e regularização; +- entrada e FGTS; +- reserva remanescente; +- financiamento e CET; +- prestação inicial; +- custo mensal total; +- cenário de amortização; +- comparação com aluguel. -Separar por: - -- QC; -- planta original de três quartos; -- área construída; -- ampliação; -- qualidade da área fechada; -- condomínio; -- posição; -- ruído; -- proximidade de serviços; -- padrão de reforma. - -Excluir casas originalmente de dois quartos. +A classificação final pode ser reduzida se o imóvel exigir consumir a reserva. --- -## 15. Relatório padrão - -### Resumo executivo - -- conclusão principal; -- confiança; -- implicação prática; -- maior risco. - -### Dados - -- fontes; -- período; -- cobertura; -- tamanho da amostra; -- exclusões; -- deduplicação. - -### Resultados - -- tabelas; -- distribuições; -- comparáveis; -- tendências; -- sensibilidade. - -### Interpretação - -- o que é sustentado; -- o que é apenas sugestivo; -- o que requer visita; -- o que requer confirmação financeira ou documental. - -### Próxima ação - -Classificar como: - -- ignorar; -- monitorar; -- aprofundar; -- visitar; -- negociar; -- candidato forte; -- decisão insuficiente. +## 12. Saída padrão + +Cada ficha deve conter: + +- anúncio e URL; +- snapshot; +- localização; +- tipologia original provável; +- preço e histórico; +- áreas e confiabilidade; +- quartos, vagas, elevador e andar; +- possíveis duplicatas; +- status visual; +- pontos fortes; +- pontos fracos; +- custos e riscos; +- pendências de visita e documentação; +- posição relativa; +- próxima ação. --- -## 16. Reprodutibilidade +## 13. Reprodutibilidade -Para cada relatório, salvar: +Estrutura recomendada: ```text -reports// +reports// ├── README.md ├── query.sql ├── analysis.py @@ -493,50 +286,25 @@ reports// └── figures/ ``` -Registrar: - -- data; -- hash do código; -- identificação do banco; -- filtros; -- versão; -- ambiente; -- contagens. +Registrar snapshot, hash do código, filtros, contagens e julgamento manual. --- -## 17. Linguagem das conclusões +## 14. Linguagem Preferir: -- “os anúncios observados sugerem”; -- “na amostra coletada”; +- “na amostra observada”; - “após deduplicação”; -- “não há evidência suficiente”; -- “a conclusão é sensível a”; -- “o dado não permite afirmar”. +- “as fotos sugerem”; +- “exige confirmação”; +- “não há série suficiente”; +- “a conclusão é sensível a”. Evitar: -- “o mercado vale”; - “foi vendido” sem prova; -- “esta é a melhor quadra” sem critério; -- “o preço justo é” sem intervalo e comparáveis; -- “vai valorizar” como certeza; -- “o lance será contemplado” como previsão. - ---- - -## 18. Critério final - -Uma análise é boa quando ajuda a evitar: - -- comprar cedo demais; -- pagar por uma reforma disfarçada; -- confundir anúncio com transação; -- superestimar valorização; -- subestimar custos; -- comprometer liquidez; -- aceitar uma planta inadequada; -- tomar decisão por ansiedade; -- descartar um bom imóvel por uma métrica superficial. +- “preço justo” sem intervalo; +- “vai valorizar”; +- “melhor quadra” sem critério; +- “contemplação provável” sem dados do grupo. diff --git a/docs/CONTEXT_CHANGELOG.md b/docs/CONTEXT_CHANGELOG.md new file mode 100644 index 0000000..fd4b3f4 --- /dev/null +++ b/docs/CONTEXT_CHANGELOG.md @@ -0,0 +1,90 @@ +# Histórico de mudanças do contexto + +## 22/07/2026 — versão 9 + +- relatório Top 15 do Mangueiral refeito isoladamente sobre a execução 22 e o schema v2; +- snapshot consolidado em 95 anúncios do Mangueiral, 78 ativos e 17 inativos; banco com 162 anúncios, 638 observações e 7.457 registros de foto; +- análise fotográfica passou a admitir somente os 3.521 registros da galeria primária; +- teto eliminatório de R$ 750 mil aplicado ao ranking, removendo `1352633` (R$ 755 mil); +- `1401074`, QC 13 e R$ 720 mil, entrou em 8º após revisão da primeira foto, descrição e galeria completa; aderência permanece inferida e pendente de avaliação do usuário; +- `1290512` registrado como inativo sem inferência de venda; +- `348115` atualizado de R$ 530 mil para R$ 550 mil conforme evento material registrado na execução 22. + +## 22/07/2026 — versão 8 + +- confirmado pelo usuário o preço máximo tolerado de **R$ 750.000** para o imóvel; +- registrado que esse valor é teto, não meta de gasto, e não inclui custos de compra, mudança, reforma ou regularização; +- preservada a exigência de ao menos R$ 50.000 de reserva líquida após todos os desembolsos. + +## 22/07/2026 — versão 7 + +- primeira execução após a migração validada: 78 detalhes, zero falhas e apenas uma mudança material (`348115`, de R$ 530 mil para R$ 550 mil); +- captura restrita às galerias primárias reutilizou 1.854 fotos e não adicionou recomendações do portal; +- corrigido o contador `inactive` para contar apenas novas inativações, não repetir todo o estoque já inativo; +- execução 21 concluída somente para o Mangueiral: 95 acumulados, 78 ativos e 17 inativos; +- novo anúncio `1401074`; `1290512` inativado sem inferência de venda; `1346118` alterado de R$ 530 mil para R$ 550 mil; +- criado backup consistente anterior à migração v2; +- schema migrado de forma aditiva, preservando integralmente anúncios, histórico, fotos e execuções; +- adicionadas normalização de CRECI/localização, hash estável, escopo de execução, disponibilidade, eventos materiais e quarentenas; +- identificados 3.936 registros legados fora da galeria principal; 3.286 apontam para fotos de outros IDs e o restante para ativos do portal; +- relatórios analíticos passaram a usar somente `is_primary_gallery=1`. + +## 21/07/2026 — versão 6 + +Revisão integral após a execução 20 do scraper. + +Mudanças: + +- snapshot atualizado para 161 anúncios, 562 observações e 7.363 fotos; +- Mangueiral consolidado em 94 anúncios acumulados, 78 ativos e 16 inativos; +- Cruzeiro consolidado em 67 anúncios acumulados, 63 ativos e 4 inativos; +- documentado que 398 de 401 transições históricas alteram `creci` contaminado e só três anúncios tiveram mudança real de preço; +- revalidadas dez quarentenas por selo visual de vendido, uma no Cruzeiro e nove no Mangueiral; +- `1356197` removido do Top 15 por novo selo visual e substituído por `1290502`; +- triagem de similaridade fotográfica reexecutada com Pillow 12.3.0, sem alteração dos rankings; +- recebida avaliação direta de 1 a 5 dos 15 finalistas do Mangueiral; após reprocessar todo o universo ativo, `1279892`, `1319996` e `1377683` passam a formar o Top 3, sendo a aderência do terceiro ainda inferida; +- confirmada preferência por cozinha funcional e integrada ao gourmet, conservação e baixa necessidade de intervenção; +- piscina, jacuzzi e banheira confirmadas como incompatibilidades; cubas de vidro, marcenaria ruim, gourmet isolado e fechamento envidraçado quente como fortes negativos; +- análise do Mangueiral refeita sobre os 78 anúncios ativos, evitando limitar o feedback aos 15 antigos; +- `1377683`, `1371718` e `1140317` incluídos no Top 5 por aderência inferida, explicitamente pendente de avaliação do usuário; +- auditadas as primeiras fotos dos 78 anúncios ativos; `1301400` foi incluído na quarentena visual e `1369473` foi separado por ser solicitação de compra, não oferta; +- incluídos `1381514` e `1400223` no Top 15 condicionado do Cruzeiro; +- removido `1375199` por inatividade, sem inferir venda; +- relatórios, parâmetros, resultados, shortlist, estado atual, esquema e manual operacional sincronizados com 21/07. + +## 20/07/2026 — versão 5 + +Revisão dos demais chats do projeto e dos relatórios atuais. + +Mudanças: + +- consolidada a prioridade atual do Jardins Mangueiral; +- Cruzeiro definido como alternativa secundária e oportunística; +- preservado o ranking interno Ouro/Prata/Bronze do Cruzeiro; +- incluídas QCs preferenciais do Mangueiral; +- incorporado o filtro de planta original de três quartos; +- incorporada a regra de avaliar funcionalidade, não apenas perda do quintal; +- incorporada avaliação explícita de ruído de vizinhança; +- criado documento financeiro com saldos, renda, aluguel, faixa-alvo e reserva; +- Pró-Cotista e MCMV Faixa 4 marcados como excluídos; +- incorporado o cenário de consórcio BB e a decisão de não contratá-lo; +- criado manual do scraper com caminho real, Playwright e Cloudflare; +- incorporados os snapshots Top 15 de 20/07/2026; +- corrigidas contradições remanescentes no `AGENTS.md` e no contexto do projeto. + +## 13/07/2026 — mudança de prioridade + +A consolidação inicial tratava Cruzeiro e Jardins Mangueiral como igualmente prioritários. + +Correção: + +1. Jardins Mangueiral passou a ser o foco principal. +2. Cruzeiro passou a ser secundário e oportunístico. +3. O ranking interno do Cruzeiro permaneceu válido para imóveis concretos. + +## 11/07/2026 — filtro do Mangueiral + +- casas originalmente de dois quartos excluídas; +- somente plantas originais de três quartos; +- quintal fechado deixou de ser penalidade automática; +- conversão deve ser julgada por funcionalidade, luz, ventilação e redundância. diff --git a/docs/CURRENT_SHORTLIST.md b/docs/CURRENT_SHORTLIST.md new file mode 100644 index 0000000..a8b5238 --- /dev/null +++ b/docs/CURRENT_SHORTLIST.md @@ -0,0 +1,53 @@ +# Shortlist atual — snapshot de 22/07/2026 + +Este documento resume os relatórios completos em `reports/mangueiral_top15/`, `reports/cruzeiro_top15/` e `reports/cruzeiro_vs_mangueiral/`. + +## 1. Jardins Mangueiral — prioridade principal + +| # | Anúncio | QC | Preço | Razão principal | Pendência principal | +|---:|---:|---:|---:|---|---| +| 1 | 1279892 | 10 | R$ 595 mil | nota 4/5; cozinha e gourmet funcionais, poucas alterações | planta, áreas e regularização | +| 2 | 1319996 | 14 | R$ 649 mil | nota 4/5; cozinha, gourmet, quintal e conservação | reversão do closet, cobertura e sistema solar | +| 3 | 1377683 | 11 | R$ 585 mil | aderência inferida; cozinha funcional e gourmet aberto | usuário avaliar, planta, cobertura e drenagem | +| 4 | 1371718 | 14 | R$ 650 mil | aderência inferida; cozinha, conservação e gourmet aberto | usuário avaliar, sistemas e insolação | +| 5 | 1140317 | 5 | R$ 599 mil | aderência inferida; cozinha equipada e gourmet conectado | usuário avaliar, cobertura e uma vaga | + +Observações: + +- o imóvel `1346017`, antes em terceiro, saiu por selo visual de vendido; +- `1356197`, antes em nono, também passou a exibir “VENDIDO” e foi substituído por `1290502`, QC 11; +- outras unidades ficaram em quarentena por indicação visual de venda; +- casas fora das QCs preferenciais podem entrar quando qualidade e preço compensam; +- áreas anunciadas não foram usadas para preço por m². +- a ordem foi recalibrada com as notas e comentários diretos do usuário em 21/07; +- o funil foi então refeito sobre os 78 ativos; `1377683`, `1371718` e `1140317` são achados novos, ainda sem nota pessoal; +- piscina, jacuzzi e banheira são incompatibilidades confirmadas; cubas de vidro e necessidade de reforma antes da mudança são fortes negativos. +- o teto de R$ 750 mil excluiu `1352633`, anunciado por R$ 755 mil; +- `1401074`, QC 13 e R$ 720 mil, entrou em 8º por aderência inferida; ainda depende de avaliação pessoal e diligência documental; +- `1290512` ficou inativo em 22/07; a ausência não foi tratada como venda. + +## 2. Cruzeiro Novo — alternativa secundária + +| # | Anúncio | Local | Preço | Razão principal | Pendência principal | +|---:|---:|---|---:|---|---| +| 1 | 1345146 | SHCES 1207 A | R$ 670 mil | reforma coerente, suíte e elevador anunciado | vaga, matrícula e sistemas | +| 2 | 1357415 | SHCES 1109 | R$ 630 mil | reforma, suíte, nascente e vazado | confirmar elevador | +| 3 | 1357633 | SHCES 309 | R$ 600 mil | reforma uniforme e sistemas renovados declarados | elevador, garagem e obra | +| 4 | 1376958 | SHCES 911 B | R$ 599 mil | reformado, nascente, vazado e suíte | sem elevador e garagem incerta | +| 5 | 1345903 | SHCES 1303 | R$ 565 mil | primeiro andar e preço competitivo | sem garagem, ruído e segurança | + +Observações: + +- `1263868` foi retirado por “VENDIDO” na primeira foto; +- `1381514` e `1400223` entraram no Top 15 condicionado; nenhum supera o Top 5 atual; +- `1375199` ficou inativo em 21/07 e saiu do ranking; ausência não prova venda; +- a janela de coleta é insuficiente para liquidez; +- a posição no ranking de imóvel concreto pode superar a faixa geral da quadra; +- andar, elevador, vaga, matrícula, instalações e ruído exigem confirmação. + +## 3. Uso correto + +- começar visitas pelo Mangueiral; +- usar o Cruzeiro quando surgir oportunidade concreta excepcional; +- reprocessar o ranking quando o snapshot mudar; +- não carregar posições de 21/07/2026 como verdade permanente. diff --git a/docs/CURRENT_STATE.md b/docs/CURRENT_STATE.md new file mode 100644 index 0000000..4ccf607 --- /dev/null +++ b/docs/CURRENT_STATE.md @@ -0,0 +1,145 @@ +# Estado atual do projeto + +**Data de referência:** 22/07/2026 + +Este é o resumo vigente. Ele prevalece sobre fases anteriores da conversa. + +## 1. Decisão imobiliária + +### Prioridade regional + +1. **Jardins Mangueiral — foco principal.** +2. **Cruzeiro — alternativa secundária e oportunística.** + +O entendimento mudou após a comparação de imóveis concretos e uma visita ao Cruzeiro. O estoque do Mangueiral passou a oferecer, com maior frequência, casas mais novas, funcionais e compatíveis com moradia de longo prazo. No Cruzeiro, apareceram mais concessões em reforma, garagem, elevador, conservação e planta. + +Isso não exclui o Cruzeiro. Um apartamento excepcional pode superar uma casa mediana do Mangueiral. + +### Filosofia + +- Esperar pelo imóvel certo é preferível a comprar com grandes concessões. +- A decisão deve equilibrar finanças, segurança patrimonial, funcionalidade e bem-estar. +- Possuir uma casa física no longo prazo tem valor psicológico, mas não justifica comprometer liquidez ou aceitar um imóvel inadequado. + +--- + +## 2. Filtros vigentes + +### Jardins Mangueiral + +- somente planta original de três quartos; +- QCs 8 e 9 preferenciais; +- QCs 6 e 7 alternativas fortes; +- QCs 10 e 11 também consideradas boas; +- posição exata pode superar a classificação da QC; +- quintal fechado é aceitável quando convertido em espaço útil; +- evitar duplicação de cozinha, perda de ventilação, calor e circulação ruim; +- avaliar ruído de paredes compartilhadas, pets, música, áreas comuns e rua. + +### Cruzeiro + +Ranking interno de localização: + +- **Ouro:** SHCES 1501, 1503, 1505, 1203, 1205 e 1207. +- **Prata:** SHCES 1103, 1105, 1107, 1109, 1111, 1303, 1305, 1307 e 1309. +- **Bronze:** conjunto SHCES 1400. +- **Caso a caso:** 1211 e 1507. + +Esse ranking é heurístico e não substitui a avaliação da unidade. + +--- + +## 3. Referência financeira vigente + +Últimos valores informados: + +- renda bruta: aproximadamente R$ 18.500 por mês; +- recursos líquidos: R$ 222.000; +- FGTS: R$ 130.000; +- reserva líquida mínima pós-compra: R$ 50.000; +- capacidade de poupança: R$ 15.000 a cada seis meses; +- aluguel usado nas comparações recentes: R$ 3.200 por mês, sem condomínio e IPTU; +- faixa de imóveis-alvo: aproximadamente R$ 650.000 a R$ 750.000; +- preço máximo tolerado para o imóvel: **R$ 750.000**. + +Esses números devem ser datados e confirmados antes de decisão ou simulação nova. + +O teto de R$ 750.000 é um limite pessoal confirmado, não uma meta de gasto nem uma autorização para comprometer a reserva. Custos de compra, mudança, reforma e regularização devem ser considerados separadamente e ainda precisam preservar a reserva mínima. + +### Exclusões + +- Pró-Cotista: fora do conjunto de opções, pelas regras consideradas de renda bruta máxima de R$ 12.000 e imóvel usado até R$ 500.000. +- MCMV Faixa 4: não usar nas simulações. +- Imóveis sem matrícula/escritura/regularidade suficiente: não presumir financiamento bancário. + +### Estratégia atual + +- financiamento tradicional é a referência principal quando houver compra; +- consórcio pode ter custo nominal menor em alguns cenários, mas perde em previsibilidade, liquidez e risco de contemplação; +- a proposta específica de consórcio BB não foi contratada; +- preservar reserva e manter estratégia lenta é preferível a forçar a compra. + +--- + +## 4. Banco e coleta + +Caminho esperado: + +```text +dfimoveis_data/dfimoveis.sqlite3 +``` + +Snapshot estrutural de 22/07/2026: + +- 162 anúncios; +- 638 observações históricas; +- 7.457 registros históricos de foto, dos quais 3.521 pertencem à galeria primária; +- Cruzeiro Novo: 67 anúncios acumulados, 63 ativos, 4 inativos; +- Jardins Mangueiral: 95 anúncios acumulados, 78 ativos, 17 inativos; +- cobertura: 13 a 22/07/2026; +- Cruzeiro não integra mais a lista de buscas; seus dados permanecem preservados com última coleta em 21/07. + +Em 22/07 foi aplicada migração aditiva do schema, após backup consistente. Valores brutos e registros históricos foram preservados. Endereço, bairro e CRECI agora possuem colunas normalizadas; fotos de recomendações do portal são mantidas, mas marcadas como fora da galeria principal; disponibilidade e problemas de qualidade possuem tabelas auditáveis. + +A janela é curta demais para inferir liquidez. + +A maioria dos snapshots adicionais é ruído de campos textuais contaminados: 398 transições alteram `creci`, enquanto somente três anúncios tiveram mudança real de preço. Não interpretar o número bruto de observações como mudanças de mercado. + +--- + +## 5. Rankings vigentes + +Os rankings completos estão em: + +- `reports/mangueiral_top15/README.md` +- `reports/cruzeiro_top15/README.md` +- `reports/cruzeiro_vs_mangueiral/README.md` + +Eles são snapshots datados, não preferências permanentes. + +Top 3 Mangueiral em 22/07/2026: + +1. anúncio 1279892 — QC 10 — R$ 595 mil; +2. anúncio 1319996 — QC 14 — R$ 649 mil; +3. anúncio 1377683 — QC 11 — R$ 585 mil, aderência inferida e pendente de avaliação do usuário. + +A ordem incorpora avaliação direta do usuário sobre os 15 finalistas: prioridade para cozinha e gourmet funcionais, conservação e baixa necessidade de intervenção; piscina, jacuzzi, banheira e cubas de vidro são incompatibilidades ou fortes negativos. O teto eliminatório de R$ 750 mil retirou `1352633` (R$ 755 mil); o novo `1401074`, QC 13 e R$ 720 mil, entrou em 8º com aderência inferida e pendente de avaliação pessoal. + +Após o feedback, o funil foi refeito sobre os 78 anúncios ativos. `1377683`, `1371718` e `1140317` entraram no Top 5 por aderência inferida nas fotos e descrições, mas ainda não possuem nota pessoal e não devem ser tratados como preferência confirmada. + +Top 3 Cruzeiro em 21/07/2026: + +1. anúncio 1345146 — SHCES 1207 A — R$ 670 mil; +2. anúncio 1357415 — SHCES 1109 — R$ 630 mil; +3. anúncio 1357633 — SHCES 309 — R$ 600 mil. + +--- + +## 6. Pendências principais + +- visitar o Mangueiral e validar QCs, trânsito, comércio, ruído e sensação de segurança; +- atualizar saldos e taxas antes de simulações finais; +- definir limite confortável de prestação, não apenas capacidade bancária; +- confirmar documentação, planta original e regularidade das ampliações; +- aumentar a série histórica antes de conclusões de liquidez e tendência; +- corrigir a instabilidade de `creci`/campos contaminados antes de usar o histórico bruto como mudança real. diff --git a/docs/DATA_MODEL.md b/docs/DATA_MODEL.md index f7ac56f..3ddd33b 100644 --- a/docs/DATA_MODEL.md +++ b/docs/DATA_MODEL.md @@ -1,481 +1,254 @@ -# Modelo de dados — referência conceitual +# Modelo de dados conceitual ## 1. Aviso -Este documento descreve o modelo lógico desejável para análise. +Este documento descreve a interpretação desejada. O esquema real deve ser registrado separadamente em `docs/ACTUAL_SCHEMA.md`. -Ele **não afirma** que o banco SQLite atual possui essas tabelas ou colunas. O esquema real deve ser inspecionado antes de qualquer consulta. - -Não migre o banco original para este modelo sem autorização. +Não migrar o banco original apenas para fazê-lo coincidir com este modelo. --- -## 2. Entidades fundamentais - -O projeto deve distinguir cinco conceitos: +## 2. Entidades essenciais -1. **fonte**: site, portal, corretor ou canal; -2. **anúncio**: publicação identificável em uma fonte; -3. **observação**: estado do anúncio em uma data de coleta; -4. **imóvel físico**: unidade residencial que pode aparecer em vários anúncios; -5. **execução de coleta**: processo técnico que obteve os dados. +### `scrape_run` -Essa separação é essencial para séries históricas e deduplicação. - ---- - -## 3. Fonte - -Entidade conceitual: `source` +Representa uma execução de coleta. Campos desejáveis: -- `source_id` -- `name` -- `base_url` -- `source_type` -- `active` -- `notes` -- `created_at` - -Não usar domínio ou nome de corretor como identificador único sem normalização. - ---- - -## 4. Execução de coleta - -Entidade conceitual: `scrape_run` - -Campos desejáveis: - -- `run_id` -- `source_id` -- `started_at` -- `finished_at` -- `status` -- `pages_requested` -- `pages_succeeded` -- `pages_failed` -- `items_seen` -- `items_inserted` -- `items_updated` -- `http_status_summary` -- `scraper_version` -- `configuration_hash` -- `error_summary` - -Serve para identificar: - -- períodos sem coleta; -- mudanças de cobertura; -- falhas; -- alterações de código; -- diferenças entre ausência real e ausência causada por erro. - ---- - -## 5. Anúncio - -Entidade conceitual: `listing` - -Representa a identidade do anúncio, não cada coleta. - -Campos desejáveis: - -- `listing_id` -- `source_id` -- `source_listing_id` -- `canonical_url` -- `first_seen_at` -- `last_seen_at` -- `last_successful_seen_at` -- `status` -- `seller_type` -- `seller_name_normalized` -- `broker_registration` -- `property_candidate_id` -- `created_at` -- `updated_at` - -Chave natural potencial: - -```text -(source_id, source_listing_id) -``` - -A URL não deve ser a única chave, pois pode mudar. - ---- +- `run_id`; +- `started_at`; +- `finished_at`; +- `status`; +- `scraper_version`; +- `configuration_hash`; +- páginas e erros; +- contagens de anúncios e fotos; +- resumo de status HTTP. -## 6. Observação histórica +### `listing` -Entidade conceitual: `listing_snapshot` +Identidade do anúncio na fonte. -Representa o conteúdo observado em uma execução. +- identificador interno; +- identificador do portal; +- URL canônica; +- primeira e última aparição; +- status; +- anunciante; +- vínculo com imóvel provável. -Campos desejáveis: +### `listing_observation` -- `snapshot_id` -- `listing_id` -- `run_id` -- `observed_at` -- `title` -- `description` -- `price` -- `condominium_fee` -- `property_tax` -- `area_private` -- `area_useful` -- `area_built` -- `area_total` -- `bedrooms` -- `suites` -- `bathrooms` -- `parking_spaces` -- `floor` -- `elevator` -- `furnished` -- `property_type` -- `address_raw` -- `neighborhood_raw` -- `latitude` -- `longitude` -- `image_count` -- `status_raw` -- `payload_hash` -- `raw_payload_reference` - -Não sobrescrever o histórico quando um anúncio muda. - -Se os dados atuais usam uma única linha mutável por anúncio, documentar essa limitação. +Estado do anúncio em uma data de coleta. ---- +- data; +- título e descrição; +- preço; +- condomínio e IPTU; +- áreas separadas; +- quartos, suítes, banheiros e vagas; +- endereço bruto; +- status bruto; +- hash do conteúdo; +- referência ao HTML. -## 7. Imóvel físico candidato +Não sobrescrever histórico. -Entidade conceitual: `property_candidate` +### `photo` -Representa uma hipótese de que anúncios diferentes descrevem o mesmo imóvel. +- anúncio ou observação; +- URL; +- caminho local; +- posição; +- hash criptográfico; +- hash perceptual; +- dimensões; +- status de download. -Campos desejáveis: +A posição da primeira foto deve ser preservada, pois ela é usada na auditoria visual de disponibilidade. -- `property_candidate_id` -- `canonical_region` -- `canonical_address` -- `canonical_unit` -- `property_type` -- `original_floor_plan` -- `dedup_confidence` -- `dedup_method` -- `review_status` -- `created_at` -- `updated_at` +### `property_candidate` -Não tratar correspondência probabilística como certeza. +Hipótese de imóvel físico comum a um ou mais anúncios. -Estados sugeridos: +- região e endereço normalizados; +- tipologia; +- planta original provável; +- método de deduplicação; +- confiança; +- estado de revisão. -- `unreviewed` -- `probable` -- `confirmed` -- `rejected` -- `ambiguous` +Não converter correspondência probabilística em certeza. --- -## 8. Endereço e localização +## 3. Localização no DF -Entidade conceitual: `location` - -Campos desejáveis: - -- `location_id` -- `region` -- `administrative_region` -- `neighborhood` -- `superquadra` -- `quadra` -- `block` -- `qc` -- `street` -- `lot` -- `unit` -- `postal_code` -- `latitude` -- `longitude` -- `geocode_precision` -- `geocode_source` - -No Distrito Federal, o endereço deve permitir estruturas como: +A normalização deve suportar: +- região administrativa; +- bairro; - SHCES; - quadra; - bloco; -- superquadra; - conjunto; -- lote; - QC; +- rua; +- lote; +- unidade; - condomínio; -- unidade. +- latitude e longitude; +- precisão da geocodificação. -Não forçar todos os endereços a um modelo de rua e número. +Não forçar todos os endereços ao modelo rua/número. --- -## 9. Mídia - -Entidade conceitual: `listing_media` - -Campos desejáveis: - -- `media_id` -- `snapshot_id` -- `media_url` -- `media_type` -- `position` -- `content_hash` -- `perceptual_hash` -- `width` -- `height` -- `download_status` - -Hashes perceptuais de imagens podem ajudar na deduplicação, mas não devem decidir sozinhos. - ---- - -## 10. Histórico de preço - -O histórico pode ser derivado de `listing_snapshot`. - -View conceitual: - -```sql -SELECT - listing_id, - observed_at, - price, - price - LAG(price) OVER ( - PARTITION BY listing_id - ORDER BY observed_at - ) AS absolute_change -FROM listing_snapshot; -``` - -Regras: +## 4. Áreas -- ignorar repetições idênticas; -- registrar aumentos e reduções; -- não interpretar ausência como venda; -- identificar alterações simultâneas de área ou tipologia; -- detectar preços promocionais artificiais; -- separar moeda e unidades. - ---- - -## 11. Deduplicação - -### 11.1 Sinais fortes - -- mesmo identificador na fonte; -- mesmo endereço e unidade; -- mesmo conjunto de imagens; -- mesmo telefone ou corretor com descrição muito semelhante; -- mesma planta, metragem e características; -- coordenadas muito próximas; -- texto quase idêntico. - -### 11.2 Sinais moderados - -- mesma quadra e bloco; -- mesmo preço; -- mesma área; -- mesmos quartos e vagas; -- datas próximas; -- imagens parcialmente coincidentes. - -### 11.3 Sinais fracos - -- mesmo bairro; -- título genérico; -- preço arredondado; -- número de quartos isolado. - -### 11.4 Regras - -- manter o anúncio original; -- criar relacionamento de duplicidade; -- registrar método e confiança; -- permitir revisão manual; -- não fundir registros de forma irreversível; -- não usar apenas texto normalizado; -- evitar que atualizações do mesmo anúncio sejam contadas como imóveis novos. - ---- - -## 12. Normalização - -### Preço - -- armazenar como número inteiro em centavos ou valor monetário consistente; -- preservar valor bruto; -- registrar moeda; -- detectar preço por mês confundido com preço total; -- detectar valores incompletos. - -### Área - -Manter campos separados: +Manter separadas: - privativa; - útil; - construída; - total; -- terreno. +- terreno; +- ampliada declarada. + +Preservar valor bruto e fonte. + +No Mangueiral, áreas anunciadas frequentemente misturam área original e ampliação. Não calcular preço por m² sem validação. -Nunca preencher uma área com outra apenas para completar dados. +--- -### Quartos +## 5. Quartos e planta Separar: -- quartos; +- quartos anunciados; +- quartos utilizáveis; - suítes; - dependência; - escritório; -- quarto reversível; -- tipologia original; -- tipologia anunciada. +- quarto adaptado; +- planta original provável; +- confiança da classificação. -### Localização +No Mangueiral, a planta original de três quartos é um filtro obrigatório. -Preservar: +--- -- texto bruto; -- versão normalizada; -- componentes extraídos; -- confiança da extração. +## 6. Status e disponibilidade -### Datas +Campos derivados desejáveis: -Usar ISO 8601 e timezone explícito quando relevante. +- ativo na última coleta; +- inativo; +- vendido na primeira foto; +- vendido na descrição; +- republicado; +- duplicata provável; +- conflito de dados; +- data da última evidência. ---- +Ausência não é prova de venda. -## 13. Qualidade dos dados - -Criar métricas por fonte, período e região: +--- -- percentual sem preço; -- percentual sem área; -- percentual sem localização; -- percentual com preço por m² calculável; -- duplicidade estimada; -- taxa de mudança de identificador; -- cobertura diária; -- falhas de coleta; -- distribuições implausíveis; -- inconsistência entre título e campos; -- divergência entre snapshots. +## 7. Deduplicação ---- +### Sinais fortes -## 14. Inspeção inicial do SQLite +- mesmo ID da fonte; +- endereço e unidade; +- conjunto de imagens; +- implantação idêntica; +- telefone e descrição coincidentes. -Consultas somente leitura úteis: +### Sinais moderados -### Tabelas e views +- quadra/bloco/QC; +- área, preço e quartos; +- texto semelhante; +- datas próximas; +- fotos parcialmente coincidentes. -```sql -SELECT - type, - name, - tbl_name, - sql -FROM sqlite_master -ORDER BY type, name; -``` +### Regras -### Contagem aproximada de tabelas +- preservar anúncios originais; +- criar grupo de imóvel provável; +- registrar confiança e método; +- permitir revisão manual; +- não fundir irreversivelmente. -Gerar consultas após listar os nomes. Não concatenar nomes externos sem validação. +--- -### Colunas +## 8. Histórico de preço -```sql -PRAGMA table_info('nome_da_tabela'); -``` +Derivar por anúncio e por imóvel provável. -### Chaves estrangeiras +Registrar: -```sql -PRAGMA foreign_key_list('nome_da_tabela'); -``` +- primeiro preço; +- preço atual; +- reduções e aumentos; +- republicações; +- mudanças simultâneas de área, quartos ou descrição; +- períodos de ausência. -### Índices +Não interpretar retirada como venda. -```sql -PRAGMA index_list('nome_da_tabela'); -``` +--- -### Integridade +## 9. Qualidade dos dados -```sql -PRAGMA quick_check; -``` +Métricas mínimas: -`quick_check` é somente leitura, mas pode ser custoso em bancos grandes. Executar quando apropriado. +- nulos por campo; +- preços implausíveis; +- áreas implausíveis; +- divergência entre título e campos; +- cobertura por dia; +- falhas por página; +- fotos ausentes; +- duplicidade estimada; +- anúncios com selo de vendido; +- mudanças de ID; +- distribuição por região e tipologia. --- -## 15. Camada derivada recomendada +## 10. Camada derivada -Sem alterar o banco original, criar: +Sugestão: ```text data/derived/ ├── listings_clean.parquet -├── snapshots_clean.parquet +├── observations_clean.parquet +├── photos_index.parquet ├── property_candidates.parquet ├── price_history.parquet ├── locations_normalized.parquet └── quality_metrics.parquet ``` -Ou um SQLite derivado: - -```text -data/derived/analytics.sqlite -``` - -Toda derivação deve registrar: - -- data; -- versão do código; -- fonte; -- filtros; -- hash ou identificação do banco de origem; -- contagem de entrada e saída. +Registrar versão do código, data, banco de origem e contagens de entrada/saída. --- -## 16. Dicionário do esquema real - -Após inspecionar o banco, produzir: - -```text -docs/ACTUAL_SCHEMA.md -``` +## 11. Implementação aditiva v2 — 22/07/2026 -Esse arquivo deve conter: +Com autorização explícita do usuário e backup consistente, parte deste modelo foi incorporada ao banco operacional sem remover dados: -- diagrama das tabelas; -- descrição de cada coluna; -- chaves; -- índices; -- cardinalidades; -- exemplos pequenos; -- problemas conhecidos; -- correspondência com este modelo conceitual; -- decisões de interpretação. +- campos brutos preservados e colunas normalizadas em `listings`; +- `stable_content_hash` separado do hash bruto legado; +- `is_primary_gallery`, origem e revisão em `photos`; +- `availability_observations` para evidência de disponibilidade; +- `data_quality_issues` para quarentenas reversíveis; +- `listing_change_events` para mudanças materiais futuras; +- escopo e configuração das futuras execuções em `crawl_runs`; +- visões `v_primary_photos`, `v_open_data_quality_issues` e `v_listing_current_availability`. -Não alterar `DATA_MODEL.md` para simplesmente espelhar um esquema ruim. Manter separação entre modelo conceitual e implementação real. +As tabelas e colunas antigas continuam preservadas para reprodução histórica. diff --git a/docs/FINANCIAL_STRATEGY.md b/docs/FINANCIAL_STRATEGY.md new file mode 100644 index 0000000..a9e8fc1 --- /dev/null +++ b/docs/FINANCIAL_STRATEGY.md @@ -0,0 +1,195 @@ +# Estratégia financeira + +## 1. Snapshot pessoal + +**Data de referência:** julho de 2026 + +| Item | Valor de trabalho | +|---|---:| +| Renda bruta mensal | aproximadamente R$ 18.500 | +| Recursos líquidos | R$ 222.000 | +| FGTS | R$ 130.000 | +| Reserva líquida mínima pós-compra | R$ 50.000 | +| Poupança adicional | R$ 15.000 a cada seis meses | +| Aluguel-base usado nas comparações | R$ 3.200/mês | +| Faixa de imóveis-alvo | R$ 650.000–R$ 750.000 | +| Preço máximo tolerado do imóvel | **R$ 750.000** | + +O aluguel-base exclui condomínio e IPTU. Não misturar com valores brutos ou contratuais sem decomposição. + +Esses valores são premissas datadas, não constantes permanentes. + +O preço de R$ 750.000 é o teto máximo tolerado para o imóvel, não o orçamento recomendado. Custos de aquisição, mudança, reforma e regularização ficam fora desse preço e continuam sujeitos à preservação da reserva líquida mínima. + +--- + +## 2. Restrições + +- preservar ao menos R$ 50.000 líquidos depois de entrada, custos, mudança e adequações; +- FGTS não é reserva de emergência; +- não usar toda a capacidade bancária como orçamento; +- não aceitar prestação inicial desconfortável apenas porque cabe na análise de crédito; +- incorporar custos de transação e reforma; +- evitar imóvel que exija comprometer a reserva logo após a compra. +- não recomendar nem simular como candidato aceitável um imóvel com preço acima de R$ 750.000, salvo se o usuário alterar explicitamente esse teto. + +--- + +## 3. Programas e linhas excluídos + +### Pró-Cotista + +Fora do conjunto atual de opções. + +Regras consideradas pelo usuário: + +- renda bruta máxima de R$ 12.000; +- imóvel usado de até R$ 500.000. + +A renda aproximada de R$ 18.500 e a faixa-alvo de R$ 650.000–R$ 750.000 não se enquadram. + +### Minha Casa Minha Vida — Faixa 4 + +Não incluir nas simulações atuais. + +### Imóvel irregular + +Financiamento bancário tradicional depende de matrícula, registro e regularidade suficientes para a garantia. Não presumir financiamento de imóvel sem escritura/matrícula regular. + +--- + +## 4. Financiamento tradicional + +É a referência principal para compra quando o imóvel correto aparecer. + +Simulações recentes citaram, aproximadamente: + +- Caixa: 11,5% ao ano; +- Banco do Brasil: 11,7% ao ano. + +Essas taxas são snapshots de propostas/simulações, não taxas vigentes garantidas. Sempre substituir por CET atual e documentos do banco. + +### Campos obrigatórios em qualquer simulação + +- preço do imóvel; +- entrada em dinheiro; +- FGTS; +- reserva preservada; +- ITBI, registro e tarifas; +- reforma e mudança; +- valor financiado; +- SAC ou Price; +- taxa nominal, efetiva e CET; +- indexador; +- prazo; +- seguros; +- primeira e última prestação; +- amortização extraordinária; +- uso de FGTS a cada 24 meses; +- horizonte de permanência; +- custo de oportunidade. + +### Comparação com o aluguel + +O usuário observou que, para um imóvel em torno de R$ 700.000, a prestação inicial estimada poderia superar o aluguel atual. + +A análise deve comparar: + +- fluxo mensal; +- patrimônio acumulado; +- liquidez; +- risco; +- estabilidade; +- custos de manutenção; +- reajuste do aluguel; +- valorização do imóvel; +- retorno líquido alternativo; +- custos de venda. + +Não decidir apenas porque a prestação é maior ou menor que o aluguel. + +--- + +## 5. Consórcio BB analisado + +Cenário específico discutido, não contratado: + +- carta: R$ 660.000; +- prazo informado: 161 meses; +- taxa de administração: 0,11% ao mês, aproximadamente 18,7% no total da carta; +- lance pretendido: 60%, equivalente a R$ 420.000; +- recursos próprios considerados: R$ 300.000; +- empréstimo complementar: R$ 120.000; +- empréstimo: 120 parcelas de R$ 1.596,66; +- parcela pós-lance estimada: aproximadamente R$ 1.924; +- último lance vencedor informado: cerca de 58%; +- lances recentes mencionados: aproximadamente 58,99% a 60%; +- grupo não era novo. + +Relatos do gerente sobre sazonalidade de agosto/setembro, competição em outubro e participação de funcionários do BB são evidência anedótica e não devem ser modelados como regra sem histórico do próprio grupo. + +### Conclusão de trabalho + +- o consórcio pode ter vantagem de custo nominal em algumas combinações; +- exige imobilização de recursos e aceita risco de contemplação; +- pode demandar empréstimo complementar, reduzindo a vantagem; +- financiamento tradicional oferece maior certeza, flexibilidade e execução imediata; +- a proposta específica foi deixada passar; +- a estratégia atual é manter paciência e precisão. + +--- + +## 6. Custos de compra + +Incluir, conforme o caso: + +- ITBI; +- registro; +- escritura quando aplicável; +- avaliação bancária; +- tarifas; +- seguros; +- mudança; +- reforma; +- mobiliário; +- regularização; +- condomínio e IPTU proporcionais; +- contingência. + +Não usar percentual genérico sem conferir regras e valores atuais. + +--- + +## 7. Cenários obrigatórios + +Toda recomendação financeira deve apresentar ao menos: + +- conservador; +- central; +- otimista; +- cenário de estresse. + +Estressar: + +- renda menor; +- juros ou CET maiores; +- reforma acima do orçamento; +- valorização baixa; +- retorno de investimento menor; +- manutenção extraordinária; +- redução da poupança; +- necessidade de vender antes do horizonte. + +--- + +## 8. Critério de decisão + +A compra é financeiramente aceitável somente quando: + +- a reserva é preservada; +- o custo mensal é confortável, não apenas aprovado; +- o imóvel atende à planta e à localização; +- custos de adequação são conhecidos; +- o horizonte justifica custos de transação; +- a comparação com aluguel não depende de premissas otimistas; +- a decisão continua boa sem contar com valorização excepcional. diff --git a/docs/LOCATION_CRITERIA.md b/docs/LOCATION_CRITERIA.md new file mode 100644 index 0000000..31dce6d --- /dev/null +++ b/docs/LOCATION_CRITERIA.md @@ -0,0 +1,138 @@ +# Critérios de localização + +## 1. Regra geral + +Avaliar localização em três níveis: + +1. região; +2. quadra, bloco, QC ou condomínio; +3. posição exata da unidade. + +A classificação geral nunca substitui a posição concreta. + +--- + +## 2. Jardins Mangueiral — prioridade principal + +### 2.1 Hierarquia de QCs + +| Nível | QCs | Uso | +|---|---|---| +| Preferenciais | 8 e 9 | Priorizar triagem e visitas quando o imóvel também for bom | +| Alternativas fortes | 6 e 7 | Manter entre as candidatas principais | +| Também boas | 10 e 11 | Avaliar normalmente, sem penalidade automática | +| Não classificadas | demais QCs | Analisar caso a caso; não excluir somente pela QC | + +A hierarquia veio de relatos de moradores e deve ser marcada como **anedótica**. + +O ranking de imóveis concretos pode produzir candidatos fortes em outras QCs. No snapshot de 21/07/2026, por exemplo, imóveis em QC 10, QC 6 e QC 8 lideraram, enquanto unidades em QCs 14, 12, 4, 5 e 3 também entraram no Top 15. + +### 2.2 O que “bem localizada” significa + +- acesso prático a mercado, farmácia e serviços; +- qualidade do trajeto a pé; +- facilidade de entrada e saída; +- tempo real em horários relevantes; +- circulação interna; +- topografia; +- estacionamento de visitantes; +- iluminação noturna; +- distância de portaria e áreas técnicas; +- distância de quadra esportiva, salão, parque infantil e lixeiras; +- privacidade; +- posição solar; +- ruído. + +### 2.3 Posição da casa + +Uma casa na QC 8 ou 9 pode perder prioridade se estiver: + +- junto a área social barulhenta; +- exposta a via interna movimentada; +- com pouca privacidade; +- em posição quente e mal ventilada; +- próxima a equipamentos ou lixeiras; +- em trecho ruim para estacionamento. + +Uma unidade excepcional nas QCs 6, 7, 10, 11 ou mesmo em QC não classificada pode superar uma opção mediana nas QCs preferenciais. + +### 2.4 Trânsito e rotina + +O custo do deslocamento ao Plano Piloto deve ser medido em campo. A flexibilidade de horário, home office e o horário escolar no início da tarde reduzem parte do impacto, mas não o eliminam. + +Registrar tempos em: + +- manhã de dia útil; +- fim de tarde; +- noite; +- fim de semana; +- trajeto ao SBS; +- trajeto ao Sudoeste; +- trajeto a São Sebastião. + +--- + +## 3. Cruzeiro — alternativa secundária + +### 3.1 Ranking interno de quadras + +Esse ranking orienta a localização relativa de apartamentos concretos no Cruzeiro Novo. + +| Faixa | Quadras SHCES | +|---|---| +| Ouro | 1501, 1503, 1505, 1203, 1205, 1207 | +| Prata | 1103, 1105, 1107, 1109, 1111, 1303, 1305, 1307, 1309 | +| Bronze | conjunto 1400 | +| Caso a caso | 1211 e 1507 | + +Regras: + +- a faixa não compensa um apartamento ruim; +- uma unidade Prata bem reformada, silenciosa e acessível pode superar uma Ouro problemática; +- edifício, bloco, fachada, andar e posição são decisivos; +- o ranking não torna o Cruzeiro prioritário sobre o Mangueiral. + +### 3.2 Imóveis concretos podem fugir da hierarquia + +O Top 15 de 21/07/2026 incluiu imóveis em SHCES 1207, 1109, 1303 e também em 309, 911, 703, 207, 305, 301, 101, 609 e 203. + +Essas entradas não redefinem automaticamente as faixas. Elas mostram que qualidade, preço, estado e funcionalidade podem justificar investigação fora da hierarquia original. + +### 3.3 Critérios locais + +Avaliar: + +- acesso ao Eixo Monumental e Plano Piloto; +- comércio útil à rotina; +- caminhabilidade; +- ônibus e vias; +- tráfego e ruído; +- estacionamento e garagem; +- iluminação e arborização; +- estado dos blocos vizinhos; +- proximidade de bares, escolas, templos e quadras esportivas; +- posição do bloco em relação à rua; +- orientação solar e ventilação; +- vista e privacidade. + +### 3.4 Observação de campo + +A visita anterior ao Cruzeiro reduziu sua prioridade porque o perfil de comércio percebido não correspondeu ao desejado. Tratar isso como preferência pessoal e hipótese a validar, não como julgamento socioeconômico da região. + +--- + +## 4. Protocolo de visita de localização + +Para um candidato real: + +- visitar em dia útil; +- observar pico de trânsito; +- visitar à noite ou no fim de semana; +- testar estacionamento; +- caminhar até serviços; +- medir ruído com janelas abertas e fechadas; +- conversar com moradores quando possível; +- verificar iluminação, circulação e segurança percebida; +- registrar tempos reais de deslocamento. + +Não depender apenas de mapa, anúncio ou corretor. diff --git a/docs/PROJECT_CONTEXT.md b/docs/PROJECT_CONTEXT.md index df23eb9..5035c23 100644 --- a/docs/PROJECT_CONTEXT.md +++ b/docs/PROJECT_CONTEXT.md @@ -2,264 +2,152 @@ ## 1. Objetivo -Construir uma base histórica e uma metodologia confiável para apoiar a compra de um imóvel residencial no Distrito Federal. +Construir uma base histórica de anúncios e uma metodologia de avaliação para uma compra residencial de longo prazo no Distrito Federal. -O objetivo não é apenas encontrar o menor preço. A decisão deve equilibrar: +A compra deve oferecer: -- segurança patrimonial de longo prazo; -- adequação funcional do imóvel; -- qualidade de vida; -- liquidez; -- custo total de aquisição e manutenção; -- risco de reformas; -- impacto financeiro mensal; -- fatores psicológicos associados a possuir uma residência estável. +- residência funcional e estável; +- segurança patrimonial; +- custo mensal sustentável; +- preservação de reserva de emergência; +- baixo risco de reforma e custos escondidos; +- adequação à rotina familiar; +- liquidez razoável; +- possibilidade de permanência por 10 a 20 anos. -A análise deve ser lenta, comparativa e baseada em evidências. Não existe urgência artificial para comprar. +O projeto não busca comprar rapidamente. Busca reduzir a probabilidade de arrependimento. --- -## 2. Filosofia de decisão +## 2. Evolução da prioridade regional -### Princípios confirmados +### Fase anterior -- Evitar comprar apenas por medo de valorização futura. -- Evitar comprometer a reserva de emergência. -- Não aceitar grandes concessões de planta, conservação ou funcionalidade apenas para alcançar um preço nominal. -- Considerar reforma como custo financeiro, operacional e psicológico. -- Preferir imóvel pronto ou com intervenções pequenas e previsíveis. -- Comparar comprar com continuar alugando. -- Considerar que a compra será provavelmente em uma região diferente da moradia atual. -- Separar segurança emocional de justificativas financeiras. -- Reconhecer o valor psicológico de possuir um imóvel físico de longo prazo, sem transformar isso em justificativa para uma compra ruim. -- Tratar preço anunciado como ponto inicial de negociação, não como valor de mercado definitivo. +Cruzeiro chegou a ser tratado como candidato principal por centralidade, acesso ao Plano Piloto e tradição patrimonial. ---- - -## 3. Situação residencial atual +### Entendimento atual -Últimos valores consolidados no histórico do projeto: +Jardins Mangueiral tornou-se a prioridade principal. Cruzeiro permanece como alternativa secundária e oportunística. -- localização atual: Asa Sul, Brasília; -- imóvel alugado: aproximadamente 66 m²; -- aluguel: R$ 3.200 por mês; -- condomínio e IPTU não incluídos nesse valor; -- reajuste anual usado nas simulações anteriores: 4,5%. +Motivos para a mudança: -Esses números devem ser confirmados antes de novas simulações, pois podem mudar. +- casas mais novas e maior oferta no Mangueiral; +- maior chance de encontrar planta e conservação adequadas; +- percepção de ambiente residencial, segurança e silêncio; +- serviços de perfil familiar em crescimento; +- melhor integração com São Sebastião; +- flexibilidade de horário e trabalho remoto reduz parte do custo do trânsito; +- no Cruzeiro, imóveis concretos apresentaram mais concessões de reforma, garagem, elevador e funcionalidade. -A comparação aluguel versus compra deve considerar que o padrão, a localização e a tipologia dos imóveis candidatos podem ser diferentes do imóvel alugado atual. +Em visita ao Cruzeiro, o usuário percebeu uma composição de comércio e serviços menos alinhada às suas preferências cotidianas, com menor presença percebida de padarias, farmácias, restaurantes e academias. Essa é uma percepção pessoal de campo; não deve ser convertida em inferência de renda, segurança ou qualidade objetiva da região. --- -## 4. Regiões prioritárias - -### 4.1 Cruzeiro - -O Cruzeiro, especialmente o Cruzeiro Novo, é um dos dois principais candidatos. - -Aspectos relevantes: - -- localização central; -- acesso ao Plano Piloto; -- blocos e quadras com diferenças importantes; -- estoque antigo, com variação de conservação; -- risco de imóveis que exigem reforma; -- diferenças de estacionamento, garagem, elevador, ruído e posição do bloco; -- apartamentos de dois e três quartos podem ter áreas totais semelhantes; -- preço deve ser analisado em conjunto com planta, estado e custos de adequação. +## 3. Rotina e logística -### 4.2 Jardins Mangueiral +Contexto relevante: -Jardins Mangueiral é o outro principal candidato. +- trabalho associado à área central de Brasília/SBS; +- filha estuda no Sudoeste e entra no início da tarde; +- existe flexibilidade de horário e trabalho remoto em parte da rotina; +- namorada e familiares dela vivem em São Sebastião; +- Jardins Mangueiral pode melhorar a logística da relação e da convivência familiar. -Aspectos relevantes: - -- casas mais novas em comparação com parte do estoque do Cruzeiro; -- sensação de segurança, silêncio e residência de longo prazo; -- proximidade de São Sebastião, onde vivem a namorada do usuário e familiares dela; -- potencial de desenvolvimento da região em horizonte de 15 a 20 anos; -- impacto de trânsito parcialmente mitigado por flexibilidade de horário e trabalho remoto; -- logística compatível com o horário escolar da filha em parte dos dias; -- necessidade de avaliar ruído de vizinhança e qualidade das adaptações internas. - -Somente casas de planta original de três quartos fazem parte do conjunto de candidatos. +A compra deve continuar racional e funcional mesmo se as circunstâncias afetivas mudarem. A proximidade da namorada é benefício, não fundamento exclusivo da decisão. --- -## 5. Preferências funcionais - -O imóvel ideal deve: +## 4. Preferências habitacionais -- funcionar como residência de longo prazo; -- exigir pouca ou nenhuma reforma relevante; -- ter planta coerente; -- evitar circulação desperdiçada; -- ter boa iluminação e ventilação; -- oferecer espaço social útil; -- evitar duplicações de cozinha ou área gourmet sem função clara; -- ter conservação compatível com o preço; -- minimizar custos escondidos; -- preservar flexibilidade para mudanças futuras da família. +- imóvel pronto ou com intervenções pequenas e previsíveis; +- evitar grandes concessões de planta, conservação e funcionalidade; +- três quartos funcionais são valorizados; +- boa iluminação e ventilação; +- espaço social útil; +- pouca circulação desperdiçada; +- armazenamento adequado; +- ruído controlado; +- manutenção sustentável; +- documentação financiável; +- flexibilidade para mudanças futuras da família. -No Jardins Mangueiral, o fechamento do quintal não é automaticamente negativo. A análise deve avaliar se a área foi convertida em espaço realmente útil, ventilado e integrado. +Preferências funcionais confirmadas em avaliação direta dos anúncios: ---- - -## 6. Referência financeira - -### Último retrato consolidado - -Valores informados no histórico, sujeitos a atualização: - -- recursos líquidos: R$ 222.000; -- saldo de FGTS: R$ 130.000; -- reserva mínima desejada após a compra: R$ 50.000; -- capacidade de poupança: R$ 15.000 a cada seis meses; -- faixa de preço mais compatível com os imóveis desejados: aproximadamente R$ 650.000 a R$ 750.000; -- faixa anterior de referência: R$ 600.000. - -Não use esses valores como atuais sem registrar a data da análise e pedir confirmação quando a conclusão depender deles. - -### Regras financeiras - -- FGTS não deve ser tratado como liquidez disponível para emergências. -- Custos de compra devem ser adicionados ao preço: - - ITBI; - - registro; - - escritura quando aplicável; - - avaliação; - - tarifas; - - mudança; - - reparos; - - mobiliário; - - eventual reforma; - - custos de oportunidade. -- A reserva mínima de R$ 50.000 não deve ser consumida pela entrada, custos ou reforma. -- A prestação não deve ser analisada isoladamente. -- Comparar: - - aluguel; - - condomínio; - - IPTU; - - seguros; - - manutenção; - - juros; - - amortização; - - custo de oportunidade da entrada; - - valorização; - - reajuste do aluguel; - - liquidez do imóvel. -- Distinguir patrimônio acumulado de fluxo de caixa mensal. +- cozinha bem planejada e, idealmente, semi-integrada ao convívio externo; +- churrasqueira e gourmet conectados ao fluxo social da casa; +- prioridade para conservação e baixa necessidade de intervenção antes da mudança; +- piscina, jacuzzi e banheira não são desejadas; +- cubas de vidro, marcenaria ruim e áreas externas abandonadas são fortes negativos; +- fechamento em vidro deve ser penalizado quando houver risco de calor excessivo; +- closet criado pela perda de um quarto pode exigir reversão futura; +- placas solares são bônus, não compensação para planta ou funcionalidade inadequada. ---- +### Quintal e ampliação no Mangueiral -## 7. Financiamento e consórcio +A perda do quintal original não é defeito automático. É aceitável quando a área vira ambiente útil de convivência, refeição, trabalho ou armazenamento. -### Financiamento +É negativa quando: -Simulações anteriores consideraram diferentes cenários de: +- duplica a cozinha sem necessidade; +- reduz ventilação e iluminação; +- cria calor ou umidade; +- compromete drenagem e impermeabilização; +- produz circulação inútil; +- ocupa a área externa sem ganho funcional real. -- SAC; -- prazos de 20, 30 e até 35 anos; -- juros próximos de 9% ao ano em alguns cenários; -- amortizações periódicas com FGTS; -- amortizações extraordinárias em dinheiro. - -Toda nova simulação deve explicitar: - -- taxa nominal e efetiva; -- indexador; -- CET; -- sistema de amortização; -- prazo; -- entrada; -- custos acessórios; -- uso de FGTS; -- estratégia de amortização; -- inflação; -- retorno líquido alternativo; -- horizonte de permanência. - -### Pró-cotista - -A estratégia não deve assumir que o Pró-cotista estará disponível. O usuário já percebeu que provavelmente não receberá essa linha. - -### Consórcio - -O consórcio do Banco do Brasil foi considerado como alternativa. - -Informações recebidas do gerente, tratadas como relatos e não como garantias: +--- -- grupos com desconto podem atrair participantes dispostos a oferecer lances elevados; -- agosto e setembro podem ser meses relativamente melhores para ofertar lance; -- outubro pode ficar mais competitivo por coincidir com pagamento de PLR de funcionários do BB; -- muitos participantes dos consórcios do BB seriam funcionários do próprio banco. +## 5. Filosofia financeira e psicológica -Essas afirmações precisam ser verificadas com dados do grupo sempre que forem usadas. Não extrapolar um grupo para todos os grupos. +O usuário valoriza possuir uma residência física de longo prazo. Essa segurança tem peso legítimo na decisão, especialmente com o avanço da idade e a preocupação com estabilidade futura. -A estratégia atual é não agir com pressa e observar os percentuais de lances ao longo do tempo. +Ao mesmo tempo: ---- +- reserva de emergência não deve ser sacrificada; +- prestação maior que o aluguel atual exige justificativa e folga; +- capacidade máxima de financiamento não é orçamento confortável; +- custo de oportunidade da entrada deve ser medido; +- reforma e mudança têm custo psicológico, além do financeiro; +- comprar para aliviar ansiedade pode produzir uma decisão pior. -## 8. Fatores familiares e logísticos - -- O usuário tem uma filha em idade escolar. -- A namorada mora em São Sebastião e tem um filho. -- Jardins Mangueiral pode reduzir a distância para a namorada e a família dela. -- O usuário tem flexibilidade de trabalho e de horário em parte da semana. -- A logística familiar deve ser considerada, mas não deve justificar um imóvel inadequado. -- A compra deve continuar válida mesmo se circunstâncias relacionais mudarem. +A conclusão financeira não deve ignorar o benefício de estabilidade, e o benefício psicológico não deve ignorar juros, liquidez e risco. --- -## 9. Horizonte +## 6. Mercado e dados -A decisão deve ser avaliada como residência e patrimônio de longo prazo. +O banco contém anúncios, observações históricas e fotos. Fotografias são essenciais porque campos estruturados e descrições não capturam adequadamente: -Questões centrais: +- planta; +- conservação; +- iluminação; +- ventilação; +- qualidade da reforma; +- fechamento do quintal; +- redundância de áreas gourmet; +- sinais visuais de anúncio vendido; +- duplicatas entre corretores. -- O imóvel continuará funcional em 10, 15 ou 20 anos? -- A localização atende a rotina sem depender de uma única circunstância atual? -- O custo mensal permanece confortável em cenários adversos? -- Existe reserva para manutenção, saúde, carro e emergências? -- A planta permite adaptação? -- A revenda é razoável? -- A compra reduz ou aumenta a fragilidade financeira? +Preço anunciado é evidência de oferta, não transação. --- -## 10. Questões em aberto +## 7. Regiões fora do foco -Manter estas questões explícitas até que os dados permitam respondê-las: +Outras regiões já foram discutidas, incluindo Asa Sul, Asa Norte, Guará I, Lúcio Costa, Águas Claras e outras. Elas não compõem o foco operacional atual. -- valor atual disponível em dinheiro e FGTS; -- limite confortável de prestação; -- prazo máximo desejável; -- custo total aceitável de aquisição; -- peso relativo entre Cruzeiro e Jardins Mangueiral; -- blocos e quadras prioritários no Cruzeiro; -- QCs prioritárias no Mangueiral após visitas; -- tolerância a imóveis sem elevador ou garagem; -- impacto real do trânsito; -- custo de manutenção de casas versus apartamentos; -- tamanho mínimo funcional; -- horizonte provável de permanência; -- estratégia final entre financiamento, consórcio e espera. +Não ampliar automaticamente o universo de busca sem instrução. Elas podem ser usadas como referência comparativa quando isso responder a uma pergunta específica. --- -## 11. Fonte de verdade - -Este documento consolida preferências e premissas, mas não substitui uma confirmação recente quando a decisão depender de: +## 8. Horizonte de decisão -- saldo financeiro; -- renda; -- taxas bancárias; -- regras de FGTS; -- custos cartorários; -- disponibilidade de crédito; -- preços atuais; -- condições de consórcio; -- situação familiar ou logística. +Perguntas obrigatórias para qualquer candidato: -Toda informação temporal deve carregar data de referência. +- continuará funcional em 10, 15 ou 20 anos? +- atende à rotina sem depender de uma única circunstância atual? +- permite preservar reserva e capacidade de poupança? +- é habitável sem obra extensa? +- possui saída razoável para revenda? +- reduz ou aumenta a fragilidade financeira? +- oferece qualidade de vida suficiente para justificar a mudança? diff --git a/docs/PROPERTY_CRITERIA.md b/docs/PROPERTY_CRITERIA.md index 8fd2ced..a0b2d2e 100644 --- a/docs/PROPERTY_CRITERIA.md +++ b/docs/PROPERTY_CRITERIA.md @@ -1,438 +1,278 @@ # Critérios de avaliação dos imóveis -## 1. Estrutura da avaliação +## 1. Classificação -Classificar cada critério como: +Cada achado deve ser marcado como: -- **eliminatório**: imóvel deve ser excluído; -- **forte**: pode inviabilizar a compra mesmo com bom preço; -- **moderado**: influencia comparação e negociação; -- **informativo**: deve ser registrado, mas não decide sozinho. +- **eliminatório**; +- **forte**; +- **moderado**; +- **informativo**; +- **pendente de confirmação**. -Não criar pesos numéricos arbitrários sem aprovação. Quando usar pontuação, mostrar os pesos, a justificativa e o efeito de cada critério. +Falta de informação não é aprovação nem eliminação automática. --- -## 2. Critérios eliminatórios gerais +## 2. Critérios eliminatórios ou de quarentena -Excluir ou colocar em quarentena analítica quando houver: +- planta incompatível com a necessidade de longo prazo; +- no Mangueiral, planta originalmente de dois quartos; +- documentação que impeça a estratégia de financiamento e não possa ser regularizada; +- problema estrutural, umidade grave ou reforma extensa sem desconto suficiente; +- ruído intolerável; +- preço total incompatível com a reserva; +- localização materialmente divergente; +- anúncio com preço ou área absurdamente inconsistente; +- indicação visual ou textual de “VENDIDO” ou “negócio fechado”; +- duplicata provável sem identificação do anúncio principal; +- conflito relevante entre título, descrição, fotos e campos. -- documentação incompatível ou não esclarecida; -- área, tipologia ou localização materialmente divergentes; -- planta que não atenda às necessidades de longo prazo; -- preço total incompatível com a preservação da reserva; -- problemas graves de umidade, infiltração ou estrutura; -- ruído intolerável identificado em visita; -- custo oculto que destrua a vantagem aparente; -- anúncio sem informação mínima para comparação; -- indícios relevantes de fraude ou inconsistência. - -Um imóvel não deve ser eliminado apenas por falta de dados no anúncio. Nesse caso, classifique-o como pendente de verificação. +Anúncio vendido deve ficar em quarentena histórica, não ser apagado. --- -## 3. Critérios gerais de qualidade - -### 3.1 Planta e funcionalidade +## 3. Critérios gerais -Avaliar: +### Planta e funcionalidade -- distribuição dos cômodos; -- privacidade dos quartos; -- largura de circulação; -- áreas mortas; -- integração social; +- três quartos utilizáveis; +- circulação eficiente; +- privacidade; - capacidade de mobiliamento; - armazenamento; -- número e localização de banheiros; -- ventilação cruzada; +- integração social; - iluminação natural; -- possibilidade de adaptação futura; -- conflito entre portas, móveis e circulação; -- uso real de varandas, quintais e áreas gourmet. +- ventilação cruzada; +- banheiros funcionais; +- possibilidade de adaptação futura. -### 3.2 Estado de conservação +### Conservação e sistemas -Registrar separadamente: +Avaliar separadamente: - estrutura; - elétrica; - hidráulica; -- revestimentos; -- esquadrias; -- telhado; - impermeabilização; +- telhado; +- esquadrias; +- revestimentos; - pintura; -- armários; +- marcenaria; - climatização; -- equipamentos; -- sinais de reforma improvisada. +- sinais de obra improvisada. -Não resumir tudo como “reformado”. Uma reforma estética pode esconder sistemas antigos. +“Reformado” não comprova renovação dos sistemas. -### 3.3 Custos de adequação +### Conforto -Estimar: - -- reparos imediatos; -- intervenções em até dois anos; -- mobiliário obrigatório; -- eletrodomésticos; -- mudança; -- custo de desocupação, quando aplicável; -- custo de tempo e transtorno; -- contingência de obra. - -Aplicar margem de segurança para reformas. Não usar apenas o orçamento mais otimista. - -### 3.4 Conforto ambiental - -Avaliar em horários diferentes: - -- incidência solar; +- insolação; - calor; - ventilação; -- iluminação; -- ruído; +- ruído interno e externo; - odores; - privacidade; -- proximidade de vias; -- fluxo de pedestres; -- iluminação noturna; +- drenagem; - segurança percebida; -- drenagem e risco de alagamento. - -### 3.5 Liquidez e revenda - -Considerar: - -- tipologia; -- padrão da região; -- facilidade de financiamento; -- regularidade documental; -- garagem; -- elevador; -- posição; -- conservação; -- faixa de preço; -- público comprador provável; -- excesso de personalização; -- limitações permanentes de planta. - ---- - -## 4. Cruzeiro Novo +- internet e sinal de celular. -### 4.1 Pontos a registrar +### Custos de adequação -- quadra; -- bloco; -- posição no bloco; -- andar; -- orientação solar; -- vista; -- proximidade de vias e comércio; -- ruído; -- elevador; -- garagem ou estacionamento; -- estado das áreas comuns; -- taxa de condomínio; -- obras previstas; -- idade e conservação do prédio; -- prumadas; -- elétrica; -- fachada; -- acessibilidade; -- área privativa e área total; -- número original de quartos; -- alterações de planta; -- ocupação atual; -- situação documental. - -### 4.2 Dois versus três quartos - -No Cruzeiro, apartamentos anunciados como dois ou três quartos podem ter áreas semelhantes. - -A análise deve verificar: - -- planta original; -- quarto revertido; -- dependência transformada; -- sala dividida; -- ventilação do cômodo adicional; -- dimensão real dos quartos; -- impacto na circulação; -- valor de revenda. - -Não classificar automaticamente três quartos como superior se o terceiro cômodo for inadequado. - -### 4.3 Elevador e garagem - -Ausência de elevador ou garagem é uma concessão relevante, não um detalhe. - -Registrar: - -- andar; -- número de lances de escada; -- acessibilidade futura; -- facilidade de mudança; -- uso por idosos; -- disponibilidade real de estacionamento; -- segurança ao estacionar; -- regras do condomínio. - -O efeito no preço deve ser analisado com imóveis comparáveis. - -### 4.4 Reforma - -Imóveis antigos podem exigir modernização invisível no anúncio. - -Durante a visita, verificar: +Estimar: -- quadro elétrico; -- aterramento; -- tomadas; -- tubulações; -- registros; -- pressão de água; -- vazamentos; -- esquadrias; -- ruído entre unidades; -- estado da laje; -- gás; -- ventilação de banheiros; -- infiltrações em fachadas; -- histórico de obras do bloco. +- reparo imediato; +- obra em até dois anos; +- móveis e eletrodomésticos indispensáveis; +- regularização; +- mudança; +- contingência; +- tempo e transtorno. --- -## 5. Jardins Mangueiral - -### 5.1 Filtro de tipologia +## 4. Jardins Mangueiral -Somente considerar casas com **planta de três quartos**. +### 4.1 Planta original -Casas originalmente de dois quartos devem ser excluídas, mesmo quando reformadas ou anunciadas como tendo três quartos. +Somente casas originalmente de três quartos. -A validação pode usar: +Validar por: -- planta original; +- planta padrão; +- implantação; - posição da escada; - dimensões; - fachada; -- implantação; - documentos; -- comparação com unidades padrão; -- fotografias. +- fotos; +- comparação com unidades conhecidas. -### 5.2 Quintal fechado e ampliações +Quarto adaptado não transforma uma planta original de dois quartos em candidata válida. -A perda do quintal original não é automaticamente um problema. +### 4.2 Quintal e ampliação -A conversão deve ser considerada positiva quando cria: +Conversão positiva: - sala ampliada; -- espaço de convivência; - ambiente de refeições; +- espaço de convivência; - escritório; -- área social ventilada; -- integração útil com a casa; -- armazenamento funcional. - -Penalizar quando a conversão: - -- duplica cozinha ou cooktop sem necessidade; -- cria circulação inútil; -- reduz ventilação e iluminação; -- aumenta calor; -- usa material de baixa qualidade; -- compromete impermeabilização; -- dificulta manutenção; -- cria ambiente sem função clara; -- prejudica privacidade; -- ocupa todo o espaço sem compensação funcional. - -### 5.3 Área gourmet +- armazenamento útil; +- integração ventilada com a casa. + +Conversão negativa: + +- segunda cozinha redundante; +- cooktop sem função clara; +- circulação de baixo valor; +- redução de luz e ventilação; +- calor excessivo; +- impermeabilização duvidosa; +- drenagem comprometida; +- manutenção difícil; +- ocupação total sem ganho funcional. + +### 4.3 Preferências funcionais confirmadas + +- cozinha bem planejada, espaçosa e, idealmente, semi-integrada à área gourmet; +- área gourmet com churrasqueira deve participar do fluxo social da casa, não ficar isolada; +- priorizar casas conservadas e que exijam poucas intervenções antes da mudança; +- boa marcenaria, quartos e banheiros funcionais têm peso material; +- piscina, jacuzzi e banheira não são desejadas e reduzem fortemente a adequação; +- cubas de vidro são indesejadas por limpeza e aparência; +- penalizar marcenaria barata ou degradada, cozinha mal executada e área externa abandonada; +- fechamento em vidro exige teste rigoroso de calor e ventilação pelo risco de efeito estufa; +- quarto convertido em closet é uma concessão quando precisar ser revertido no futuro; +- placas solares são bônus, condicionadas à documentação e ao estado do sistema; +- detalhes estéticos reversíveis, como cortinas e sancas, pesam menos que planta, cozinha, conservação e área social. + +### 4.4 Regularidade + +Confirmar: + +- cobertura e fechamento; +- drenagem e calhas; +- aprovação condominial; +- licenças quando aplicáveis; +- impacto em financiamento e seguro; +- área efetiva e conceito da área anunciada; +- placas solares e homologação; +- piscina, spa e impermeabilização. -Não atribuir valor automático ao rótulo “área gourmet”. +### 4.5 Ruído de vizinhança -Avaliar: +Investigar: -- frequência provável de uso; -- integração com a cozinha; -- redundância de equipamentos; -- exaustão; -- ventilação; -- limpeza; -- circulação; -- capacidade de receber pessoas; -- qualidade da execução; -- manutenção. - -Um segundo cooktop ao lado da cozinha principal pode ser redundante. +- paredes compartilhadas; +- passos e móveis; +- música; +- festas; +- cães; +- crianças; +- área de lazer; +- quadra esportiva; +- comércio; +- motos; +- coleta de lixo; +- obras. -### 5.4 QCs e acesso a serviços +--- -Relatos de moradores usados como referência anedótica: +## 5. Cruzeiro -- QCs 8 e 9: percebidas como mais fortes para acesso prático a comércio e serviços; -- QCs 6 e 7: alternativas consideradas; -- QCs 10 e 11: também consideradas boas. +### 5.1 Planta e quartos -Essas preferências não substituem verificação de campo. +No estoque do Cruzeiro, dois e três quartos podem ter área semelhante e o terceiro cômodo pode ser conversão. -Para cada QC, medir ou registrar: +Confirmar: -- distância a comércio; -- acesso a mercado, farmácia e serviços; -- saída viária; -- tempo em horários relevantes; -- transporte; -- topografia; -- iluminação; -- tráfego interno; -- ruído; -- estacionamento; -- áreas comuns; -- manutenção do condomínio. +- planta original; +- dependência convertida; +- sala dividida; +- ventilação e dimensão do terceiro quarto; +- impacto na circulação e revenda. -### 5.5 Ruído e vizinhança +O ranking corrente prioriza três quartos utilizáveis, mas a contagem anunciada não é suficiente. -Avaliar explicitamente: +### 5.2 Elevador, garagem e andar -- paredes compartilhadas; -- ruído de passos e móveis; -- música; -- festas; -- cães; -- crianças; -- áreas de convivência; -- quadras esportivas; -- comércio; -- portarias; -- vias internas; -- motos; -- coleta de lixo; -- obras; -- templos; -- escolas; -- bares. +Ausência de elevador ou garagem é concessão relevante. -Fazer visitas em mais de um horário quando possível, incluindo noite ou fim de semana. +Avaliar: -Perguntar aos moradores sem depender apenas do corretor. +- número de lances de escada; +- acessibilidade futura; +- mudança e uso por idosos; +- vagas vinculadas ou apenas informais; +- disputa por estacionamento; +- segurança noturna; +- posição do apartamento. -### 5.6 Reformas e regularidade +### 5.3 Prédio e sistemas Verificar: -- fechamento de área externa; -- cobertura; -- drenagem; -- calhas; -- telhado; -- impermeabilização; -- ventilação; -- padrão elétrico; -- hidráulica; -- alterações estruturais; -- aprovação condominial; -- regularidade documental; -- impacto em seguro e financiamento. +- quadro elétrico e aterramento; +- tubulações e registros; +- pressão de água; +- gás; +- prumadas; +- fachada; +- laje e infiltração; +- obras previstas; +- taxas extraordinárias; +- estado das áreas comuns; +- ruído entre unidades. --- -## 6. Checklist de visita +## 6. Fotografias e anúncios -### Antes da visita +As fotos fazem parte da evidência principal. -- salvar anúncio e data; -- registrar preço; -- registrar condomínio e IPTU; -- conferir área e quartos; -- buscar histórico do anúncio; -- verificar anúncios duplicados; -- mapear entorno; -- listar dúvidas. +Procedimento: -### Durante a visita - -- fotografar com autorização; -- registrar ruído com janelas abertas e fechadas; -- testar torneiras, descargas, chuveiros e registros; -- observar umidade e odores; -- verificar tomadas e quadro; -- medir cômodos críticos; -- conferir incidência solar; -- observar circulação; -- avaliar armazenamento; -- verificar sinal de celular e internet; -- examinar garagem ou estacionamento; -- conversar com porteiro ou moradores quando apropriado; -- perguntar motivo da venda; -- perguntar tempo de anúncio; -- perguntar reformas e documentação; -- verificar taxas extraordinárias. - -### Depois da visita +1. abrir a primeira foto atual; +2. procurar selo de vendido, permuta ou negócio fechado; +3. inspecionar galeria completa; +4. comparar imagens com outros anúncios; +5. verificar coerência de planta, estado e área; +6. identificar fotos antigas, decorativas ou de outro imóvel; +7. registrar qualidade e lacunas da evidência. -- registrar impressão no mesmo dia; -- separar fatos de percepções; -- estimar custos; -- comparar com alternativas reais; -- listar riscos; -- definir preço máximo; -- registrar pendências documentais; -- evitar decisão motivada apenas por entusiasmo. +Republicações visualmente equivalentes contam como um imóvel provável. --- -## 7. Negociação +## 7. Checklist de visita -O preço máximo deve considerar: +### Antes -- valor comparável; -- estado; -- custos de compra; -- reforma; -- liquidez; -- concessões; -- risco; -- tempo de anúncio; -- histórico de preço; -- condição de pagamento; -- custo de oportunidade. +- salvar anúncio, preço e data; +- revisar histórico; +- verificar duplicatas; +- mapear localização; +- listar pendências; +- calcular custo total preliminar. -Não negociar com base apenas no percentual de desconto. +### Durante -O desconto nominal deve ser comparado ao custo real de corrigir as deficiências. +- medir cômodos críticos; +- testar torneiras, registros e descargas; +- observar umidade e odores; +- conferir quadro elétrico; +- avaliar sol, calor e ventilação; +- medir ruído; +- conferir garagem ou estacionamento; +- perguntar motivo da venda e tempo de anúncio; +- pedir documentação e histórico de reformas; +- perguntar por taxas extraordinárias e conflitos de vizinhança. ---- +### Depois -## 8. Saída padrão por imóvel - -Cada ficha analítica deve conter: - -- URL e identificador; -- data de coleta; -- região, quadra, bloco ou QC; -- tipologia original; -- área; -- quartos; -- garagem; -- elevador; -- preço; -- condomínio; -- IPTU; -- preço por m² válido ou não; -- histórico de preço; -- possíveis duplicatas; -- pontos fortes; -- pontos fracos; -- reformas; -- custo estimado de adequação; -- riscos; -- pendências; -- posição relativa aos comparáveis; -- preço máximo sugerido, quando houver dados; -- decisão: excluir, monitorar, visitar, negociar ou candidato forte. +- registrar impressão no mesmo dia; +- separar fatos de entusiasmo; +- estimar custo de adequação; +- definir preço máximo; +- classificar: excluir, monitorar, aprofundar, visitar, negociar ou candidato forte. diff --git a/docs/SCRAPER_OPERATIONS.md b/docs/SCRAPER_OPERATIONS.md new file mode 100644 index 0000000..b285356 --- /dev/null +++ b/docs/SCRAPER_OPERATIONS.md @@ -0,0 +1,206 @@ +# Operação do scraper e do banco + +## 1. Arquitetura atual + +Estrutura esperada: + +```text +dfimoveis_data/ +├── dfimoveis.sqlite3 +├── photos/ +│ └── / +├── raw/ +│ ├── listing/ +│ └── search/ +└── browser-profile/ +``` + +O SQLite é a fonte estruturada. Fotos e HTML bruto são evidências complementares essenciais. + +--- + +## 2. Funções já previstas no scraper + +- múltiplas pesquisas; +- paginação com `pagina=N`; +- requisições assíncronas; +- concorrência controlada; +- retentativas; +- extração de páginas de anúncio; +- download de todas as fotos; +- armazenamento em SQLite; +- observações históricas e mudanças; +- HTML bruto comprimido; +- marcação de anúncios removidos ou inativos; +- fallback opcional por Playwright. + +Não simplificar o scraper de modo a perder histórico, fotos ou HTML bruto. + +--- + +## 3. Cloudflare e 403 + +Foi confirmado desafio JavaScript do Cloudflare, com referências a `challenges.cloudflare.com` e `cf-ray` associado a GRU. + +Consequências: + +- `httpx` isolado não resolve desafio JavaScript; +- trocar apenas User-Agent, aumentar retries ou reduzir concorrência não garante acesso; +- o scraper deve tentar o cliente HTTP normal e usar Playwright como fallback quando houver 403 ou challenge. + +### Playwright + +Configuração operacional: + +- Chromium visível no primeiro uso; +- perfil persistente em `dfimoveis_data/browser-profile`; +- reutilização de cookies e sessão; +- resolução manual do challenge quando necessário; +- depois, possibilidade de execução automatizada enquanto a sessão permanecer válida; +- não usar modo headless no primeiro desafio. + +O objetivo é usar uma sessão legítima do navegador, não tentar derrotar ou explorar mecanismos de proteção. + +Respeitar termos aplicáveis, limites de requisição e carga do site. + +--- + +## 4. User-Agent e sessão + +- usar `DFIMOVEIS_USER_AGENT` configurável; +- preservar cookies e perfil local; +- não gravar credenciais no repositório; +- não compartilhar o diretório `browser-profile`; +- incluir perfis e cookies no `.gitignore`. + +--- + +## 5. Banco em análise + +Caminho: + +```text +dfimoveis_data/dfimoveis.sqlite3 +``` + +Abrir em modo somente leitura: + +```python +connection = sqlite3.connect( + "file:dfimoveis_data/dfimoveis.sqlite3?mode=ro", + uri=True, +) +connection.execute("PRAGMA query_only = ON") +``` + +Não executar análises que escrevam no banco. + +Para transformações: + +- exportar Parquet/CSV; +- criar `data/derived/analytics.sqlite`; +- ou trabalhar em uma cópia consistente. + +--- + +## 6. Snapshot de 22/07/2026 + +- 162 anúncios; +- 637 observações históricas; +- 7.457 registros de foto: 3.521 da galeria primária e 3.936 evidências legadas excluídas da análise; +- Mangueiral: 95 anúncios acumulados, 78 ativos e 17 inativos; +- Cruzeiro Novo: 67 acumulados, 63 ativos e 4 inativos; +- coleta entre 13 e 22/07/2026; +- a partir da execução 21, somente o Mangueiral permanece no arquivo de buscas. + +A cobertura é curta. Não inferir liquidez, sazonalidade ou tendência de preço. + +O histórico legado contém mudanças infladas por campos textuais instáveis. O schema v2 usa `stable_content_hash`, exclui ruído de interface e registra mudanças materiais futuras em `listing_change_events`. + +### Migração v2 + +- backup anterior: `dfimoveis_data/backups/dfimoveis_before_schema_v2_20260722.sqlite3`; +- migração idempotente: `python scripts/migrate_dfimoveis_schema_v2.py`; +- nunca apagar fotos legadas: usar `v_primary_photos` ou `is_primary_gallery=1` nas análises; +- usar `creci_normalized`, `address_normalized` e `neighborhood_normalized`, preservando os campos brutos; +- consultar `v_listing_current_availability` e `v_open_data_quality_issues` para triagem; +- futuras execuções registram buscas e configuração em `crawl_runs`. + +--- + +## 7. Qualidade e deduplicação + +O scraper e a análise devem preservar três níveis: + +- anúncio; +- observação histórica; +- imóvel físico provável. + +Sinais de duplicidade: + +- imagens iguais ou muito semelhantes; +- mesma implantação; +- texto quase idêntico; +- mesmo endereço; +- mesmos quartos, área e preço; +- anúncios de corretores diferentes. + +Não apagar duplicatas. Registrar grupos, confiança e anúncio de referência. + +--- + +## 8. Disponibilidade e “vendido” + +Auditar: + +- primeira foto; +- descrição; +- status estruturado; +- atividade na coleta. + +Estados sugeridos: + +- ativo; +- inativo; +- vendido visualmente indicado; +- negócio fechado declarado; +- republicado; +- duplicata provável; +- status desconhecido. + +Selo visual é evidência operacional. Não prova transação registral. + +--- + +## 9. Observabilidade + +Cada execução deve registrar: + +- início e fim; +- versão do scraper; +- configuração; +- pesquisas executadas; +- páginas solicitadas e concluídas; +- status HTTP; +- desafios Cloudflare; +- anúncios vistos; +- fotos baixadas; +- erros; +- tempo de execução; +- número de anúncios marcados inativos. + +Diferenciar falha de coleta de redução real de estoque. + +--- + +## 10. Segurança operacional + +- não versionar banco, fotos, HTML bruto, cookies ou perfil de navegador; +- não expor tokens e sessões; +- limitar concorrência; +- usar backoff; +- evitar coleta agressiva; +- não remover dados históricos; +- manter backup antes de migrações; +- testar mudanças em banco de desenvolvimento; +- nunca migrar o banco original durante uma análise. diff --git a/reports/creci_26903_mangueiral/README.md b/reports/creci_26903_mangueiral/README.md new file mode 100644 index 0000000..060ff6a --- /dev/null +++ b/reports/creci_26903_mangueiral/README.md @@ -0,0 +1,55 @@ +# Imóveis do CRECI 26.903 — Jardins Mangueiral + +**Snapshot:** 21/07/2026 +**Fonte:** `dfimoveis_data/dfimoveis.sqlite3`, aberto somente para leitura. + +## Pergunta + +Quais anúncios de imóveis no Jardins Mangueiral estão associados ao CRECI **26.903**, separados entre vendidos e disponíveis? + +## Método e ressalva + +O portal apresenta o registro como `26.903`. O campo `creci` foi normalizado para a busca removendo pontos e espaços, porque seu conteúdo bruto inclui texto residual da página. Foram encontrados **15 anúncios acumulados**, todos ainda marcados como ativos pelo coletor no snapshot. + +A separação abaixo usa a primeira foto corrente: + +- **vendido:** há selo explícito “VENDIDO”, “negócio fechado” ou equivalente; +- **disponível:** anúncio ativo e sem selo visual de venda na primeira foto. + +“Disponível” significa apenas **aparentemente disponível no portal**. É necessário confirmar diretamente com o anunciante. Da mesma forma, o selo de vendido é evidência operacional, não prova registral da transação. + +## Vendidos — 8 anúncios + +| Anúncio | QC | Preço anunciado | Área estruturada | Evidência | +|---:|---:|---:|---:|---| +| [1366801](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-11-1366801) | 11 | R$ 575 mil | 68 m² | selo na primeira foto | +| [1346017](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-1346017) | 10 | R$ 577 mil | 68 m² | selo na primeira foto | +| [1349519](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-1349519) | 14 | R$ 640 mil | 68 m² | selo na primeira foto | +| [1356197](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-4-1356197) | 4 | R$ 649 mil | 68 m² | selo na primeira foto | +| [1346231](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-1346231) | 10 | R$ 660 mil | 68 m² | selo na primeira foto | +| [1352943](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-3-1352943) | 3 | R$ 670 mil | 68 m² | selo na primeira foto | +| [1351729](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-9-1351729) | 9 | R$ 680 mil | 68 m² | selo na primeira foto | +| [1362968](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-13-1362968) | 13 | R$ 730 mil | 68 m² | selo na primeira foto | + +## Aparentemente disponíveis — 7 anúncios + +| Anúncio | QC | Preço anunciado | Área estruturada | Situação no snapshot | +|---:|---:|---:|---:|---| +| [1173275](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-15-1173275) | 15 | R$ 549 mil | 68 m² | ativo, sem selo de venda | +| [1336887](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-condominio-jardins-mangueiral-1336887) | não informado | R$ 550 mil | 65 m² | ativo, sem selo de venda | +| [1363016](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-1363016) | 14 | R$ 550 mil | 68 m² | ativo, sem selo de venda | +| [1345134](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-11-1345134) | 11 | R$ 640 mil | 68 m² | ativo, sem selo de venda | +| [1324014](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-12-rua-k-1324014) | 12 | R$ 649 mil | 68 m² | ativo, sem selo de venda | +| [1358920](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-13-1358920) | 13 | R$ 675 mil | 68 m² | ativo, sem selo de venda | +| [1278187](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-1278187) | 10 | R$ 690 mil | 68 m² | ativo, sem selo de venda | + +## Leitura prática + +- O CRECI 26.903 concentra **8 de 15 anúncios com indicação visual de venda** no snapshot, ou 53,3% do recorte. +- Os oito continuam ativos tecnicamente no portal; portanto, o estado estruturado isolado superestima a oferta desse anunciante. +- Não é possível concluir velocidade de venda: o banco começou a observar esses anúncios em 13/07/2026, e não contém a data da negociação. +- Os anúncios podem representar estoque captado pelo mesmo corretor ou imobiliária, não necessariamente imóveis de sua propriedade. + +## Reprodução + +A consulta usada está em [`query.sql`](query.sql). A classificação visual está registrada em [`results.csv`](results.csv) e não é inferida pelo SQL. diff --git a/reports/creci_26903_mangueiral/query.sql b/reports/creci_26903_mangueiral/query.sql new file mode 100644 index 0000000..5337d5d --- /dev/null +++ b/reports/creci_26903_mangueiral/query.sql @@ -0,0 +1,15 @@ +-- Executar exclusivamente em conexão read-only. +SELECT + listing_id, + price_brl, + area_m2, + bedrooms, + address, + inactive_at, + first_seen_at, + last_seen_at, + url +FROM listings +WHERE lower(url) LIKE '%jardins-mangueiral%' + AND creci_normalized = '26903' +ORDER BY price_brl, listing_id; diff --git a/reports/creci_26903_mangueiral/results.csv b/reports/creci_26903_mangueiral/results.csv new file mode 100644 index 0000000..6f52190 --- /dev/null +++ b/reports/creci_26903_mangueiral/results.csv @@ -0,0 +1,16 @@ +listing_id,classification,qc,price_brl,area_m2,database_active,first_photo_sale_marker,url +1366801,sold_visual,11,575000,68,true,true,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-11-1366801 +1346017,sold_visual,10,577000,68,true,true,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-1346017 +1349519,sold_visual,14,640000,68,true,true,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-1349519 +1356197,sold_visual,4,649000,68,true,true,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-4-1356197 +1346231,sold_visual,10,660000,68,true,true,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-1346231 +1352943,sold_visual,3,670000,68,true,true,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-3-1352943 +1351729,sold_visual,9,680000,68,true,true,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-9-1351729 +1362968,sold_visual,13,730000,68,true,true,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-13-1362968 +1173275,apparently_available,15,549000,68,true,false,https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-15-1173275 +1336887,apparently_available,,550000,65,true,false,https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-condominio-jardins-mangueiral-1336887 +1363016,apparently_available,14,550000,68,true,false,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-1363016 +1345134,apparently_available,11,640000,68,true,false,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-11-1345134 +1324014,apparently_available,12,649000,68,true,false,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-12-rua-k-1324014 +1358920,apparently_available,13,675000,68,true,false,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-13-1358920 +1278187,apparently_available,10,690000,68,true,false,https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-1278187 diff --git a/reports/cruzeiro_top10/README.md b/reports/cruzeiro_top10/README.md deleted file mode 100644 index 7bb3b99..0000000 --- a/reports/cruzeiro_top10/README.md +++ /dev/null @@ -1,172 +0,0 @@ -# Ranking preliminar — apartamentos no Cruzeiro Novo - -**Data de referência do snapshot:** 17/07/2026 -**Relatório revisado:** 17/07/2026 -**Unidade principal:** imóvel físico provável, não snapshot nem anúncio isolado -**Finalidade:** priorizar visitas; não estimar preço negociado nem substituir vistoria - -## Pergunta - -Quais são os dez imóveis do Cruzeiro Novo que mais merecem atenção segundo as preferências e regras do projeto, dando às fotografias importância comparável à dos dados estruturados? - -## Universo e método - -Foram avaliados os 65 anúncios encontrados pela busca: - -`https://www.dfimoveis.com.br/venda/df/cruzeiro/novo/apartamento/3-quartos` - -A coleta cobre um único dia e um único portal. O banco foi aberto somente em leitura. Os campos foram complementados com os HTMLs brutos, pois localização e descrição no SQLite têm limitações já documentadas em `docs/ACTUAL_SCHEMA.md`. - -Na coleta concluída em 17/07, os 65 anúncios do Cruzeiro permaneceram ativos e nenhum anúncio novo entrou. O único preço alterado foi o do anúncio `1372539`, de R$ 572.500 para R$ 569.000; ele continua fora do ranking porque a descrição confirma planta de três quartos convertida em dois. Assim, a ordem foi mantida após revisão das mudanças materiais. - -Não foi criada pontuação numérica, pois os pesos não foram aprovados. A ordem é uma **prioridade de visita ajustada por risco**, aplicando: - -1. critérios eliminatórios e inconsistências; -2. planta funcional de três quartos; -3. indícios de reforma relevante ou custos escondidos; -4. iluminação, ventilação, distribuição e conservação visíveis; -5. andar, elevador e garagem; -6. preço, área e condomínio anunciados; -7. qualidade e completude da evidência. - -### Revisão fotográfica - -Em 17/07/2026, a primeira foto dos dez escolhidos foi auditada especificamente para marcas de “vendido” ou “negócio fechado”. Nenhuma das dez apresentou esse sinal. - -A primeira passagem examinou até 16 imagens de cada um dos 65 anúncios, totalizando 1.029 arquivos. Depois, foram examinadas todas as 532 fotos dos 17 finalistas. Descontada a sobreposição entre as etapas, 1.289 arquivos distintos foram efetivamente vistos. - -As imagens foram usadas para observar conservação, coerência da reforma, luz, ventilação aparente, tamanho relativo dos quartos, circulação, integração social, cozinha, banheiros, área de serviço, fachada e estacionamento. Fotografias não permitem validar elétrica, hidráulica, infiltração, ruído, estrutura ou documentação. - -Muitos anúncios incluem, depois das fotos do imóvel, imagens genéricas do portal, logos e até cartões de outros imóveis marcados como “vendido”. Esses ativos foram desconsiderados na avaliação visual do apartamento. - -## Ranking - -### 1. Anúncio 1345146 — SHCES 1207, bloco A - -- **Anunciado:** R$ 670.000; 65 m²; condomínio R$ 605; 3 quartos, 1 suíte; 4º andar. -- **Por que lidera:** é o conjunto mais equilibrado entre reforma pronta, planta preservada e acessibilidade. O anúncio declara elevador, diferencial forte para uso de longo prazo. -- **Fotos:** reforma coerente e bem conservada; cozinha planejada, área de serviço separada, dois banheiros atualizados, três quartos reconhecíveis e boa luz. Os dormitórios e a área de serviço parecem compactos, mas funcionais. -- **Pendências:** confirmar funcionamento/obras do elevador, posição solar, área da matrícula, estacionamento/garagem e sistemas elétrico e hidráulico. -- **Ação:** candidato forte; visitar primeiro. -- **URL:** https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1207-bloco-a-1345146 - -### 2. Anúncio 1232283 — SHCES 309, bloco B - -- **Anunciado:** R$ 600.000; 70 m²; condomínio R$ 497; 3 quartos, 1 suíte; 3º andar; 2 vagas; nascente e vazado. -- **Por que está no topo:** maior área entre os primeiros colocados, preço competitivo, duas vagas anunciadas e reforma recente. O anúncio informa vista livre e ocupação imediata. -- **Fotos:** ambientes claros, armários abundantes, dois banheiros modernos e reforma consistente. Um dos dormitórios parece estreito; a qualidade da circulação precisa ser sentida presencialmente. -- **Pendências:** confirmar se as duas vagas são privativas/vinculadas e se há elevador — ele não é informado. No 3º andar, sua ausência é concessão forte. -- **Ação:** candidato forte; visitar, condicionado à confirmação das vagas e acessibilidade. -- **URL:** https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-309-bloco-b-1232283 - -### 3. Anúncio 1357415 — SHCES 1109 - -- **Anunciado:** R$ 630.000; 67,2 m²; condomínio R$ 350; 3 quartos, 1 suíte; 4º andar; nascente e vazado. -- **Por que se destaca:** reforma visualmente mais homogênea que a maioria, bloco revitalizado, vista livre, boa ventilação e condomínio anunciado baixo. -- **Fotos:** sala social bem resolvida, cozinha planejada, marcenaria útil, dois banheiros atualizados, quartos claros e conservação convincente. Não aparecem sinais evidentes de obra imediata. -- **Pendências:** não há elevador informado e o imóvel está no 4º andar; confirmar isso antes da visita. Verificar estacionamento, escopo real da reforma e autenticidade do condomínio de R$ 350. -- **Ação:** candidato forte se a escada for aceitável; caso contrário, rebaixar fortemente. -- **URL:** https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1109-1357415 - -### 4. Anúncio 1357633 — SHCES 309 - -- **Anunciado:** R$ 600.000; 64 m²; 3 quartos; 2º andar; nascente, vazado e de canto. -- **Por que se destaca:** o anúncio declara reforma de elétrica, hidráulica, pisos e acabamentos, além de documentação regular. O 2º andar reduz o impacto provável da ausência de elevador. -- **Fotos:** acabamento moderno e uniforme, boa marcenaria, iluminação natural e três dormitórios aparentes. A planta permanece convencional e funcional; não há suíte anunciada, mas há banheiro de serviço. -- **Pendências:** condomínio, IPTU, garagem e elevador estão ausentes. Confirmar notas/escopo da reforma e ventilação dos banheiros. -- **Ação:** candidato forte; visitar. -- **URL:** https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-309-1357633 - -### 5. Anúncio 1376958 — SHCES 911, bloco B - -- **Anunciado:** R$ 599.000; 62 m²; condomínio R$ 600; 3 quartos, 1 suíte; 2º andar; nascente e vazado. -- **Por que se destaca:** combina preço baixo no grupo reformado, andar razoável, suíte e ventilação cruzada declarada. -- **Fotos:** sala ampla para a metragem, cozinha e banheiros atualizados, boa vista e luz. O quarto com beliche aparenta ser pequeno, mas utilizável; a área de serviço é funcional, embora simples. -- **Pendências:** prédio sem elevador segundo a descrição e sem garagem informada. Confirmar área privativa, ruído da via visível e o que está incluído no condomínio. -- **Ação:** visitar. -- **URL:** https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-911-bloco-b-1376958 - -### 6. Anúncio 1345903 — SHCES 1303 - -- **Anunciado:** R$ 565.000; 64,5 m²; condomínio R$ 529; 3 quartos, 1 suíte; 1º andar; vazado. -- **Por que se destaca:** menor preço do top 10, acessibilidade melhor por estar no 1º andar, suíte e informação explícita de elétrica e esquadrias novas. -- **Fotos:** imóvel cuidado e aparentemente habitável sem obra imediata. Banheiros estão atualizados, mas cozinha, pisos e parte da marcenaria têm linguagem mais antiga. A planta parece íntegra e os três quartos são visíveis. -- **Pendências:** somente estacionamento público; confirmar ventilação, ruído do 1º andar, hidráulica e segurança das janelas. -- **Ação:** visitar com foco em custo real de modernização opcional. -- **URL:** https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1303-1345903 - -### 7. Anúncio 1339324 — SHCES 703 - -- **Anunciado:** R$ 665.000; 64 m²; condomínio R$ 390; 3 quartos, 1 suíte; 3º andar. -- **Por que se destaca:** reforma pronta, climatização, condomínio anunciado baixo e excelente aproveitamento de marcenaria. -- **Fotos:** uma das melhores apresentações: integração social coerente, cozinha funcional, dois banheiros bem executados, três quartos utilizáveis, boa iluminação e áreas comuns cuidadas. A circulação íntima parece estreita. -- **Pendências:** elevador, garagem, posição solar e escopo técnico da reforma não são informados. O 3º andar sem elevador seria concessão relevante. -- **Ação:** visitar após esclarecer acessibilidade e estacionamento. -- **URL:** https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-703-1339324 - -### 8. Imóvel provável dos anúncios 1370889 e 1375200 — SHCES 207 - -- **Anunciado:** R$ 695.000; 62 m²; condomínio entre R$ 435 e R$ 453; 3 quartos, 1 suíte. Um anúncio informa 2º andar. -- **Por que se destaca:** prédio reformado, planta social integrada, suíte e condição pronta para morar. -- **Fotos:** os dois anúncios mostram o mesmo apartamento com alta confiança visual. Sala/cozinha integradas funcionam bem, há área de serviço independente, dois banheiros atualizados e três dormitórios. A reforma parece consistente, embora bastante personalizada. -- **Pendências:** confirmar formalmente que os anúncios são da mesma unidade, andar, orientação solar, área, garagem e elevador. A duplicidade não deve inflar a oferta. -- **Ação:** visitar uma única vez após confirmar o anúncio primário. -- **URLs:** https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-207-1370889 e https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-207-1375200 - -### 9. Anúncio 1372268 — SHCES 305, bloco I - -- **Anunciado:** R$ 595.000; 62,61 m²; condomínio R$ 460; 3 quartos; 1º andar; canto e vazado; 2 vagas. -- **Por que entra:** duas vagas anunciadas e 1º andar são diferenciais duráveis. O preço deixa margem maior para atualização que os reformados mais caros. -- **Fotos:** planta convencional, clara e aparentemente conservada; cozinha e banheiros são funcionais, porém mais antigos. Não há sinal visual de obra estrutural, mas a modernização seria maior do que nos primeiros colocados. -- **Pendências:** confirmar documentalmente as duas vagas, ventilação, elétrica, hidráulica e orçamento real de adequação. -- **Ação:** visitar como alternativa de valor; não assumir que o desconto cobre reforma sem orçamento. -- **URL:** https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-305-bloco-i-1372268 - -### 10. Anúncio 1373131 — SHCES 305 - -- **Anunciado:** R$ 725.000; 65 m²; condomínio R$ 420; 3 quartos; 2º andar; nascente e vazado; sem elevador. -- **Por que entra:** é a reforma tecnicamente mais bem descrita: elétrica e hidráulica renovadas, projeto de arquiteta, boa orientação e ventilação cruzada. -- **Fotos:** execução visual limpa e consistente, cozinha e banheiro novos, três quartos preservados e boa luminosidade. Não possui suíte anunciada e a linguagem totalmente branca deve ser avaliada sem o efeito de grande-angular. -- **Pendências:** não há garagem informada; preço é alto para unidade sem suíte, elevador ou vaga. Confirmar documentação da reforma e medidas reais dos ambientes. -- **Ação:** visitar somente se a condição pronta justificar o prêmio pedido. -- **URL:** https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-305-1373131 - -## Quase entraram - -- **[1382466](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-101-bloco-c-1382466), R$ 650.000:** boa reforma aparente e uma vaga, mas faltam fotos da cozinha e informações de andar, elevador e orientação; aprofundar antes de substituir alguém do top 10. -- **[1290510](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-911-bloco-a-1290510), R$ 640.000:** três quartos com suíte, vazado e reformado, mas fica no 4º andar sem elevador informado e os valores de condomínio/IPTU foram claramente extraídos como R$ 1; precisa de confirmação. -- **[1371813](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1109-bloco-d-1371813), R$ 709.000:** reforma moderna e 68 m², mas o conjunto de fotos é curto e não esclarece bem três quartos, área de serviço, andar, garagem ou elevador. - -## Quarentenas e exclusões relevantes - -- **1373346:** é um imóvel no Noroeste capturado indevidamente pela busca; excluído. -- **1212351, 1338088, 1259968, 1315328 e 1372539:** planta de três quartos convertida em dois ou sala/escritório; não priorizados para residência de longo prazo. -- **1313649:** anunciado na descrição como dois quartos apesar do campo estruturado indicar três; condomínio de R$ 1.172; excluído até esclarecer planta. -- **1370861:** três quartos originais transformados em suíte master e escritório; não atende à funcionalidade desejada. -- **1365929, 1161400, 1278826 e similares:** fotos e descrição indicam reforma relevante, sem desconto claramente suficiente frente às alternativas prontas. -- **1366910, 1372290 e 1383534:** 22–35 fotos visualmente similares indicam o mesmo imóvel provável, mas os anúncios divergem entre SHCES 207 e SHCES 303 e entre 63 e 74 m². O conjunto seria competitivo, porém permanece em quarentena até confirmar endereço, área e anúncio válido. -- **1370948, 1371797 e 1372167:** grupo provável de anúncios duplicados, sem vantagem suficiente sobre o top 10. -- **1357834 e 1358242:** duplicata provável; há ainda um terceiro anúncio visualmente semelhante, 1382413. -- **1372907, 1348535 e 1380850:** elevador, garagem ou área podem ser atrativos, mas os preços de R$ 820 mil a R$ 990 mil não vêm acompanhados de vantagem funcional suficiente para superar as opções anteriores. A conclusão financeira depende de atualização dos saldos e limites do usuário. - -Uma imagem com selo “vendido” foi tratada como sinal de inconsistência, não como prova de venda, porque muitos anúncios contêm ativos genéricos de outros imóveis. - -## Limitações e verificações para visita - -O ranking é sensível a cinco informações ainda não confirmadas: tolerância pessoal a escadas, existência jurídica das vagas, conceito correto de área, qualidade invisível das reformas e limite financeiro atual. Antes de qualquer proposta: - -1. conferir matrícula, área privativa e vagas; -2. testar elétrica, hidráulica, pressão, esquadrias e sinais de infiltração; -3. medir os três quartos e validar que permanecem funcionais; -4. visitar em horário de tráfego e à noite para ruído e estacionamento; -5. verificar elevador, obras e atas do condomínio; -6. confirmar condomínio, IPTU, taxas extras e orientação solar; -7. comparar preço máximo somente depois de atualizar recursos, FGTS, reserva e prestação confortável. - -## Reprodutibilidade - -- `analysis.py`: extrai banco e HTMLs em leitura, produzindo TSV. -- `photo_similarity.py`: sinaliza duplicatas por hash visual simples; os resultados exigem revisão humana. -- `query.sql`: consultas principais de universo e qualidade. -- `parameters.json`: parâmetros e fingerprint do snapshot. -- `results.csv`: ranking em formato tabular. diff --git a/reports/cruzeiro_top10/__pycache__/analysis.cpython-314.pyc b/reports/cruzeiro_top10/__pycache__/analysis.cpython-314.pyc deleted file mode 100644 index c945a61..0000000 Binary files a/reports/cruzeiro_top10/__pycache__/analysis.cpython-314.pyc and /dev/null differ diff --git a/reports/cruzeiro_top10/__pycache__/photo_similarity.cpython-314.pyc b/reports/cruzeiro_top10/__pycache__/photo_similarity.cpython-314.pyc deleted file mode 100644 index e7f824e..0000000 Binary files a/reports/cruzeiro_top10/__pycache__/photo_similarity.cpython-314.pyc and /dev/null differ diff --git a/reports/cruzeiro_top10/parameters.json b/reports/cruzeiro_top10/parameters.json deleted file mode 100644 index 3c49b3d..0000000 --- a/reports/cruzeiro_top10/parameters.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "analysis_date": "2026-07-17", - "listing_data_reference_date": "2026-07-17", - "database_path": "dfimoveis_data/dfimoveis.sqlite3", - "database_main_file_sha256": "7a5102a62bc66a344bd9440fa36301d10a57711bcdd263b767b65e88f70957f4", - "logical_snapshot_sha256": "fe604aab8af7f67c833e6de2a0fc81c7dc2950ca440ad7b23ebd03d0c2546188", - "database_mode": "read_only_transaction_with_wal", - "search_url_fragment": "/cruzeiro/novo/", - "listing_limit": 100, - "observed_listing_count": 65, - "database_crawl_run_count": 16, - "active_listing_count": 65, - "new_listing_count_since_previous_report": 0, - "material_price_change_count": 1, - "ranking_unit": "probable_physical_property", - "numeric_score_used": false, - "photo_first_pass_limit_per_listing": 16, - "photo_finalist_count": 17, - "photo_files_reviewed_distinct": 1289, - "first_photo_sale_marker_audit_count": 10, - "visually_unavailable_listing_ids": [] -} diff --git a/reports/cruzeiro_top10/results.csv b/reports/cruzeiro_top10/results.csv deleted file mode 100644 index 1182129..0000000 --- a/reports/cruzeiro_top10/results.csv +++ /dev/null @@ -1,11 +0,0 @@ -rank,representative_listing_id,probable_duplicate_ids,price_brl,area_m2,bedrooms,suites,floor,elevator,parking_spaces,decision -1,1345146,,670000,65,3,1,4,yes,,candidato forte -2,1232283,,600000,70,3,1,3,unknown,2,candidato forte -3,1357415,,630000,67.2,3,1,4,unknown,,candidato forte condicionado a escadas -4,1357633,,600000,64,3,0,2,unknown,,visitar -5,1376958,,599000,62,3,1,2,no,,visitar -6,1345903,,565000,64.5,3,1,1,unknown,0,visitar -7,1339324,,665000,64,3,1,3,unknown,,visitar após esclarecer acessibilidade -8,1370889,1375200,695000,62,3,1,2,unknown,,visitar uma única vez -9,1372268,,595000,62.61,3,0,1,unknown,2,visitar como alternativa de valor -10,1373131,,725000,65,3,0,2,no,,visitar se o prêmio pela reforma for aceitável diff --git a/reports/cruzeiro_top15/README.md b/reports/cruzeiro_top15/README.md new file mode 100644 index 0000000..cddfd78 --- /dev/null +++ b/reports/cruzeiro_top15/README.md @@ -0,0 +1,64 @@ +# Top 15 — Cruzeiro Novo + +**Snapshot:** 21/07/2026 + +**Objetivo:** priorizar investigação para moradia de 10–20 anos, mantendo o Cruzeiro como alternativa secundária e oportunística; preço anunciado não é preço negociado. + +## Universo e método + +O banco `dfimoveis_data/dfimoveis.sqlite3` foi aberto em modo somente leitura (`mode=ro`, `PRAGMA query_only=ON`). O snapshot contém 161 anúncios, 562 observações históricas e 7.363 fotos; no recorte do Cruzeiro Novo há 67 anúncios acumulados, 63 ativos e 4 inativos. A coleta cobre 13–21/07/2026, período curto demais para inferir liquidez. + +Em 21/07 entraram `1381514` e `1400223`; `1375199` e `1383814` ficaram inativos. O primeiro novo anúncio é reformado, mas está no 4º andar e não informa elevador ou vaga. O segundo custa R$ 495 mil e está no 2º andar, porém as fotos mostram necessidade de reforma ampla. Ambos foram incluídos como investigações condicionadas, não como candidatos fortes. + +O ranking considera três quartos utilizáveis, funcionalidade, condição aparente, iluminação/ventilação, acessibilidade futura, elevador, natureza da vaga, custo de adequação e qualidade da evidência. Não usa preço por m², pois área e qualidade dos campos não são uniformes. Republicações visualmente equivalentes contam como um imóvel provável. A falta de informação é marcada como pendência, nunca como aprovação. + +## Auditoria da primeira foto + +A primeira foto corrente dos finalistas, dos dois novos anúncios e de `1263868` foi aberta e inspecionada para “vendido”, “negócio fechado” ou equivalente. O anúncio `1263868`, ainda ativo no banco, continua com **VENDIDO** na foto principal e permanece em quarentena. Nenhum dos 15 colocados apresenta esse indicativo. A imagem é evidência operacional de indisponibilidade, não prova registral da venda. + +A triagem perceptual foi reexecutada com Pillow 12.3.0 e confirmou os principais grupos de republicação já documentados. Entre os finalistas, `1348535` teve somente três fotos semelhantes às de `1370861`; os endereços distintos (SHCES 1307 e 913) não sustentam deduplicação. O ranking permaneceu inalterado. + +Todos os classificados continuam com a tipologia original de três quartos apenas como **provável e pendente de confirmação**. A contagem estruturada, isoladamente, não prova que o terceiro quarto seja original e funcional. + +## Ranking + +| # | Anúncio | Local | Preço | Área informada | Por que priorizar | Principal pendência | +|---:|---|---|---:|---:|---|---| +| 1 | [1345146](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1207-bloco-a-1345146) | SHCES 1207 A | R$ 670 mil | 65 m² | Reforma coerente, suíte e elevador anunciado | Vaga, matrícula e sistemas | +| 2 | [1357415](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1109-1357415) | SHCES 1109 | R$ 630 mil | 67,2 m² | Boa reforma, suíte, nascente e vazado | Confirmar elevador | +| 3 | [1357633](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-309-1357633) | SHCES 309 | R$ 600 mil | 64 m² | Reforma uniforme e sistemas renovados declarados | Elevador, garagem e comprovação da obra | +| 4 | [1376958](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-911-bloco-b-1376958) | SHCES 911 B | R$ 599 mil | 62 m² | Reformado, nascente, vazado e suíte | Sem elevador; garagem não informada | +| 5 | [1345903](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1303-1345903) | SHCES 1303 | R$ 565 mil | 64,5 m² | Primeiro andar e preço competitivo | Sem garagem; ruído e segurança | +| 6 | [1339324](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-703-1339324) | SHCES 703 | R$ 665 mil | 64 m² | Integração social, suíte e boa apresentação | Andar, elevador e garagem | +| 7 | [1370889](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-207-1370889) / [1375200](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-207-1375200) | SHCES 207 | R$ 695 mil | 62 m² | Reformado e com suíte | Duplicata provável; andar, elevador e vaga | +| 8 | [1372268](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-305-bloco-i-1372268) | SHCES 305 I | R$ 595 mil | 62,61 m² | Primeiro andar e duas vagas anunciadas | Provar vagas e orçar modernização | +| 9 | [1373131](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-305-1373131) | SHCES 305 | R$ 725 mil | 65 m² | Reforma tecnicamente bem descrita | Sem elevador/garagem e preço alto | +| 10 | [1381514](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-301-1381514) | SHCES 301 | R$ 690 mil | 63 m² estruturados; 93 m² nos detalhes | Reforma completa aparente, boa marcenaria e três quartos fotografados | 4º andar; elevador, vaga e conceito de área não informados | +| 11 | [1382466](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-101-bloco-c-1382466) | SHCES 101 C | R$ 650 mil | 62 m² | Boa reforma aparente e uma vaga | Galeria curta; andar e elevador ausentes | +| 12 | [1290510](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-911-bloco-a-1290510) | SHCES 911 A | R$ 640 mil | 62 m² | Suíte, vazado e reformado | 4º andar; condomínio/IPTU extraídos como R$ 1 | +| 13 | [1371813](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1109-bloco-d-1371813) | SHCES 1109 D | R$ 709 mil | 68 m² | Reforma moderna e área acima do padrão | Fotos não comprovam toda a planta, vaga ou elevador | +| 14 | [1400223](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-609-bloco-d-1400223) | SHCES 609 D | R$ 495 mil | 62,61 m² | 2º andar, boa luz e preço com margem para obra | Reforma ampla, vaga/elevador ausentes e sistemas antigos | +| 15 | [1369327](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-203-bloco-g-1369327) | SHCES 203 G | R$ 490 mil | 62 m² | Vaga e preço com margem para adequação | Estado interno, 4º andar e ausência de elevador | + +## Quase entraram + +- [1375154](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1205-1375154), R$ 550 mil: 67,2 m² e boa luminosidade, mas pede modernização e confirmação de andar/vaga. +- [1370890](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-105-1370890), R$ 560 mil: primeiro andar e DCE, porém condição mais básica e sem garagem informada. +- [1368610](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-309-1368610), R$ 579,9 mil: boa distribuição e melhorias declaradas; falta vantagem clara frente aos classificados. +- [1370891](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-207-1370891), R$ 520 mil: vazado e de preço baixo, mas sem vaga e ainda dependente de modernização; saiu apenas pela entrada de evidência nova. + +## Quarentenas e limitações + +- `1232283` e `1345890` ficaram inativos em 20/07; `1375199` e `1383814`, em 21/07. A ausência da busca não prova venda. +- `1263868` foi retirado por “VENDIDO” na primeira foto. `1322206` também declara venda fechada na descrição. +- `1212351`, `1338088`, `1259968`, `1315328`, `1372539`, `1313649` e `1370861` têm conversão ou conflito relevante de planta. +- Os grupos `1366910`/`1372290`/`1383534`, `1370948`/`1371797`/`1372167` e `1357834`/`1358242`/`1382413` são duplicatas prováveis ou têm endereço/área divergentes. +- O ranking serve para ordenar investigação. Andar, elevador, vaga, matrícula, instalações, ruído, insolação e custo de obra exigem confirmação. + +## Próxima ação + +Solicitar, antes de cada visita, planta ou matrícula, andar, existência de elevador, natureza jurídica da vaga, atas recentes do condomínio e histórico de elétrica/hidráulica. As posições 13–15 são alternativas de preço: só avançam se orçamento de reforma, escadas e ausência de garagem forem compatíveis com permanência de longo prazo e preservação da reserva. + +## Reprodutibilidade + +Execute `python reports/cruzeiro_top15/analysis.py` para a extração somente leitura. A ordenação final inclui julgamento fotográfico documentado neste arquivo e não é produzida automaticamente pelo script. diff --git a/reports/cruzeiro_top10/analysis.py b/reports/cruzeiro_top15/analysis.py similarity index 97% rename from reports/cruzeiro_top10/analysis.py rename to reports/cruzeiro_top15/analysis.py index dacea23..f88a2dc 100644 --- a/reports/cruzeiro_top10/analysis.py +++ b/reports/cruzeiro_top15/analysis.py @@ -75,7 +75,7 @@ def main() -> int: l.raw_html_path, COUNT(p.source_url) AS photo_count FROM listings AS l JOIN listing_searches AS s USING (listing_id) - LEFT JOIN photos AS p USING (listing_id) + LEFT JOIN photos AS p ON p.listing_id=l.listing_id AND p.is_primary_gallery=1 WHERE instr(s.search_url, ?) > 0 AND l.inactive_at IS NULL GROUP BY l.listing_id diff --git a/reports/cruzeiro_top15/parameters.json b/reports/cruzeiro_top15/parameters.json new file mode 100644 index 0000000..0d2d045 --- /dev/null +++ b/reports/cruzeiro_top15/parameters.json @@ -0,0 +1,20 @@ +{ + "analysis_date": "2026-07-21", + "listing_data_reference_date": "2026-07-21", + "database_path": "dfimoveis_data/dfimoveis.sqlite3", + "database_main_file_sha256": "bfbbdd09e88f76afd917ebd981b848b9321aeb5fc0602f712645d33e1a5ea76c", + "database_mode": "read_only_transaction_with_wal", + "search_url_fragment": "/cruzeiro/novo/", + "listing_limit": 100, + "observed_listing_count": 67, + "active_listing_count": 63, + "inactive_listing_count": 4, + "database_crawl_run_count": 20, + "ranking_size": 15, + "ranking_unit": "probable_physical_property", + "numeric_score_used": false, + "price_per_m2_used": false, + "first_photo_finalist_audit_count": 16, + "visually_unavailable_listing_ids": ["1263868"], + "context_documents_reviewed": ["docs/CURRENT_STATE.md", "docs/PROJECT_CONTEXT.md", "docs/LOCATION_CRITERIA.md", "docs/PROPERTY_CRITERIA.md", "docs/FINANCIAL_STRATEGY.md", "docs/SCRAPER_OPERATIONS.md", "docs/DATA_MODEL.md", "docs/ANALYSIS_RULES.md"] +} diff --git a/reports/cruzeiro_top10/photo_similarity.py b/reports/cruzeiro_top15/photo_similarity.py similarity index 92% rename from reports/cruzeiro_top10/photo_similarity.py rename to reports/cruzeiro_top15/photo_similarity.py index a48e4fe..837f14b 100644 --- a/reports/cruzeiro_top10/photo_similarity.py +++ b/reports/cruzeiro_top15/photo_similarity.py @@ -22,7 +22,7 @@ DATA_ROOT = DB_PATH.parent def difference_hash(path: Path) -> int | None: try: with Image.open(path) as image: - pixels = list(image.convert("L").resize((9, 8)).getdata()) + pixels = list(image.convert("L").resize((9, 8)).get_flattened_data()) except (OSError, UnidentifiedImageError): return None value = 0 @@ -48,7 +48,7 @@ def main() -> None: ), uncommon AS ( SELECT sha256 FROM photos - WHERE sha256 IS NOT NULL + WHERE sha256 IS NOT NULL AND is_primary_gallery=1 GROUP BY sha256 HAVING COUNT(DISTINCT listing_id) <= 5 ) @@ -56,7 +56,7 @@ def main() -> None: FROM photos AS p JOIN cruzeiro AS c USING (listing_id) JOIN uncommon AS u USING (sha256) - WHERE p.local_path IS NOT NULL + WHERE p.local_path IS NOT NULL AND p.is_primary_gallery=1 ORDER BY p.listing_id, p.ordinal """ ).fetchall() diff --git a/reports/cruzeiro_top10/query.sql b/reports/cruzeiro_top15/query.sql similarity index 97% rename from reports/cruzeiro_top10/query.sql rename to reports/cruzeiro_top15/query.sql index ae13f95..4645c76 100644 --- a/reports/cruzeiro_top10/query.sql +++ b/reports/cruzeiro_top15/query.sql @@ -26,6 +26,7 @@ SELECT p.listing_id, COUNT(*) AS photo_count FROM photos AS p JOIN listing_searches AS s USING (listing_id) WHERE instr(s.search_url, '/cruzeiro/novo/') > 0 + AND p.is_primary_gallery = 1 AND EXISTS ( SELECT 1 FROM listings AS l WHERE l.listing_id = p.listing_id AND l.inactive_at IS NULL diff --git a/reports/cruzeiro_top15/results.csv b/reports/cruzeiro_top15/results.csv new file mode 100644 index 0000000..ad61336 --- /dev/null +++ b/reports/cruzeiro_top15/results.csv @@ -0,0 +1,16 @@ +rank,representative_listing_id,probable_duplicate_ids,price_brl,area_m2,bedrooms,suites,floor,elevator,parking_spaces,original_three_bedroom_status,visual_status,decision +1,1345146,,670000,65,3,1,4,yes,,probable_pending_confirmation,no_sale_marker,strong_candidate +2,1357415,,630000,67.2,3,1,4,unknown,,probable_pending_confirmation,no_sale_marker,confirm_elevator_then_visit +3,1357633,,600000,64,3,0,2,unknown,,probable_pending_confirmation,no_sale_marker,visit +4,1376958,,599000,62,3,1,2,no,,probable_pending_confirmation,no_sale_marker,visit +5,1345903,,565000,64.5,3,1,1,unknown,0,probable_pending_confirmation,no_sale_marker,visit_as_value_option +6,1339324,,665000,64,3,1,3,unknown,,probable_pending_confirmation,no_sale_marker,clarify_accessibility_then_visit +7,1370889,1375200,695000,62,3,1,2,unknown,,probable_pending_confirmation,no_sale_marker,identify_primary_listing_then_visit_once +8,1372268,,595000,62.61,3,0,1,unknown,2,probable_pending_confirmation,no_sale_marker,prove_parking_then_visit +9,1373131,,725000,65,3,0,2,no,,probable_pending_confirmation,no_sale_marker,visit_if_reform_premium_is_acceptable +10,1381514,,690000,63,3,0,4,unknown,,probable_pending_confirmation,no_sale_marker,confirm_elevator_parking_and_area_then_visit +11,1382466,,650000,62,3,0,,unknown,1,probable_pending_confirmation,no_sale_marker,request_missing_rooms_before_visit +12,1290510,,640000,62,3,1,4,no,,probable_pending_confirmation,no_sale_marker,validate_costs_then_visit +13,1371813,,709000,68,3,1,,unknown,,probable_pending_confirmation,no_sale_marker,request_full_gallery_then_decide +14,1400223,,495000,62.61,3,0,2,unknown,,probable_pending_confirmation,no_sale_marker,quote_full_renovation_and_confirm_parking +15,1369327,,490000,62,3,0,4,no,1,probable_pending_confirmation,no_sale_marker,quote_reform_and_test_stairs diff --git a/reports/cruzeiro_vs_mangueiral/README.md b/reports/cruzeiro_vs_mangueiral/README.md index 175277a..61e400a 100644 --- a/reports/cruzeiro_vs_mangueiral/README.md +++ b/reports/cruzeiro_vs_mangueiral/README.md @@ -1,133 +1,88 @@ -# Ranking reconstruído — Cruzeiro Novo x Jardins Mangueiral +# Top 30 — Jardins Mangueiral x Cruzeiro Novo -**Data do snapshot:** 17/07/2026 -**Unidade:** imóvel físico provável -**Finalidade:** priorizar investigação e visitas; não estimar preço de transação nem substituir vistoria +**Snapshot:** 21/07/2026 -## Resumo executivo +**Unidade:** imóvel físico provável -O Jardins Mangueiral continua oferecendo os melhores candidatos por espaço, suíte, vagas e preço anunciado. O Cruzeiro Novo continua superior em centralidade, acesso ao Plano Piloto e menor dependência de carro. +**Finalidade:** ordenar investigação para moradia de 10–20 anos; não estimar preço de transação nem substituir vistoria e análise financeira. -A casa `1279892`, QC 10, permanece em primeiro lugar geral pelo equilíbrio entre R$ 595 mil, condição visual, três quartos prováveis e quintal convertido sem eliminação total da área aberta. O apartamento `1345146`, SHCES 1207, é o melhor do Cruzeiro e fica em segundo: reforma coerente, suíte e elevador anunciado, mas com preço maior e vaga ainda incerta. +## Resposta -Confiança do ranking: **moderada para priorização de visitas e baixa para decisão de compra**. Fotos e anúncios não confirmam documentação, estrutura, sistemas, ruído, conforto térmico ou preço negociável. +Após reaplicar o contexto do projeto, o **Jardins Mangueiral é a região principal** e o Cruzeiro Novo é alternativa secundária e oportunística. O Mangueiral tende a entregar mais espaço, suíte, vagas e ambiente residencial pelo preço; o Cruzeiro só supera essa preferência quando uma unidade concreta compensa claramente as concessões de escadas, garagem, reforma e funcionalidade pela centralidade. -## Universo e atualização +`1279892` permanece em primeiro lugar geral. `1345146` é o melhor apartamento e ocupa o terceiro lugar, atrás também de `1350367`. A confiança é **moderada para ordenar investigação e baixa para decidir compra**, pois documentação, estrutura, ruído, conforto térmico, custos de adequação e preço negociado não estão comprovados. -- Fonte: DF Imóveis. -- Banco: 159 anúncios, 295 snapshots e 6.272 mídias. -- Cruzeiro Novo: 65 anúncios acumulados e ativos. -- Jardins Mangueiral: 94 anúncios acumulados; 84 ativos no banco e 10 inativos. -- Cobertura útil: coletas de 13 e 17/07/2026. -- Histórico: ainda curto demais para tendência, liquidez ou tempo real de mercado. +## Universo, período e qualidade -O banco foi aberto com `mode=ro`, `PRAGMA query_only = ON` e transação de leitura consistente para incluir o WAL. O `quick_check` retornou `ok`. +- Fonte: DF Imóveis; cobertura observada de 13–21/07/2026. +- Banco aberto com `mode=ro`, `PRAGMA query_only=ON`; `quick_check`: `ok`. +- 161 anúncios, 562 observações históricas e 7.363 fotos. +- Cruzeiro: 67 anúncios acumulados, 63 ativos e 4 inativos. +- Mangueiral: 94 acumulados, 78 ativos e 16 inativos. +- A coleta de 21/07 adicionou dois anúncios do Cruzeiro e nenhum do Mangueiral; 20 anúncios acumulados estão inativos. +- Das 401 transições históricas observadas, 398 envolvem o campo `creci` contaminado; somente três anúncios tiveram mudança real de preço. O histórico bruto não deve ser lido como 401 mudanças de mercado. +- Não há série suficiente para inferir liquidez, tendência ou venda a partir de retirada. +- Preços são de oferta; áreas não são comparáveis o bastante para preço por m². -## Método de reconstrução +## Método -O comparativo foi refeito a partir dos rankings regionais corrigidos, preservando a ordem relativa dentro de cada região. Não foram usados preço por metro quadrado nem pontuação numérica, porque as áreas das casas e apartamentos não são semanticamente comparáveis e os pesos não foram aprovados. +Foram relidos `PROJECT_CONTEXT.md`, `PROPERTY_CRITERIA.md`, `DATA_MODEL.md` e `ANALYSIS_RULES.md`. A ordem combina os rankings regionais sem pesos secretos e sem alternância automática, considerando: três quartos utilizáveis, funcionalidade futura, condição aparente, iluminação/ventilação, acessibilidade, vagas, regularidade, custo de adequação, logística familiar e qualidade da evidência. -A ordem geral combina: +No Mangueiral, planta original de três quartos é filtro obrigatório; quintal fechado só é negativo quando reduz luz/ventilação ou cria ambiente redundante e de manutenção difícil. No Cruzeiro, escadas, ausência de garagem e sistemas antigos são concessões materiais para permanência de longo prazo. A proximidade de São Sebastião é benefício logístico, não fundamento exclusivo da decisão. -1. funcionalidade de longo prazo e três quartos utilizáveis; -2. condição visual e risco de reforma; -3. iluminação, ventilação, circulação e armazenamento aparentes; -4. preço, custos conhecidos e margem para adequação; -5. acessibilidade, vagas e dependência de carro; -6. riscos específicos da tipologia; -7. qualidade e coerência da evidência fotográfica; -8. compatibilidade da localização com a rotina registrada no projeto. +A ordem regional do Mangueiral foi recalibrada após o usuário avaliar diretamente os 15 finalistas em 21/07 e, em seguida, o funil foi refeito sobre os 78 anúncios ativos. As notas pessoais prevalecem quando existem; anúncios novos entram por aderência inferida e ficam explicitamente pendentes de avaliação pessoal. Para não inventar equivalência numérica com apartamentos ainda não avaliados, as posições relativas do Cruzeiro foram mantidas. -No Cruzeiro, os principais ajustes de risco são escadas, ausência de garagem, sistemas antigos e obras do bloco. No Mangueiral, são planta original, regularização das ampliações, impermeabilização, calor/ventilação e logística. +Republicações visualmente equivalentes contam como um imóvel provável. Falta de informação é pendência, não aprovação. -## Auditoria de disponibilidade pelas fotos +## Auditoria visual de disponibilidade -A primeira foto dos 20 finalistas foi inspecionada especificamente para “vendido”, “negócio fechado” ou sinal equivalente. - -- Nenhum dos dez finalistas do Cruzeiro apresentou esse sinal. -- No Mangueiral, quatro anúncios que apareceram em versões anteriores foram removidos e colocados em quarentena visual: `1346231`, `1349519`, `1351729` e `1366801`. -- O banco ainda os tratava como ativos; para um ranking de visitas, a evidência visual prevaleceu como sinal de indisponibilidade operacional. -- A marca não comprova registro, preço ou conclusão jurídica da transação. +A primeira foto corrente dos 78 anúncios ativos do Mangueiral, dos finalistas do Cruzeiro e das quarentenas foi aberta e inspecionada. Nenhum dos 30 imóveis classificados atuais exibe “vendido”, “negócio fechado” ou equivalente. Ficam em quarentena `1263868` no Cruzeiro e `1301400`, `1346017`, `1346231`, `1349519`, `1351729`, `1352943`, `1356197`, `1362968` e `1366801` no Mangueiral. O sinal visual indica provável indisponibilidade operacional, não prova jurídica de venda. ## Ranking geral -| # | Região | Anúncio | Local | Preço | Motivo principal | Pendência decisiva | -|---:|---|---|---|---:|---|---| -| 1 | Mangueiral | [1279892](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-rua-f-1279892) | QC 10 | R$ 595.000 | Melhor equilíbrio entre preço, estado e espaço externo | Planta, áreas divergentes e regularização | -| 2 | Cruzeiro | [1345146](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1207-bloco-a-1345146) | SHCES 1207 A | R$ 670.000 | Melhor alternativa urbana; reformado e com elevador anunciado | Vaga, área da matrícula e sistemas | -| 3 | Mangueiral | [1350367](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-6-rua-c-1350367) | QC 6 | R$ 569.000 | Preço competitivo e ampliação social aparentemente funcional | Área, licenças, calor e drenagem | -| 4 | Cruzeiro | [1232283](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-309-bloco-b-1232283) | SHCES 309 B | R$ 600.000 | 70 m², suíte, nascente/vazado e duas vagas anunciadas | Elevador e natureza jurídica das vagas | -| 5 | Mangueiral | [1346017](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-1346017) | QC 10 | R$ 577.000 | Clara, pouco personalizada e com quintal majoritariamente aberto | Taxas, orientação e regularização da cobertura | -| 6 | Mangueiral | [1397378](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-8-rua-b-1397378) | QC 8 | R$ 600.000 | QC prática e implantação compatível com a planta de 68 m² | Manutenção, drenagem e galeria contaminada | -| 7 | Cruzeiro | [1357415](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1109-1357415) | SHCES 1109 | R$ 630.000 | Boa reforma, suíte e posição nascente/vazada | Confirmar elevador antes de agendar | -| 8 | Mangueiral | [1359960](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-7-1359960) | QC 7 | R$ 610.000 | Ampliação social flexível sem segunda cozinha completa evidente | Calor, ventilação e impermeabilização | -| 9 | Cruzeiro | [1357633](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-309-1357633) | SHCES 309 | R$ 600.000 | Reforma uniforme e sistemas declarados renovados | Elevador, garagem, condomínio e prova da reforma | -| 10 | Cruzeiro | [1376958](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-911-bloco-b-1376958) | SHCES 911 B | R$ 599.000 | Reformado, nascente, vazado e com suíte | Sem elevador e garagem não informada | -| 11 | Mangueiral | [1319996](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-1319996) | QC 14 | R$ 649.000 | Reforma completa, marcenaria e placas solares | QC, cobertura, taxas e homologação solar | -| 12 | Cruzeiro | [1345903](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1303-1345903) | SHCES 1303 | R$ 565.000 | Menor preço competitivo e primeiro andar | Sem garagem; ruído e segurança do térreo | -| 13 | Mangueiral | [1324014](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-12-rua-k-1324014) | QC 12 | R$ 649.000 | Acabamento interno e marcenaria fortes | Vaga, redundância gourmet e ventilação | -| 14 | Cruzeiro | [1339324](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-703-1339324) | SHCES 703 | R$ 665.000 | Integração social, suíte e boa apresentação visual | Terceiro andar, elevador e garagem desconhecidos | -| 15 | Mangueiral | [1333569](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-6-1333569) | QC 6 | R$ 650.000 | Ampliação social em uso e QC alternativa prática | Conceito dos 90 m² e manutenção da cobertura | -| 16 | Cruzeiro | [1370889](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-207-1370889) / [1375200](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-207-1375200) | SHCES 207 | R$ 695.000 | Apartamento reformado com suíte | Duplicata, andar, elevador, vaga e área | -| 17 | Mangueiral | [1359480](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-4-1359480) | QC 4 | R$ 535.000 | Referência de menor preço habitável | QC, planta, documentação e acabamento externo | -| 18 | Cruzeiro | [1372268](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-305-bloco-i-1372268) | SHCES 305 I | R$ 595.000 | Primeiro andar e duas vagas anunciadas | Provar vagas e orçar modernização | -| 19 | Mangueiral | [1356197](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-4-1356197) | QC 4 | R$ 649.000 | Acabamento interno forte e casa vazia | Espaço coberto parece garagem; regularização | -| 20 | Cruzeiro | [1373131](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-305-1373131) | SHCES 305 | R$ 725.000 | Reforma tecnicamente bem descrita | Sem elevador, sem garagem e prêmio de preço | - -## Comparação regional - -| Dimensão | Cruzeiro Novo | Jardins Mangueiral | -|---|---|---| -| Faixa do top 10 | R$ 565 mil–R$ 725 mil | R$ 535 mil–R$ 650 mil | -| Mediana do top 10 | R$ 615 mil | R$ 610 mil | -| Espaço | 62–70 m²; conceito de área mais homogêneo | 68–90 m² informados; ampliações pouco comparáveis | -| Vagas | Frequentemente ausentes ou incertas | Uma ou duas na maioria dos finalistas | -| Acessibilidade | Depende fortemente de andar e elevador | Escada interna permanente em todos os sobrados padrão | -| Reforma | Elétrica, hidráulica e prédio antigos | Cobertura, drenagem, impermeabilização e ampliação | -| Mobilidade | Centralidade e menor dependência de carro | Maior dependência logística; proximidade de São Sebastião | -| Espaço social | Compacto | Quintal e ampliações mais flexíveis | -| Documentação crítica | Vaga, área, obras do bloco | Planta original e regularização das ampliações | - -## Sensibilidade à prioridade pessoal - -| Prioridade dominante | Região favorecida | Primeiro candidato | -|---|---|---| -| Centralidade e acesso ao Plano | Cruzeiro | 1345146 | -| Espaço, suíte, vagas e custo-benefício | Mangueiral | 1279892 | -| Menor preço habitável | Mangueiral | 1359480, com concessões | -| Apartamento próximo de R$ 600 mil | Cruzeiro | 1232283 | -| Menor risco de ampliação irregular | Cruzeiro | 1345146 ou 1357633 | -| Menor risco de sistemas prediais antigos | Mangueiral | 1346017 ou 1397378, sujeito a vistoria | -| Proximidade de São Sebastião e rede familiar | Mangueiral | 1279892 | - -## Imóveis imediatamente fora do corte - -- **Cruzeiro:** [1382466](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-101-bloco-c-1382466), [1290510](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-911-bloco-a-1290510) e [1371813](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1109-bloco-d-1371813). -- **Mangueiral:** [1368562](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-5-1368562). - -## Próxima ação recomendada - -As quatro visitas mais informativas continuam sendo: - -1. `1279892`, para testar a melhor hipótese de casa equilibrada; -2. `1345146`, para testar a melhor hipótese urbana com elevador; -3. `1350367`, para testar custo-benefício e ampliação no Mangueiral; -4. `1232283`, para testar apartamento maior, suíte e vagas anunciadas. - -Registrar após cada visita: tempo real de deslocamento, sensação de espaço, ruído, estacionamento, escadas, ventilação, manutenção esperada e vontade de permanecer por 10–20 anos. Essas quatro visitas devem definir qual região recebe a rodada seguinte. - -## Limitações - -- Preços são pedidos, não transações. -- A cobertura histórica é curta e de um único portal. -- A situação financeira do projeto precisa ser confirmada antes de proposta ou preço máximo. -- Fotos não validam estrutura, sistemas, ruído, conforto térmico ou documentação. -- A planta original das casas e vagas/elevadores dos apartamentos continuam pendentes. -- A escolha regional ainda depende de uma preferência não consolidada: centralidade versus casa, espaço e proximidade familiar. +| # | Região | Pos. regional | Anúncio | Local | Preço | Classificação e pendência decisiva | +|---:|---|---:|---|---|---:|---| +| 1 | Mangueiral | 1 | [1279892](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-rua-f-1279892) | QC 10 | R$ 595 mil | **Forte:** equilíbrio geral; confirmar planta, áreas e regularização | +| 2 | Mangueiral | 2 | [1319996](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-1319996) | QC 14 | R$ 649 mil | **Forte, 4/5:** cozinha, gourmet, quintal e conservação; reverter closet se necessário | +| 3 | Cruzeiro | 1 | [1345146](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1207-bloco-a-1345146) | SHCES 1207 A | R$ 670 mil | **Forte:** melhor opção urbana; confirmar vaga, planta e sistemas | +| 4 | Mangueiral | 3 | [1377683](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-11-1377683) | QC 11 | R$ 585 mil | **Aderência inferida:** cozinha funcional e gourmet aberto; usuário avaliar | +| 5 | Mangueiral | 4 | [1371718](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-rua-c-1371718) | QC 14 | R$ 650 mil | **Aderência inferida:** conservação, cozinha e gourmet; usuário avaliar | +| 6 | Cruzeiro | 2 | [1357415](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1109-1357415) | SHCES 1109 | R$ 630 mil | **Forte condicionado:** reformado e vazado; confirmar elevador | +| 7 | Mangueiral | 5 | [1140317](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-5-rua-l-1140317) | QC 5 | R$ 599 mil | **Aderência inferida:** cozinha equipada e gourmet aberto; usuário avaliar | +| 8 | Mangueiral | 6 | [1324014](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-12-rua-k-1324014) | QC 12 | R$ 649 mil | **Visitar, 3/5:** gourmet e conservação agradam; confirmar vaga e ventilação | +| 9 | Cruzeiro | 3 | [1357633](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-309-1357633) | SHCES 309 | R$ 600 mil | **Visitar:** reforma uniforme; elevador, vaga e sistemas pendentes | +| 10 | Mangueiral | 7 | [1290502](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-11-1290502) | QC 11 | R$ 600 mil | **Aprofundar, 3/5:** reforma adequada; gourmet implementável | +| 11 | Cruzeiro | 4 | [1376958](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-911-bloco-b-1376958) | SHCES 911 B | R$ 599 mil | **Visitar:** reformado e nascente; sem elevador e vaga incerta | +| 12 | Mangueiral | 8 | [1352633](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-9-rua-g-1352633) | QC 9 | R$ 755 mil | **Aderência inferida:** conjunto visual forte; preço alto e usuário avaliar | +| 13 | Mangueiral | 9 | [1345745](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-quadra-qc-12-1345745) | QC 12 | R$ 670 mil | **Aderência inferida:** cozinha e gourmet amplos; testar calor | +| 14 | Cruzeiro | 5 | [1345903](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1303-1345903) | SHCES 1303 | R$ 565 mil | **Alternativa de valor:** primeiro andar, mas sem garagem | +| 15 | Mangueiral | 10 | [1333569](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-6-1333569) | QC 6 | R$ 650 mil | **Condicionado, 3/5:** testar calor do fechamento de vidro | +| 16 | Cruzeiro | 6 | [1339324](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-703-1339324) | SHCES 703 | R$ 665 mil | **Aprofundar:** boa integração; faltam andar, elevador e vaga | +| 17 | Mangueiral | 11 | [1357311](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-1-rua-a-1357311) | QC 1 | R$ 699,9 mil | **Condicionado:** gourmet bom, mas há possível dano de água no teto | +| 18 | Mangueiral | 12 | [1357912](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-3-1357912) | QC 3 | R$ 580 mil | **Condicionado, 3/5:** espaços úteis; intervenções pesam | +| 19 | Cruzeiro | 7 | [1370889](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-207-1370889) / [1375200](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-207-1375200) | SHCES 207 | R$ 695 mil | **Aprofundar:** reformado; identificar anúncio principal e atributos | +| 20 | Cruzeiro | 8 | [1372268](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-305-bloco-i-1372268) | SHCES 305 I | R$ 595 mil | **Alternativa de valor:** provar duas vagas e orçar modernização | +| 21 | Mangueiral | 13 | [1259149](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-11-1259149) | QC 11 | R$ 590 mil | **Aderência inferida fraca:** preço razoável; acabamento e área pendentes | +| 22 | Cruzeiro | 9 | [1373131](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-305-1373131) | SHCES 305 | R$ 725 mil | **Condicionado:** reforma forte; sem elevador/garagem e caro | +| 23 | Mangueiral | 14 | [348115](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-rua-c-348115) | QC 14 | R$ 550 mil | **Referência de valor:** anúncio antigo; conservação e área pendentes | +| 24 | Cruzeiro | 10 | [1381514](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-301-1381514) | SHCES 301 | R$ 690 mil | **Condicionado:** reforma forte; 4º andar, elevador/vaga e área divergente pendentes | +| 25 | Mangueiral | 15 | [1346118](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-1346118) | QC 14 | R$ 550 mil | **Referência de valor:** base simples; modernização e área divergente | +| 26 | Cruzeiro | 11 | [1382466](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-101-bloco-c-1382466) | SHCES 101 C | R$ 650 mil | **Pendente:** boa reforma; galeria curta e andar/elevador ausentes | +| 27 | Cruzeiro | 12 | [1290510](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-911-bloco-a-1290510) | SHCES 911 A | R$ 640 mil | **Pendente:** suíte e reforma; 4º andar e taxas inválidas | +| 28 | Cruzeiro | 13 | [1371813](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-1109-bloco-d-1371813) | SHCES 1109 D | R$ 709 mil | **Pendente:** reforma moderna; evidência curta da planta | +| 29 | Cruzeiro | 14 | [1400223](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-609-bloco-d-1400223) | SHCES 609 D | R$ 495 mil | **Alternativa de obra:** 2º andar e boa luz; reforma ampla e vaga incerta | +| 30 | Cruzeiro | 15 | [1369327](https://www.dfimoveis.com.br/imovel/apartamento-3-quartos-venda-novo-cruzeiro-df-shces-quadra-203-bloco-g-1369327) | SHCES 203 G | R$ 490 mil | **Alternativa de obra:** vaga e desconto; 4º andar sem elevador | + +## Quase entraram + +As opções seguintes, todas com URL, estão nos relatórios regionais: [Cruzeiro Novo](../cruzeiro_top15/README.md#quase-entraram) e [Jardins Mangueiral](../mangueiral_top15/README.md#quase-entraram). + +## Próxima ação e decisão financeira + +No Mangueiral, começar a diligência por `1279892` e `1319996`; pedir planta, QC, licenças da ampliação, taxas e evidência de cobertura/drenagem antes da visita. No Cruzeiro, pedir andar, elevador, matrícula da vaga, atas e histórico de sistemas do prédio. As posições gerais entre tipologias permanecem provisórias até o usuário avaliar visualmente os apartamentos na mesma escala. + +O ranking físico não autoriza compra. Antes de negociar, calcular entrada, custos de aquisição, reforma/regularização, reserva remanescente, CET e custo mensal total. A posição deve cair se o imóvel exigir consumir a reserva ou depender de uma única circunstância afetiva/logística. ## Reprodutibilidade -- `results.csv`: ranking reconstruído. -- `parameters.json`: universo, método e fingerprint lógico do snapshot. -- `reports/cruzeiro_top10/`: fontes do ranking regional do Cruzeiro. -- `reports/mangueiral_top10/`: fontes do ranking regional do Mangueiral. +As extrações estão em `reports/cruzeiro_top15/analysis.py` e `reports/mangueiral_top15/analysis.py`. Os arquivos `results.csv` registram os 15 classificados regionais e `parameters.json` registra snapshot, contagens, hash do banco e critérios. A deduplicação e a inspeção fotográfica incluem julgamento manual documentado. diff --git a/reports/cruzeiro_vs_mangueiral/parameters.json b/reports/cruzeiro_vs_mangueiral/parameters.json index c9bc432..806f006 100644 --- a/reports/cruzeiro_vs_mangueiral/parameters.json +++ b/reports/cruzeiro_vs_mangueiral/parameters.json @@ -1,31 +1,33 @@ { - "analysis_date": "2026-07-17", - "listing_data_reference_date": "2026-07-17", + "analysis_date": "2026-07-21", + "listing_data_reference_date": "2026-07-21", "database_path": "dfimoveis_data/dfimoveis.sqlite3", - "database_main_file_sha256": "046e0a2fef3eb3c2e5ebdf07d30bd04a31db0bb1ea315ccc536c6bf8ba96577e", - "logical_snapshot_sha256": "fe604aab8af7f67c833e6de2a0fc81c7dc2950ca440ad7b23ebd03d0c2546188", + "database_main_file_sha256": "bfbbdd09e88f76afd917ebd981b848b9321aeb5fc0602f712645d33e1a5ea76c", "database_mode": "read_only_transaction_with_wal", "source_reports": [ - "reports/cruzeiro_top10/README.md", - "reports/mangueiral_top10/README.md" + "reports/cruzeiro_top15/README.md", + "reports/mangueiral_top15/README.md" ], - "cruzeiro_listing_count": 65, - "mangueiral_listing_count": 94, - "mangueiral_active_listing_count": 84, - "mangueiral_inactive_listing_count": 10, - "total_listing_count": 159, - "database_snapshot_count": 295, - "database_photo_count": 6272, - "database_crawl_run_count": 16, - "cruzeiro_photo_files_reviewed_distinct": 1289, - "mangueiral_photo_files_reviewed_distinct_cumulative": 1907, - "total_photo_files_reviewed_distinct_cumulative": 3196, - "regional_finalists_compared": 20, - "ranking_merge_method": "preserve_regional_order_then_interleave_by_cross_typology_visit_priority", - "report_rebuilt_from_regional_results": true, + "total_listing_count": 161, + "database_snapshot_count": 562, + "database_photo_count": 7363, + "database_crawl_run_count": 20, + "cruzeiro_observed_listing_count": 67, + "cruzeiro_active_listing_count": 63, + "mangueiral_observed_listing_count": 94, + "mangueiral_active_listing_count": 78, + "regional_ranking_size": 15, + "regional_finalists_compared": 30, "ranking_unit": "probable_physical_property", + "ranking_merge_method": "contextual_cross_typology_priority_with_mangueiral_as_primary_region_and_regional_order_preserved", "numeric_score_used": false, + "mangueiral_user_feedback_date": "2026-07-21", + "mangueiral_user_visual_functional_scores_used": true, + "mangueiral_full_active_universe_reprocessed": true, "cross_typology_price_per_m2_used": false, - "first_photo_sale_marker_audit_count": 20, - "visually_unavailable_listing_ids": ["1346231", "1349519", "1351729", "1366801"] + "mangueiral_first_photo_active_universe_audit_count": 78, + "cruzeiro_first_photo_finalist_and_quarantine_audit_count": 16, + "visually_unavailable_listing_ids": ["1263868", "1301400", "1346017", "1346231", "1349519", "1351729", "1352943", "1356197", "1362968", "1366801"], + "source_mismatch_listing_ids": ["1369473"], + "context_documents_reviewed": ["docs/CURRENT_STATE.md", "docs/PROJECT_CONTEXT.md", "docs/LOCATION_CRITERIA.md", "docs/PROPERTY_CRITERIA.md", "docs/FINANCIAL_STRATEGY.md", "docs/SCRAPER_OPERATIONS.md", "docs/DATA_MODEL.md", "docs/ANALYSIS_RULES.md"] } diff --git a/reports/cruzeiro_vs_mangueiral/results.csv b/reports/cruzeiro_vs_mangueiral/results.csv index 123fa30..6661e23 100644 --- a/reports/cruzeiro_vs_mangueiral/results.csv +++ b/reports/cruzeiro_vs_mangueiral/results.csv @@ -1,21 +1,31 @@ -rank,region,representative_listing_id,probable_duplicate_ids,location,price_brl,area_m2,bedrooms,suites,parking_spaces,key_condition,decision -1,mangueiral,1279892,,QC 10,595000,68,3,1,1,planta original e ampliações pendentes de documentos,candidato forte -2,cruzeiro,1345146,,SHCES 1207 bloco A,670000,65,3,1,,elevador anunciado e vaga pendente,candidato forte -3,mangueiral,1350367,,QC 6,569000,68,3,1,2,área ampliação e conforto térmico pendentes,candidato forte -4,cruzeiro,1232283,,SHCES 309 bloco B,600000,70,3,1,2,elevador e natureza das vagas pendentes,candidato forte condicionado -5,mangueiral,1346017,,QC 10,577000,68,3,1,2,taxas orientação e cobertura pendentes,candidato forte -6,mangueiral,1397378,,QC 8,600000,68,3,1,2,planta manutenção e cobertura pendentes,candidato forte -7,cruzeiro,1357415,,SHCES 1109,630000,67.2,3,1,,quarto andar e elevador desconhecido,confirmar elevador antes da visita -8,mangueiral,1359960,,QC 7,610000,68,3,1,2,conforto ambiental do quintal fechado pendente,visitar -9,cruzeiro,1357633,,SHCES 309,600000,64,3,0,,elevador garagem e condomínio pendentes,visitar -10,cruzeiro,1376958,,SHCES 911 bloco B,599000,62,3,1,,sem elevador e garagem não informada,visitar -11,mangueiral,1319996,,QC 14,649000,68,3,1,2,localização cobertura e placas solares pendentes,visitar -12,cruzeiro,1345903,,SHCES 1303,565000,64.5,3,1,0,primeiro andar e somente estacionamento público,alternativa de valor -13,mangueiral,1324014,,QC 12,649000,68,3,1,,vaga conforto da área gourmet e regularização pendentes,visitar -14,cruzeiro,1339324,,SHCES 703,665000,64,3,1,,terceiro andar elevador e garagem desconhecidos,esclarecer acessibilidade -15,mangueiral,1333569,,QC 6,650000,90,3,1,2,conceito de área e cobertura pendentes,visitar após os anteriores -16,cruzeiro,1370889,1375200,SHCES 207,695000,62,3,1,,duplicata provável elevador e garagem desconhecidos,confirmar anúncio primário -17,mangueiral,1359480,,QC 4,535000,70,3,1,2,planta documentação e acabamento externo pendentes,referência de valor -18,cruzeiro,1372268,,SHCES 305 bloco I,595000,62.61,3,0,2,vagas e custo de modernização pendentes,alternativa de valor -19,mangueiral,1356197,,QC 4,649000,68,3,1,2,uso do espaço coberto e regularização pendentes,visitar após os anteriores -20,cruzeiro,1373131,,SHCES 305,725000,65,3,0,,sem elevador e garagem não informada,visitar apenas se reforma justificar prêmio +rank,region,regional_rank,representative_listing_id,probable_duplicate_ids,location,price_brl,decision +1,mangueiral,1,1279892,,QC 10,595000,strong_candidate +2,mangueiral,2,1319996,,QC 14,649000,strong_candidate +3,cruzeiro,1,1345146,,SHCES 1207 A,670000,strong_candidate +4,mangueiral,3,1377683,,QC 11,585000,user_review_then_documents +5,mangueiral,4,1371718,,QC 14,650000,user_review_then_documents +6,cruzeiro,2,1357415,,SHCES 1109,630000,strong_candidate_conditioned +7,mangueiral,5,1140317,,QC 5,599000,user_review_then_documents +8,mangueiral,6,1324014,,QC 12,649000,visit +9,cruzeiro,3,1357633,,SHCES 309,600000,visit +10,mangueiral,7,1290502,,QC 11,600000,investigate +11,cruzeiro,4,1376958,,SHCES 911 B,599000,visit +12,mangueiral,8,1352633,,QC 9,755000,user_review_and_price_test +13,mangueiral,9,1345745,,QC 12,670000,user_review_and_heat_test +14,cruzeiro,5,1345903,,SHCES 1303,565000,value_alternative +15,mangueiral,10,1333569,,QC 6,650000,conditioned_heat_test +16,cruzeiro,6,1339324,,SHCES 703,665000,investigate +17,mangueiral,11,1357311,,QC 1,699900,inspect_possible_water_damage +18,mangueiral,12,1357912,,QC 3,580000,pending_intervention_cost +19,cruzeiro,7,1370889,1375200,SHCES 207,695000,investigate +20,cruzeiro,8,1372268,,SHCES 305 I,595000,value_alternative +21,mangueiral,13,1259149,,QC 11,590000,user_review_and_area_validation +22,cruzeiro,9,1373131,,SHCES 305,725000,conditioned +23,mangueiral,14,348115,,QC 14,550000,user_review_and_condition_validation +24,cruzeiro,10,1381514,,SHCES 301,690000,conditioned +25,mangueiral,15,1346118,,QC 14,550000,user_review_and_renovation_scope +26,cruzeiro,11,1382466,,SHCES 101 C,650000,pending_evidence +27,cruzeiro,12,1290510,,SHCES 911 A,640000,pending_cost_validation +28,cruzeiro,13,1371813,,SHCES 1109 D,709000,pending_evidence +29,cruzeiro,14,1400223,,SHCES 609 D,495000,renovation_alternative +30,cruzeiro,15,1369327,,SHCES 203 G,490000,renovation_alternative diff --git a/reports/database_assessment.md b/reports/database_assessment.md index 4039556..0b9758a 100644 --- a/reports/database_assessment.md +++ b/reports/database_assessment.md @@ -1,303 +1,169 @@ -# Avaliação inicial do banco de dados +# Avaliação do banco de dados -**Data da avaliação:** 13 de julho de 2026 -**Banco:** `dfimoveis_data/dfimoveis.sqlite3` -**Escopo:** diagnóstico estrutural e de qualidade anterior a qualquer análise dos imóveis +**Data da avaliação:** 21 de julho de 2026 -## 1. Pergunta respondida +**Banco:** `dfimoveis_data/dfimoveis.sqlite3` -O banco já representa de forma segura anúncios, snapshots históricos e imóveis físicos, com cobertura e qualidade suficientes para iniciar análises imobiliárias? +**Modo:** `mode=ro`, `PRAGMA query_only = ON` +**SHA-256 do arquivo principal:** `bfbbdd09e88f76afd917ebd981b848b9321aeb5fc0602f712645d33e1a5ea76c` -**Resposta curta:** ele representa anúncios e estados de conteúdo, mas ainda não representa imóveis físicos deduplicados. A coleta cobre apenas um dia e contém exatamente um snapshot por anúncio. Preços, áreas e quartos podem ser usados somente após validações específicas; localização e dados de anunciante estão fortemente contaminados e não devem ser usados como estão. Portanto, o banco ainda não sustenta tendência histórica, tempo de mercado, preço por m² ou comparáveis por localização. +## 1. Pergunta -## 2. Segurança e método +O snapshot atualizado sustenta a revisão dos rankings e já permite conclusões de histórico, disponibilidade e liquidez? -A análise foi feita exclusivamente com consultas agregadas ou amostras pequenas. O banco foi aberto com `sqlite3 -readonly` ou URI `mode=ro&immutable=1`, sempre com `PRAGMA query_only = ON`. Nenhum scraper foi executado e nenhuma instrução SQL de escrita foi enviada ao banco. +**Resposta curta:** sustenta a revisão operacional dos rankings, mas ainda não sustenta inferência de liquidez ou preço de transação. O banco contém quatro dias efetivos de observação entre 13 e 21/07/2026, e a maior parte dos novos snapshots é causada por campos textuais contaminados, não por mudança imobiliária real. -Identificação do arquivo analisado: +## 2. Integridade e esquema -- tamanho: 5.017.600 bytes; -- modificação: `2026-07-13 14:20:34.601285975 -03:00`; -- SHA-256 inicial: `1ce3128b488c50c993d7328ac6e24b5905f083a7e04e3f636407eea1edd02b9d`; -- sem arquivos `-wal` ou `-shm` e sem processo com o arquivo aberto na inspeção inicial; +- tamanho do arquivo principal: 9.478.144 bytes; - `PRAGMA quick_check`: `ok`; -- `PRAGMA foreign_key_check`: nenhuma violação. +- `PRAGMA foreign_key_check`: nenhuma violação; +- codificação: UTF-8; +- `journal_mode`: WAL; +- 2.314 páginas de 4.096 bytes; +- cinco tabelas da aplicação e `sqlite_sequence`; +- quatro autoíndices; nenhuma view ou trigger; +- esquema físico sem mudança material em relação a `docs/ACTUAL_SCHEMA.md`. -Na validação final, o arquivo principal continuava com o mesmo tamanho, `mtime` e SHA-256. Como seu modo persistido é WAL, o cliente SQLite havia criado dois sidecars de runtime: `dfimoveis.sqlite3-shm`, com 32.768 bytes, e `dfimoveis.sqlite3-wal`, vazio. Eles não foram removidos, conforme a regra explícita do projeto. +O banco foi consultado em transação somente leitura. Não foi usado `immutable=1`, pois este é o arquivo atualizado pelo scraper. -O esquema completo e as decisões de interpretação estão em `docs/ACTUAL_SCHEMA.md`. +## 3. Universo e cobertura -## 3. Universo, período e cobertura - -Não houve filtro ou exclusão de registros para este diagnóstico. O universo físico contém: - -| Unidade | Quantidade | +| Unidade | Total | |---|---:| -| Execuções do coletor | 4 | -| Anúncios únicos por `listing_id` | 156 | -| URLs de anúncio únicas | 156 | -| Snapshots de conteúdo | 156 | -| Vínculos anúncio–busca | 156 | -| Fotos registradas | 5.386 | -| Anúncios com pelo menos uma foto | 156 | - -### Cobertura temporal - -Todas as datas técnicas válidas estão em ISO 8601. A coleta cobre somente **13/07/2026**: - -| Evento | UTC | Horário de Brasília (UTC−3) | -|---|---|---| -| Primeira execução iniciada | 12:20:58 | 09:20:58 | -| Primeira observação de anúncio | 12:56:32 | 09:56:32 | -| Última observação de anúncio | 13:25:51 | 10:25:51 | -| Última execução concluída | 17:20:34 | 14:20:34 | - -As duas primeiras execuções terminaram com `status = ok`, mas registraram zero páginas, URLs e detalhes. As duas execuções com coleta efetiva somaram: - -- 9 páginas de busca; -- 156 URLs encontradas; -- 156 detalhes processados com sucesso e zero falhas; -- 5.383 fotos baixadas e 3 falhas; -- zero anúncios marcados como inativos. - -As buscas cobertas foram: - -1. `https://www.dfimoveis.com.br/venda/df/cruzeiro/novo/apartamento/3-quartos` — 65 anúncios; -2. `https://www.dfimoveis.com.br/venda/df/brasilia/jardins-mangueiral/casa/3,4-quartos` — 91 anúncios. - -O universo é, portanto, intencionalmente limitado a um portal e a duas consultas. A busca do Jardins Mangueiral aceita três **ou quatro** quartos: 89 casas foram extraídas com três quartos anunciados e 2 com quatro. Mesmo os 89 registros de três quartos não comprovam a planta original exigida pelo projeto. - -## 4. Como as entidades são representadas - -### Anúncio - -`listings` guarda uma linha por `listing_id` do DF Imóveis, com URL única e o estado corrente. Os 156 IDs, URLs e hashes correntes são distintos. Essa é uma identidade de publicação no portal, não de unidade residencial. - -### Snapshot ou observação histórica - -`listing_history` guarda uma linha por par único `(listing_id, content_hash)`. Isso é um histórico de **mudanças de conteúdo**: uma nova observação idêntica não cria novo snapshot. `listings.first_seen_at` e `last_seen_at` condensam a janela observada. - -No snapshot atual: - -- todos os 156 anúncios têm exatamente um registro histórico; -- o hash histórico é igual ao hash corrente em todos os casos; -- `captured_at = first_seen_at` em todos os casos; -- `first_seen_at = last_seen_at` em todos os casos. - -Assim, não há série histórica real ainda. Não é possível medir mudança de preço, republicação, duração, saída ou retorno do estoque. - -### Execução do scraper - -`crawl_runs` registra horários, estado e contadores JSON, mas não existe `run_id` em `listings`, `listing_history` ou `listing_searches`. A execução geradora só pode ser inferida por horário. Isso limita auditoria, cobertura por execução e diagnóstico de ausências. +| Execuções registradas | 20 | +| Execuções `ok` | 12 | +| Execuções `failed` | 8 | +| Anúncios acumulados | 161 | +| Observações históricas | 562 | +| Vínculos anúncio–busca | 161 | +| Fotos registradas | 7.363 | +| Hashes de foto distintos | 3.455 | +| Anúncios inativos | 20 | -### Imóvel físico +Cobertura técnica: 13–21/07/2026. Há observações de anúncios em quatro datas, janela insuficiente para sazonalidade ou liquidez. -Não existe tabela ou chave para imóvel físico, unidade, endereço normalizado ou relação de duplicidade. Anúncios de corretores diferentes permanecem independentes. A base também não contém hashes perceptuais; possui apenas SHA-256 exato das imagens. +| Região | Acumulados | Ativos | Inativos | +|---|---:|---:|---:| +| Jardins Mangueiral | 94 | 78 | 16 | +| Cruzeiro Novo | 67 | 63 | 4 | -Logo, as unidades válidas hoje são: +A execução 20, em 21/07, processou oito páginas, encontrou 141 URLs, concluiu 141 detalhes sem falha, baixou 572 fotos novas, reutilizou 4.404 e marcou 20 anúncios como inativos. Ausência da busca não comprova venda. -- anúncio único: suportado por `listing_id`; -- estado alterado do anúncio: suportado por `listing_history`; -- imóvel físico provável/confirmado: **não suportado sem derivação e revisão**. +## 4. O que os dados representam -## 5. Qualidade dos dados +- `listings`: identidade de anúncio e estado corrente; +- `listing_history`: estados distintos por `content_hash`, não cada observação; +- `listing_searches`: vínculo entre anúncio e busca; +- `photos`: mídia associada ao anúncio, sem vínculo a um snapshot específico; +- `crawl_runs`: execução técnica sem chave direta para os anúncios observados; +- imóvel físico provável: não existe como entidade persistida e depende de deduplicação derivada. -### 5.1 Integridade estrutural +Há 21 anúncios com um snapshot, 6 com dois, 7 com três e 127 com quatro. Essa distribuição não deve ser interpretada como número de mudanças reais. -Pontos positivos: +## 5. Auditoria das mudanças históricas -- arquivo íntegro segundo `quick_check`; -- nenhuma FK órfã em histórico, buscas ou fotos; -- todos os JSONs são sintaticamente válidos; -- todos os IDs de anúncio têm 6–7 caracteres numéricos; -- todas as URLs pertencem ao domínio e padrão esperados; -- todos os 156 HTMLs brutos referenciados existem; -- todos os hashes de conteúdo têm 64 caracteres; -- não há URL, hash corrente ou caminho de HTML repetido. +Foram comparadas as transições consecutivas de `data_json`: -Limitações estruturais: - -- nenhuma relação entre execução e item; -- fonte implícita, sem `source_id`; -- área armazenada em um único conceito; -- mídia ligada ao anúncio, não ao snapshot; -- ausência de entidade de imóvel físico e de localização normalizada; -- apenas autoíndices; não há índices por datas ou atributos analíticos. - -### 5.2 Completude dos principais campos - -| Campo | Ausentes | Percentual | -|---|---:|---:| -| preço | 0 | 0,0% | -| área | 0 | 0,0% | -| quartos | 0 | 0,0% | -| condomínio | 59 | 37,8% | -| IPTU | 144 | 92,3% | -| suítes | 41 | 26,3% | -| vagas | 57 | 36,5% | -| cidade | 156 | 100,0% | -| UF | 156 | 100,0% | -| nome do anunciante | 156 | 100,0% | -| latitude/longitude | 156 / 156 | 100,0% / 100,0% | -| data de publicação | 156 | 100,0% | -| data de inativação | 156 | 100,0% | - -Esses percentuais medem apenas nulos. Para campos textuais, a taxa de preenchimento é enganosa porque o parser capturou conteúdo da página em vez do valor pretendido. - -### 5.3 Contaminação de texto - -Os problemas mais graves são: - -- 146 endereços (93,6%) têm mais de 300 caracteres; -- 154 bairros (98,7%) têm mais de 100 caracteres; -- os dois valores curtos de bairro são `.` e um trecho de descrição, também inválidos; -- 98 códigos de anunciante (62,8%) têm mais de 100 caracteres; -- 153 valores de CRECI (98,1%) têm mais de 100 caracteres. - -Os textos longos incluem navegação, formulários, política de privacidade e outros fragmentos da página. Eles podem conter dados de contato exibidos pelo portal; por isso, não foram reproduzidos neste relatório. Esses campos devem ser considerados **indisponíveis**, não apenas ruidosos. - -Os títulos têm somente quatro valores distintos e funcionam como títulos genéricos por tipologia. As 156 descrições são distintas, mas têm apenas 156–161 caracteres, compatíveis com resumos/metadados truncados, não com a descrição completa. `extra_json` contém um array `json_ld` vazio nos 156 registros e não resolve a reextração. - -### 5.4 Valores estruturados e outliers - -| Tipo anunciado | N | Preço mínimo | Preço máximo | Área mínima | Área máxima | Quartos | -|---|---:|---:|---:|---:|---:|---:| -| Apartamento | 65 | R$ 480.000 | R$ 2.030.598 | 61 m² | 113 m² | 3 | -| Casa | 91 | R$ 450.000 | R$ 570.000.000 | 0,11 m² | 131,46 m² | 3–4 | - -Não há valores nulos ou não positivos em preço e área, mas isso não significa validade: +| Campo alterado | Transições | +|---|---:| +| `content_hash` | 401 | +| `creci` | 398 | +| `advertiser_code` | 66 | +| `neighborhood` | 25 | +| `description` | 11 | +| `price_brl` | 3 | +| `address` | 3 | -- anúncio `1351663`: R$ 570.000.000, forte indício de erro de escala ou parsing; -- anúncio `1370918`: 0,11 m², área fisicamente implausível. +Em 305 transições, somente `creci` e o hash mudaram. Isso indica instabilidade do parser ou conteúdo variável da página. Não há base para tratar 401 transições como mudanças de mercado. -Não foi aplicado corte nem correção silenciosa. Também não se calculou preço por m², pois `area_m2` não distingue área útil, privativa, construída, total ou terreno. +Mudanças reais de preço identificadas: -### 5.5 Fotos e arquivos brutos +- `1173275`: R$ 550.000 para R$ 549.000 em 21/07; +- `1348535`: R$ 950.000 para R$ 880.000 em 20/07, mantido em 21/07; +- `1372539`: R$ 572.500 para R$ 569.000 em 17/07, mantido depois. -Das 5.386 linhas em `photos`: +Esses valores são preços anunciados, não negociados. -- 5.383 têm arquivo local, e o tamanho em disco coincide com `bytes`; -- 3 não têm hash, MIME, tamanho ou caminho, correspondendo às três falhas registradas pelo coletor; -- há 4.514 WebP, 558 JPEG, 311 PNG e 3 sem MIME; -- os anúncios possuem de 5 a 61 fotos; -- não há caminho local nem ordinal duplicado dentro de anúncio. +## 6. Qualidade dos campos -Há 3.307 hashes distintos. Cento e quatorze hashes aparecem em mais de um anúncio, e um deles aparece nos 156 anúncios. Isso revela logos, selos, placeholders ou outros ativos comuns. Hash idêntico pode ser sinal de anúncio duplicado somente depois de excluir ativos genéricos e combinar outros sinais. +Nos 161 anúncios: -## 6. Duplicidades e imóveis físicos prováveis +- preço, área e quartos estão preenchidos em todos; +- cidade, UF, latitude e longitude estão ausentes em todos; +- 150 endereços têm mais de 300 caracteres; +- 159 bairros têm mais de 100 caracteres; +- permanece um preço de R$ 570 milhões (`1351663`); +- permanece uma área de 0,11 m² (`1370918`); +- nenhum registro de foto está sem hash ou caminho local no snapshot atual. +- a triagem perceptual com Pillow 12.3.0 foi reexecutada nos dois recortes; recuperou os grupos já documentados e não identificou nova duplicação suficientemente sustentada entre os 30 finalistas. -Não há duplicidade técnica imediata por `listing_id`, URL ou `content_hash`. Uma assinatura exploratória composta por bairro, tipo, preço, área, quartos e vagas encontrou 13 grupos, equivalentes a 18 linhas excedentes. Esse resultado **não é evidência de 18 imóveis duplicados**, porque: +O preenchimento não garante validade. Localização e anunciante continuam contaminados. Área não distingue privativa, útil, construída, total, terreno ou ampliação. -- o bairro está contaminado; -- preço, área e quartos podem coincidir entre unidades distintas; -- fotos compartilhadas incluem ativos genéricos; -- não há endereço/unidade confiável nem telefone normalizado; -- SHA-256 só detecta arquivos idênticos, não versões redimensionadas da mesma foto. +## 7. Disponibilidade e quarentena visual -Consequentemente, o método de deduplicação desta avaliação foi apenas técnico: unicidade de anúncio por `listing_id`. Nenhuma fusão de anúncios nem contagem de imóveis físicos foi produzida. +Vinte anúncios estão inativos no banco, mas retirada não prova venda. Além disso, dez anúncios ainda ativos exibem indicação explícita na primeira foto: -Uma futura camada derivada deve combinar, com confiança e revisão manual: +- Cruzeiro: `1263868`; +- Mangueiral: `1301400`, `1346017`, `1346231`, `1349519`, `1351729`, `1352943`, `1356197`, `1362968` e `1366801`. -- endereço/QC/quadra/bloco/unidade reextraídos; -- imagens após remoção de ativos comuns, idealmente com hash perceptual; -- preço, área, planta, quartos e vagas validados; -- anunciante e descrição normalizados; -- estados `unreviewed`, `probable`, `confirmed`, `rejected` e `ambiguous`. +Esses registros ficam em quarentena histórica como “vendido visualmente indicado”. O selo é evidência operacional, não prova registral. -## 7. Possíveis quebras de coleta +## 8. Atualização dos rankings -1. **Localização:** `address` e `neighborhood` capturaram grandes trechos da página; cidade, UF e coordenadas ficaram vazias. -2. **Anunciante:** `advertiser_code` e `creci` frequentemente capturaram texto extenso; `advertiser_name` ficou vazio. -3. **Dados estruturados:** o `json_ld` foi preservado como array vazio em todos os anúncios. -4. **Escala numérica:** pelo menos um preço e uma área são claramente suspeitos. -5. **Fotos:** três falhas foram registradas de modo consistente, sem arquivo local. -6. **Execuções vazias:** duas execuções `ok` não coletaram páginas. Sem motivo/configuração persistidos, não é possível diferenciar teste, filtro vazio ou falha silenciosa. -7. **Filtro do Mangueiral:** a URL coletada inclui casas de quatro quartos e não identifica planta original. +O Mangueiral não recebeu anúncio novo em 21/07. `1356197`, antes em 9º, passou a exibir **VENDIDO** na primeira foto. Depois do feedback pessoal, o funil foi refeito sobre os 78 ativos; `1377683`, `1371718` e `1140317` entraram no Top 5 por aderência inferida. A auditoria integral também identificou `1301400` com selo de vendido na primeira foto e `1369473` como solicitação de compra, não oferta. -## 8. Limitações para qualquer conclusão imobiliária +O Cruzeiro recebeu: -- Um único dia não permite análise histórica ou tendência. -- A amostra cobre apenas DF Imóveis e duas buscas específicas. -- Preço anunciado não é preço negociado. -- Não há transações, status comprovado de venda ou evidência de fechamento. -- Não há imóveis físicos deduplicados. -- Não há localização analítica confiável por QC, quadra ou bloco. -- Não há conceito comparável de área. -- O estado de reforma, planta original, elevador, garagem, andar e qualidade funcional não está modelado de forma suficiente. -- Para Jardins Mangueiral, `bedrooms = 3` não valida planta original de três quartos. +- `1381514`: SHCES 301, R$ 690 mil, 4º andar, reforma aparente forte, sem confirmação de elevador ou vaga e com divergência entre 63 e 93 m²; +- `1400223`: SHCES 609 D, R$ 495 mil, 2º andar, boa luz e necessidade de reforma ampla. -Portanto, ainda não é apropriado produzir medianas regionais, comparáveis, preço por m², tempo de anúncio, liquidez ou recomendações de visita com base apenas neste banco. +Os dois entraram no Top 15 condicionado. `1375199` saiu por inatividade; `1370891` passou para “quase entrou” pela nova evidência, não por piora comprovada. -## 9. Próximas ações recomendadas +## 9. Limitações -Antes da análise dos imóveis: +- um único portal e duas buscas; +- janela histórica curta; +- 20 inativos sem causa confirmada; +- snapshots inflados por campos textuais instáveis; +- ausência de entidade de imóvel físico; +- localização estruturada não confiável; +- área semanticamente inconsistente; +- fotos podem conter material genérico e republicações; +- planta original, sistemas, ruído e documentação exigem validação externa. -1. corrigir e testar a extração de endereço, bairro, anunciante e CRECI usando os HTMLs já salvos, sem recrawling; -2. criar uma derivação reproduzível fora do banco original e preservar os valores brutos; -3. separar áreas privativa, útil, construída, total e de terreno, deixando nulo o conceito não comprovado; -4. criar regras explícitas de validação para preço e área, mantendo os outliers identificados em quarentena; -5. filtrar o Mangueiral por planta original de três quartos, não apenas pelo número anunciado; -6. coletar múltiplas datas e auditar a cobertura por busca antes de estimar permanência, entradas ou saídas; -7. numa evolução aprovada do coletor, adicionar `source_id`, `run_id` nos snapshots, referência ao HTML bruto histórico e versão/configuração da coleta; -8. construir `property_candidates` apenas em uma camada derivada, com confiança e revisão, sem fundir registros no banco original. +Não calcular preço por m² amplo, liquidez ou tendência com este snapshot. -## 10. Consultas de reprodução +## 10. Reprodução -Todas devem ser executadas com `sqlite3 -readonly dfimoveis_data/dfimoveis.sqlite3` ou conexão Python URI em `mode=ro` e `PRAGMA query_only = ON`. +Consultas essenciais, sempre em leitura: ```sql --- Objetos do esquema +PRAGMA query_only = ON; +PRAGMA quick_check; +PRAGMA foreign_key_check; + SELECT type, name, tbl_name, sql FROM sqlite_master -ORDER BY type, name; +ORDER BY type, name +LIMIT 50; --- Contagens (executar uma tabela por vez após validar os nomes) -SELECT COUNT(*) FROM crawl_runs; SELECT COUNT(*) FROM listings; SELECT COUNT(*) FROM listing_history; SELECT COUNT(*) FROM listing_searches; SELECT COUNT(*) FROM photos; +SELECT COUNT(*) FROM crawl_runs; --- Cobertura -SELECT MIN(started_at), MAX(finished_at), COUNT(*) -FROM crawl_runs; - -SELECT MIN(first_seen_at), MAX(last_seen_at), - COUNT(DISTINCT date(first_seen_at)) -FROM listings; - --- Número de snapshots por anúncio -SELECT snapshots, COUNT(*) AS listings -FROM ( - SELECT listing_id, COUNT(*) AS snapshots - FROM listing_history - GROUP BY listing_id -) -GROUP BY snapshots; - --- Completude de campos críticos -SELECT - COUNT(*) AS total, - SUM(price_brl IS NULL) AS missing_price, - SUM(area_m2 IS NULL) AS missing_area, - SUM(condominium_brl IS NULL) AS missing_condominium, - SUM(iptu_brl IS NULL) AS missing_iptu, - SUM(latitude IS NULL OR longitude IS NULL) AS missing_coordinates -FROM listings; - --- Contaminação textual sem imprimir os textos -SELECT - SUM(length(address) > 300) AS long_address, - SUM(length(neighborhood) > 100) AS long_neighborhood, - SUM(length(advertiser_code) > 100) AS long_advertiser_code, - SUM(length(creci) > 100) AS long_creci -FROM listings; - --- Integridade referencial e física -PRAGMA quick_check; -PRAGMA foreign_key_check; +SELECT s.search_url, + COUNT(*) AS accumulated, + SUM(l.inactive_at IS NULL) AS active, + SUM(l.inactive_at IS NOT NULL) AS inactive +FROM listing_searches AS s +JOIN listings AS l USING (listing_id) +GROUP BY s.search_url +LIMIT 10; ``` -## 11. Implicação para a decisão de compra +## 11. Implicação prática -Esta avaliação reduz o risco de transformar uma coleta tecnicamente bem-sucedida em falsa precisão de mercado. O próximo ganho real não virá de comparar preços imediatamente, mas de corrigir localização e semântica de área, acumular histórico e construir uma deduplicação reversível. Até lá, os registros são úteis como inventário bruto de anúncios e arquivos, não como avaliação consolidada de imóveis físicos. +O snapshot melhora a triagem operacional, sobretudo ao revelar inativos e dois apartamentos novos. Ele ainda não justifica pressa nem conclusões de mercado. O ganho imediato vem de manter quarentenas visuais, corrigir a geração excessiva de snapshots e validar documentalmente os candidatos antes de visita ou negociação. diff --git a/reports/mangueiral_top10/README.md b/reports/mangueiral_top10/README.md deleted file mode 100644 index 06bd464..0000000 --- a/reports/mangueiral_top10/README.md +++ /dev/null @@ -1,184 +0,0 @@ -# Ranking preliminar — casas no Jardins Mangueiral - -**Data de referência do snapshot:** 17/07/2026 -**Relatório revisado:** 17/07/2026 -**Unidade principal:** imóvel físico provável, não snapshot nem anúncio isolado -**Finalidade:** priorizar visitas; não estimar preço negociado nem substituir vistoria ou validação documental - -## Pergunta - -Quais são as dez casas do Jardins Mangueiral que mais merecem atenção segundo as preferências e regras do projeto, dando às fotografias importância comparável à dos dados estruturados? - -## Universo e método - -Foram avaliados os 94 anúncios acumulados encontrados pela busca de casas no Jardins Mangueiral: 84 estavam ativos e 10 inativos no snapshot consistente de 17/07/2026. A base cobre um único portal. Há 159 anúncios nas duas regiões, 295 snapshots de conteúdo e 6.272 mídias; 133 anúncios têm dois snapshots, mas quatro mudanças foram materialmente relevantes nos campos imobiliários e apenas uma delas foi preço. - -Como o banco estava em WAL, ele foi aberto com `mode=ro`, sem `immutable=1`, dentro de uma transação de leitura consistente e com `PRAGMA query_only = ON`. Entre os anúncios ativos, 80 informam três quartos e preço plausível entre R$ 450 mil e R$ 1,15 milhão. O anúncio de R$ 1,15 milhão descreve outra implantação, no condomínio American Garden, e não a casa-padrão de 68 m² das QCs; não é comparável ao universo prioritário. Esses números descrevem anúncios, não imóveis únicos nem preços negociados. - -Não foi calculado preço por metro quadrado: os campos e descrições misturam área privativa, construída, total e de terreno. Tampouco foi criada pontuação numérica, porque os pesos não foram aprovados. A ordem é uma **prioridade de visita ajustada por risco**, considerando em conjunto: - -1. compatibilidade provável com a planta original de três quartos; -2. funcionalidade, circulação, armazenamento e flexibilidade de longo prazo; -3. qualidade real da conversão do quintal, sem penalizar fechamento automaticamente; -4. luz e ventilação aparentes, conservação e coerência dos acabamentos; -5. risco e transtorno de adequação; -6. preço, condomínio, IPTU, vagas e área anunciados; -7. QCs citadas nos relatos de moradores, apenas como evidência anedótica; -8. completude, coerência e confiabilidade das fotos. - -### Filtro da planta original - -Os dez imóveis abaixo têm fachada, posição de escada, distribuição e dormitórios fotografados compatíveis com a tipologia padrão de três quartos, e nenhum deles é descrito como conversão de dois para três quartos. Isso sustenta apenas a classificação **planta original provável**. A confirmação exige planta, matrícula ou documentação da unidade. O anúncio 1374012, por exemplo, foi retirado da disputa apesar do preço baixo porque a própria descrição informa “3 quartos sendo 1 adaptado”. - -### Revisão fotográfica - -Em 17/07/2026, a primeira foto de todos os escolhidos foi auditada especificamente para marcas de “vendido” ou “negócio fechado”. Quatro anúncios que chegaram a integrar versões do ranking foram removidos por esse critério: `1346231`, `1349519`, `1351729` e `1366801`. - -A revisão anterior havia examinado 1.892 arquivos distintos. Nesta atualização foram revisadas as imagens iniciais dos novos anúncios elegíveis e, em detalhe, 15 imagens coerentes do novo finalista `1397378`; imagens posteriores da galeria que pertencem visualmente a outros imóveis foram descartadas como contaminação. As plantas oficiais de duas e três unidades de três quartos e os mapas locais em `resources/` também foram confrontados com a galeria e a QC. - -As fotos foram usadas para avaliar coerência da planta, presença dos três dormitórios, circulação, luz, ventilação aparente, conservação, cozinha, banheiros, lavanderia, quintal, integração social e qualidade das ampliações. Elas não validam elétrica, hidráulica, impermeabilização, estrutura, calor, ruído ou regularização. - -As galerias baixadas frequentemente continuam, depois das imagens do imóvel, com recomendações do portal, fotos de outras casas, selos de “vendido”, publicidade e logos. Esses arquivos foram vistos, identificados pela quebra de coerência visual e desconsiderados. Por isso, quantidade bruta de fotos não foi tratada como qualidade de evidência, e hashes compartilhados foram usados apenas para triagem manual de duplicidade. - -## Ranking - -### 1. Anúncio 1279892 — QC 10 - -- **Anunciado:** R$ 595.000; 68 m² no campo estruturado e 107 m² na descrição; condomínio R$ 383; IPTU R$ 1.050; 3 quartos, 1 suíte; 1 vaga informada no banco. -- **Por que lidera:** oferece o melhor equilíbrio entre preço, localização considerada boa nos relatos, reforma pronta e planta visualmente coerente. A diferença para casas mais caras parece estar mais na ausência de mobiliário do que em obra obrigatória. -- **Fotos:** ambientes claros, sala ampla, cozinha planejada bem executada, banheiros atualizados e três dormitórios reconhecíveis. O fundo combina área coberta e trechos abertos, preservando luz e ventilação; não aparece uma segunda cozinha completa redundante. -- **Pendências:** esclarecer os conceitos de 68 e 107 m², a DCE citada, regularização das ampliações, número jurídico de vagas e impermeabilização da cobertura translúcida. -- **Ação:** candidato forte; visitar primeiro. -- **URL:** https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-rua-f-1279892 - -### 2. Anúncio 1350367 — QC 6 - -- **Anunciado:** R$ 569.000; 68 m² no banco, 107 m² totais e terreno de 131 m² na descrição; condomínio R$ 320; 3 quartos, 1 suíte; 2 vagas. -- **Por que está no topo:** preço baixo para o grupo final, QC considerada alternativa prática e ampliação social que parece efetivamente utilizável. -- **Fotos:** casa vazia, clara e aparentemente reformada; banheiros e pisos coerentes; três dormitórios aparentes. O quintal foi convertido em uma varanda ampla com churrasqueira e bancada, mas mantém abertura lateral e circulação, em vez de virar cômodo escuro ou segunda cozinha fechada. -- **Pendências:** confirmar área construída, licenças, ventilação e calor sob a cobertura, drenagem, elétrica da ampliação e o que falta de marcenaria/mobiliário. -- **Ação:** candidato forte; visitar. -- **URL:** https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-6-rua-c-1350367 - -### 3. Anúncio 1346017 — QC 10 - -- **Anunciado:** R$ 577.000; 68 m²; condomínio e IPTU ausentes; 3 quartos, 1 suíte; 2 vagas. -- **Por que se destaca:** casa pronta, luminosa e pouco personalizada por preço competitivo, em QC considerada boa nos relatos. -- **Fotos:** sala e jantar funcionais, cozinha planejada, três quartos claros e banheiros conservados. O quintal permanece majoritariamente aberto, com cobertura leve e uso social simples; é uma das soluções menos arriscadas para ventilação e manutenção. -- **Pendências:** confirmar proteção contra chuva, privacidade, área de serviço, taxas, orientação solar e regularização de qualquer cobertura. -- **Ação:** candidato forte; visitar. -- **URL:** https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-1346017 - -### 4. Anúncio 1397378 — QC 8 - -- **Anunciado:** R$ 600.000; 68 m²; condomínio R$ 316,14; IPTU R$ 1.119,67; 3 quartos, 1 suíte; 2 vagas. -- **Por que se destaca:** QC 8 tem acesso prático a comércio e serviços nos mapas fornecidos, e a casa combina preço intermediário com implantação próxima da planta original de três quartos. -- **Fotos:** sala e cozinha claras, marcenaria utilizável, três dormitórios aparentes e escada/andar superior compatíveis com a planta de 68 m². O fundo mantém trecho aberto, corredor lateral e cobertura parcial, sem transformar todo o quintal em segunda cozinha. Há sinais de acabamento simples e manutenção pontual, mas não de reforma integral imediata. -- **Pendências:** confirmar planta e documentos, origem das marcas/acabamentos, drenagem linear, impermeabilização da cobertura, orientação solar e itens de marcenaria que permanecem. Parte final da galeria está contaminada por fotos de outros imóveis e foi desconsiderada. -- **Ação:** candidato forte; visitar depois dos três primeiros. -- **URL:** https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-8-rua-b-1397378 - -### 5. Anúncio 1359960 — QC 7 - -- **Anunciado:** R$ 610.000; 68 m²; condomínio R$ 339; IPTU R$ 1.128,19; 3 quartos, 1 suíte; 2 vagas. -- **Por que entra:** QC considerada alternativa prática e conversão do quintal que cria uma sala social ampla, em vez de apenas instalar equipamentos com rótulo “gourmet”. -- **Fotos:** boa sala frontal, cozinha planejada, três quartos aparentes e grande espaço coberto nos fundos, hoje usado para descanso e convivência. Não foi identificada segunda cozinha completa; a ampliação parece flexível e mobiliável. -- **Pendências:** o fechamento é extenso; testar calor, ventilação cruzada, iluminação noturna, exaustão, acústica e impermeabilização antes de valorizá-lo. -- **Ação:** visitar com foco no conforto ambiental da ampliação. -- **URL:** https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-7-1359960 - -### 6. Anúncio 1319996 — QC 14 - -- **Anunciado:** R$ 649.000; 68 m²; condomínio e IPTU ausentes; 3 quartos, 1 suíte; 2 vagas. -- **Por que se destaca:** uma das reformas mais completas e coerentes, com placas solares e boa separação entre convivência e lavanderia. -- **Fotos:** acabamento uniforme, marcenaria abundante, três dormitórios aparentes, banheiros atualizados e área externa coberta com bancada, churrasqueira, abertura lateral e circulação suficiente para receber pessoas. -- **Pendências:** QC 14 não está entre as QCs priorizadas pelos relatos; confirmar taxas, homologação das placas, ventilação/exaustão, manutenção da cobertura e escopo técnico da reforma. -- **Ação:** visitar como referência de imóvel pronto. -- **URL:** https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-1319996 - -### 7. Anúncio 1324014 — QC 12 - -- **Anunciado:** R$ 649.000; 68 m²; condomínio e IPTU ausentes; 3 quartos, 1 suíte; vaga não extraída. -- **Por que entra:** acabamento interno e marcenaria fortes, com área social coberta bem executada e condição aparente de ocupação sem reforma relevante. -- **Fotos:** cozinha, sala e banheiros atualizados; a área gourmet é ampla e iluminada, mas concentra churrasqueira, bancada e apoio muito próximos da cozinha principal. -- **Pendências:** confirmar vaga, planta original, ventilação, exaustão, conforto térmico, drenagem, regularização da cobertura e se a duplicação de equipamentos melhora de fato a rotina. -- **Ação:** visitar depois dos candidatos mais baratos e das QCs prioritárias. -- **URL:** https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-12-rua-k-1324014 - -### 8. Anúncio 1333569 — QC 6 - -- **Anunciado:** R$ 650.000; 90 m²; condomínio e IPTU ausentes; 3 quartos, 1 suíte; 2 vagas. -- **Por que entra:** QC considerada alternativa prática e ampliação social já em uso, com abertura superior e lateral que pode mitigar o fechamento do quintal. -- **Fotos:** casa ocupada, bem conservada e funcional; a área externa reúne jantar, estar e churrasqueira, com cobertura aparentemente translúcida/retrátil. Os cômodos íntimos parecem utilizáveis, embora menos bem documentados que nos primeiros colocados. -- **Pendências:** confirmar se os 90 m² são comparáveis, funcionamento e manutenção da cobertura, exaustão, calor, iluminação, taxas e regularização. -- **Ação:** visitar depois dos oito primeiros. -- **URL:** https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-6-1333569 - -### 9. Anúncio 1359480 — QC 4 - -- **Anunciado:** R$ 535.000; 70 m²; condomínio R$ 330; IPTU ausente; 3 quartos, 1 suíte; 2 vagas. -- **Por que entra:** é a alternativa de menor preço entre os finalistas habitáveis e preserva margem financeira para custos de aquisição e adequações. -- **Fotos:** sala integrada utilizável, cozinha e banheiros funcionais e três dormitórios aparentes. O quintal/lavanderia têm acabamento mais simples que os líderes, mas não sugerem obra estrutural imediata nas imagens. -- **Pendências:** QC 4 precisa provar conveniência logística; confirmar planta original, área de 70 m², documentação, drenagem, impermeabilização e orçamento de acabamento externo. -- **Ação:** visitar como referência de valor e limite inferior de preço. -- **URL:** https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-4-1359480 - -### 10. Anúncio 1356197 — QC 4 - -- **Anunciado:** R$ 649.000; 68 m²; condomínio R$ 316; IPTU ausente; 3 quartos, 1 suíte; 2 vagas. -- **Por que entra:** casa vazia com acabamento interno forte e condição aparente de ocupação sem reforma relevante. -- **Fotos:** sala, cozinha, banheiros e marcenaria bem conservados; boa parte do espaço coberto parece funcionar como garagem, com menor evidência de quintal social útil. -- **Pendências:** confirmar planta original, uso e ventilação do espaço coberto, drenagem, impermeabilização, regularização e conveniência da QC 4. -- **Ação:** visitar depois dos nove primeiros. -- **URL:** https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-4-1356197 - -## Quase entraram - -- **[1368562](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-5-1368562), QC 5, R$ 720.000:** ampliação de aproximadamente 110 m² bem executada e ventilada por cobertura translúcida, mas o prêmio de preço e a QC menos prioritária reduzem a urgência da visita. - -## Quarentenas e exclusões relevantes - -- **1351729:** a primeira foto declara “VENDIDO” e “negócio fechado”. Isso não comprova registro ou preço da transação, mas é evidência suficiente de indisponibilidade operacional; removido do ranking de visitas por correção do usuário em 17/07/2026. -- **1349519:** a primeira foto também declara “VENDIDO” e “negócio fechado”, com o código correspondente ao anúncio. Removido do ranking de visitas por correção do usuário em 17/07/2026. -- **1366801:** a primeira foto declara “VENDIDO” e “negócio fechado”, com o código 1468 correspondente ao anúncio. Removido do ranking de visitas por correção do usuário em 17/07/2026. -- **1346231:** a primeira foto declara “VENDIDO” e “negócio fechado”, com o código 1428 correspondente ao anúncio. Removido após auditoria sistemática das primeiras fotos em 17/07/2026. -- **1350829 e 1358463:** anunciados com quatro quartos; fora do filtro. -- **1374012:** a descrição declara que um dos três quartos é adaptado; não há prova suficiente de planta original de três quartos. -- **1351663:** preço estruturado de R$ 570 milhões, erro evidente de escala; excluído até correção. -- **1369473 e 1336887:** galerias dominadas por material genérico ou de outros anúncios, sem evidência suficiente do imóvel. -- **1301400 e 1201070:** fotos com marcação de vendido/permuta; tratadas como inconsistência, não prova de venda. -- **1041635 e 1383513:** mesmo imóvel provável pelas fotos; a repetição não foi contada como duas opções. -- **1239730, 1242337, 1294027, 1359192, 1359662 e 1367341:** grupo de republicações prováveis da mesma unidade; a oferta não foi inflada. -- **1354016 e 1377683:** duplicata provável após revisão visual; seria uma única opção, não duas. -- **1356153, 1358854 e 1358920:** grupo provável de uma mesma casa vazia. -- **1348449 e 1351461:** descrições e composição praticamente idênticas na QC 13; tratar como mesmo imóvel até confirmação. - -## Qualidade e limitações - -- O banco contém anúncios e snapshots de conteúdo, não imóveis físicos confirmados. Os dois pontos observados ainda são insuficientes para tendência ou tempo real de mercado. -- Entre os 84 anúncios ativos do Mangueiral, condomínio falta em 40 e IPTU em 74; não foi possível comparar custo mensal com consistência. -- Área existe em todos os registros, mas não é semanticamente comparável. Os próprios finalistas exibem divergências entre banco e descrição. -- A busca e as galerias contêm material contaminante do portal. Duplicidades foram classificadas manualmente e permanecem probabilísticas. -- Anúncio, foto e descrição não confirmam planta original, regularização da ampliação, documentação, estrutura ou sistemas. -- As preferências por QC vêm de relatos anedóticos e precisam ser testadas em deslocamentos e visitas reais. -- A referência financeira de R$ 650 mil a R$ 750 mil não foi assumida como atual. O ranking prioriza visitas, não define capacidade de compra ou preço máximo. - -## Verificações obrigatórias nas visitas - -1. solicitar planta original, matrícula, habite-se e documentos das ampliações; -2. medir os três quartos e conferir posição da escada, fachada e implantação; -3. testar calor, ventilação, luz e ruído com portas e janelas fechadas e abertas; -4. inspecionar telhado, rufos, calhas, impermeabilização, drenagem e sinais de infiltração; -5. testar quadro elétrico, aterramento, tomadas, hidráulica, pressão e escoamento; -6. verificar se a área gourmet duplica a cozinha ou realmente melhora a rotina; -7. confirmar condomínio, IPTU, vagas, taxas extras, regras de obra e atas; -8. percorrer a QC em horários relevantes para comércio, trânsito, segurança, ruído e estacionamento; -9. só depois estimar adequação e definir preço máximo de negociação. - -## Reprodutibilidade - -- `analysis.py`: extrai banco e HTMLs em leitura, produzindo TSV. -- `photo_similarity.py`: sinaliza pares por hash visual simples; exige revisão humana e sofre com imagens genéricas do portal. -- `query.sql`: consultas principais de universo e qualidade. -- `parameters.json`: parâmetros e fingerprint do snapshot. -- `results.csv`: ranking em formato tabular. diff --git a/reports/mangueiral_top10/__pycache__/analysis.cpython-312.pyc b/reports/mangueiral_top10/__pycache__/analysis.cpython-312.pyc deleted file mode 100644 index db9baaa..0000000 Binary files a/reports/mangueiral_top10/__pycache__/analysis.cpython-312.pyc and /dev/null differ diff --git a/reports/mangueiral_top10/__pycache__/analysis.cpython-314.pyc b/reports/mangueiral_top10/__pycache__/analysis.cpython-314.pyc deleted file mode 100644 index 272ea52..0000000 Binary files a/reports/mangueiral_top10/__pycache__/analysis.cpython-314.pyc and /dev/null differ diff --git a/reports/mangueiral_top10/__pycache__/photo_similarity.cpython-312.pyc b/reports/mangueiral_top10/__pycache__/photo_similarity.cpython-312.pyc deleted file mode 100644 index 254cd15..0000000 Binary files a/reports/mangueiral_top10/__pycache__/photo_similarity.cpython-312.pyc and /dev/null differ diff --git a/reports/mangueiral_top10/__pycache__/photo_similarity.cpython-314.pyc b/reports/mangueiral_top10/__pycache__/photo_similarity.cpython-314.pyc deleted file mode 100644 index 4d8e4b1..0000000 Binary files a/reports/mangueiral_top10/__pycache__/photo_similarity.cpython-314.pyc and /dev/null differ diff --git a/reports/mangueiral_top10/parameters.json b/reports/mangueiral_top10/parameters.json deleted file mode 100644 index c3e9eb8..0000000 --- a/reports/mangueiral_top10/parameters.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "analysis_date": "2026-07-17", - "listing_data_reference_date": "2026-07-17", - "database_path": "dfimoveis_data/dfimoveis.sqlite3", - "database_main_file_sha256": "7a5102a62bc66a344bd9440fa36301d10a57711bcdd263b767b65e88f70957f4", - "logical_snapshot_sha256": "fe604aab8af7f67c833e6de2a0fc81c7dc2950ca440ad7b23ebd03d0c2546188", - "database_mode": "read_only_transaction_with_wal", - "search_url_fragment": "/jardins-mangueiral/", - "listing_limit": 150, - "observed_listing_count": 94, - "active_listing_count": 84, - "inactive_listing_count": 10, - "database_crawl_run_count": 16, - "new_listing_count_since_previous_report": 3, - "active_plausible_price_three_bedroom_count": 80, - "ranking_unit": "probable_physical_property", - "numeric_score_used": false, - "original_three_bedroom_requires_document_confirmation": true, - "photo_first_pass_limit_per_listing": 16, - "photo_first_pass_files": 1449, - "photo_finalist_count": 19, - "photo_finalist_files": 747, - "photo_files_reviewed_distinct_cumulative": 1907, - "new_finalist_photos_reviewed": 15, - "plans_reviewed": 2, - "map_captures_reviewed": 6, - "first_photo_sale_marker_audit_count": 10, - "visually_unavailable_listing_ids": ["1346231", "1349519", "1351729", "1366801"] -} diff --git a/reports/mangueiral_top10/results.csv b/reports/mangueiral_top10/results.csv deleted file mode 100644 index 14bfe67..0000000 --- a/reports/mangueiral_top10/results.csv +++ /dev/null @@ -1,11 +0,0 @@ -rank,representative_listing_id,probable_duplicate_ids,qc,price_brl,area_m2,bedrooms,suites,parking_spaces,original_three_bedroom_status,decision -1,1279892,,10,595000,68,3,1,1,probable_pending_documents,strong_candidate -2,1350367,,6,569000,68,3,1,2,probable_pending_documents,strong_candidate -3,1346017,,10,577000,68,3,1,2,probable_pending_documents,strong_candidate -4,1397378,,8,600000,68,3,1,2,probable_pending_documents,strong_candidate -5,1359960,,7,610000,68,3,1,2,probable_pending_documents,visit_and_test_closed_yard -6,1319996,,14,649000,68,3,1,2,probable_pending_documents,visit -7,1324014,,12,649000,68,3,1,,probable_pending_documents,visit -8,1333569,,6,650000,90,3,1,2,probable_pending_documents,visit_after_top_eight -9,1359480,,4,535000,70,3,1,2,probable_pending_documents,visit_as_value_reference -10,1356197,,4,649000,68,3,1,2,probable_pending_documents,visit_after_top_nine diff --git a/reports/mangueiral_top15/README.md b/reports/mangueiral_top15/README.md new file mode 100644 index 0000000..c45dd4e --- /dev/null +++ b/reports/mangueiral_top15/README.md @@ -0,0 +1,70 @@ +# Top 15 — Jardins Mangueiral + +**Snapshot:** 22/07/2026 (execução 22, concluída às 21h34 no horário de Brasília) + +**Objetivo:** priorizar investigação na região principal do projeto, somente entre casas com planta original provável de três quartos e horizonte de 10–20 anos. + +## Universo e método + +O banco foi aberto somente para leitura. Há 162 anúncios, 638 observações históricas e 7.457 registros históricos de foto; apenas os 3.521 registros marcados como galeria primária foram admitidos como evidência fotográfica. No Mangueiral são 95 anúncios acumulados, 78 ativos e 17 inativos. A coleta cobre 13–22/07/2026. Foram separados anúncio, imóvel provável e observação histórica, deduplicando republicações por fotos, descrição e implantação. + +Desde o relatório anterior, `1401074` entrou no universo e `1290512` ficou inativo; a ausência não prova venda. A execução 22 examinou 78 anúncios sem falhas de detalhe e registrou uma única mudança material: `348115` passou de R$ 530 mil para R$ 550 mil. Os demais “changes” históricos são majoritariamente ruído legado de campos contaminados e não foram interpretados como movimento de mercado. + +O ranking considera planta original provável de três quartos, QC, funcionalidade da conversão do quintal, cozinha, ventilação, iluminação, conservação, vagas, regularidade e custo de adequação. Fechar o quintal não gera penalidade automática; a funcionalidade real da intervenção é que importa. Áreas anunciadas não foram usadas para preço por m² porque misturam privativa, construída e ampliada. A planta permanece **provável e pendente de documentos** em todos os finalistas. + +O novo teto pessoal foi aplicado como filtro eliminatório: **preço anunciado máximo de R$ 750 mil**. Dos 78 ativos, 73 têm três quartos estruturados e preço entre R$ 1 e R$ 750 mil antes das demais quarentenas. O teto não é meta de gasto e não inclui ITBI, registro, mudança, reforma ou regularização; todos esses desembolsos ainda precisam preservar ao menos R$ 50 mil de reserva líquida. + +Em 21/07, o usuário avaliou individualmente os 15 finalistas anteriores em escala de 1 a 5. Como esse feedback revelou critérios capazes de alterar também o funil de entrada, a análise foi refeita sobre os **78 anúncios ativos**, não apenas reordenada. Foram relidas descrições e características de todo o universo, reaplicadas quarentenas e duplicatas e revistas as galerias dos sobreviventes mais plausíveis. A coluna “nota” só contém avaliações dadas pelo usuário; “inferida” significa aderência estimada pelas evidências, ainda pendente de validação pessoal. + +## Auditoria da primeira foto + +As primeiras fotos dos 78 anúncios ativos foram triadas, incluindo a primeira foto de `1401074`. `1301400`, `1346017`, `1346231`, `1349519`, `1351729`, `1352943`, `1356197`, `1362968` e `1366801` exibem “VENDIDO”, “negócio fechado” ou equivalente, embora ainda estejam ativos no portal. Nenhum dos 15 colocados atuais apresenta esse indicativo. O selo indica provável indisponibilidade operacional, não comprova a transação. + +A triagem perceptual foi reexecutada com Pillow 12.3.0. Ela recuperou os grupos de republicação já conhecidos; entre os candidatos, `1363572` teve sinal fraco com `1370918` (quatro fotos semelhantes). A divergência de área e a baixa quantidade de correspondências não justificam consolidá-los automaticamente. A similaridade não provocou nova consolidação; a mudança do ranking decorreu do feedback do usuário e da revisão integral do universo ativo. + +## Ranking + +| # | Anúncio | Nota | QC | Preço | Leitura após análise integral | Principal pendência | +|---:|---|---:|---:|---:|---|---| +| 1 | [1279892](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-rua-f-1279892) | 4/5 | 10 | R$ 595 mil | Boa cozinha semi-integrada à área gourmet; poucas alterações e bom preço | Planta, áreas divergentes e regularização | +| 2 | [1319996](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-1319996) | 4/5 | 14 | R$ 649 mil | Cozinha, gourmet, quintal, quartos e banheiros fortes; energia solar é bônus | Reversão futura do closet, cobertura e homologação solar | +| 3 | [1377683](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-11-1377683) | inferida | 11 | R$ 585 mil | Cozinha clara e funcional ligada a gourmet aberto, bom preço e conservação aparente | Usuário avaliar; planta, cobertura, drenagem e ruído | +| 4 | [1371718](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-rua-c-1371718) | inferida | 14 | R$ 650 mil | Cozinha equipada, marcenaria conservada e gourmet aberto sem piscina | Usuário avaliar; sistemas, cobertura e insolação | +| 5 | [1140317](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-5-rua-l-1140317) | inferida | 5 | R$ 599 mil | Cozinha bem equipada e área gourmet aberta integrada ao fluxo da casa | Usuário avaliar; acabamento heterogêneo, cobertura e uma vaga anunciada | +| 6 | [1324014](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-12-rua-k-1324014) | 3/5 | 12 | R$ 649 mil | Gourmet agradável, cozinha razoavelmente espaçosa e boa conservação | Confirmar vaga e ventilação; sanca é incômodo reversível | +| 7 | [1290502](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-11-1290502) | 3/5 | 11 | R$ 600 mil | Reforma, cozinha e banheiros adequados; gourmet pode ser implementado | Planta, cobertura, posição solar, custo do gourmet e preço R$ 600/620 mil | +| 8 | [1401074](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-13-1401074) | inferida | 13 | R$ 720 mil | Casa conservada, cozinha planejada e gourmet aberto ligado a quintal amplo | Usuário avaliar; cuba de vidro, acabamentos externos, documentação dos 110 m² e cobertura | +| 9 | [1345745](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-quadra-qc-12-1345745) | inferida | 12 | R$ 670 mil | Cozinha funcional e gourmet amplo, conectado e sem equipamento aquático | Usuário avaliar; calor, ventilação e regularidade da grande cobertura | +| 10 | [1333569](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-6-1333569) | 3/5 | 6 | R$ 650 mil | Gourmet e banheiros bons | Testar efeito estufa do fechamento em vidro e fluxo interno confuso | +| 11 | [1357311](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-1-rua-a-1357311) | inferida | 1 | R$ 699,9 mil | Cozinha conectada a gourmet grande e iluminado | Usuário avaliar; sinais aparentes de infiltração/desplacamento no teto, QC e preço | +| 12 | [1357912](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-3-1357912) | 3/5 | 3 | R$ 580 mil | Espaços bem aproveitados | Marcenaria básica e intervenções futuras antes da mudança | +| 13 | [1259149](https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-11-1259149) | inferida | 11 | R$ 590 mil | Preço e QC razoáveis, quintal parcialmente aberto | Usuário avaliar; acabamento básico, área anunciada e custo de adequação | +| 14 | [348115](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-rua-c-348115) | inferida | 14 | R$ 550 mil | Preço baixo, três quartos e churrasqueira sem piscina anunciada | Usuário avaliar; anúncio antigo, conservação, coerência dos 120 m² e modernização | +| 15 | [1346118](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-14-1346118) | inferida | 14 | R$ 550 mil | Base simples e barata, sem intervenção aquática anunciada | Usuário avaliar; exige modernização e área diverge entre 63/110 m² | + +## Quase entraram + +- [1352633](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-9-rua-g-1352633), QC 9, R$ 755 mil: visualmente aderente, mas **excluído do ranking por superar o teto confirmado de R$ 750 mil**. +- `1290512`, anteriormente avaliado em 3/5, ficou inativo em 22/07; a ausência foi registrada sem inferir venda. +- `1353638`, antes entre os quase classificados, ficou inativo em 21/07; a ausência foi registrada sem inferir venda. +- [1041635](https://www.dfimoveis.com.br/imovel/casa-condominio-3-quartos-venda-jardins-mangueiral-brasilia-df-qc-10-1041635), QC 10, R$ 690 mil: piscina e boa localização; é provável duplicata de `1383513` e exige auditoria estrutural maior. + +## Quarentenas e limitações + +- Vendido na primeira foto: `1301400`, `1346017`, `1346231`, `1349519`, `1351729`, `1352943`, `1356197`, `1362968` e `1366801`. +- Acima do teto de R$ 750 mil: `1352633` (R$ 755 mil) e qualquer outra oferta que ultrapasse o limite, ainda que visualmente aderente. +- Novos inativos em 21/07: `1346001`, `1350155`, `1353638` e `1358463`; ausência da busca não prova venda. +- Novo inativo em 22/07: `1290512`; ausência da busca não prova venda. +- `1201070` possui marcação de permuta na galeria e permanece fora; permuta não foi tratada como prova de venda. +- `1369473` é uma solicitação de compra (“procuro casa”), não uma oferta imobiliária, e foi colocado em quarentena por incompatibilidade de fonte. +- `1350829` e `1358463` anunciam quatro quartos; `1348449` e `1374012` declaram quarto adaptado; `1026522` diverge do campo estruturado ao descrever quatro quartos; `1351663` tem preço estruturado de R$ 570 milhões. +- Grupos de republicações não foram multiplicados, incluindo `1041635`/`1383513`, `1239730`/`1242337`/`1294027`/`1359192`/`1359662`, `1354016`/`1377683` e `1356153`/`1358854`/`1358920`. +- Só visita e documentação confirmam planta original, licenças, estrutura, impermeabilização, insolação, taxas e disponibilidade. + +## Próxima ação + +Começar a diligência documental por `1279892` e `1319996` e pedir ao usuário uma avaliação visual de `1377683`, `1371718`, `1140317` e `1401074`. Antes de visitar, exigir planta original, QC/condomínio exatos, área privativa versus ampliada e aprovação da cobertura. Piscina, jacuzzi e banheira são incompatibilidades funcionais confirmadas, não bônus; placas solares exigem documentação própria. Para qualquer finalista, calcular custos de compra e adequação além do preço sem violar a reserva mínima. + +## Reprodutibilidade + +Execute `python reports/mangueiral_top15/analysis.py` para a extração somente leitura. O julgamento fotográfico e a deduplicação final estão documentados aqui. diff --git a/reports/mangueiral_top10/analysis.py b/reports/mangueiral_top15/analysis.py similarity index 97% rename from reports/mangueiral_top10/analysis.py rename to reports/mangueiral_top15/analysis.py index 72547a1..0266cf6 100644 --- a/reports/mangueiral_top10/analysis.py +++ b/reports/mangueiral_top15/analysis.py @@ -72,7 +72,7 @@ def main() -> int: l.raw_html_path, COUNT(p.source_url) AS photo_count FROM listings AS l JOIN listing_searches AS s USING (listing_id) - LEFT JOIN photos AS p USING (listing_id) + LEFT JOIN photos AS p ON p.listing_id=l.listing_id AND p.is_primary_gallery=1 WHERE instr(s.search_url, ?) > 0 AND l.inactive_at IS NULL GROUP BY l.listing_id diff --git a/reports/mangueiral_top15/parameters.json b/reports/mangueiral_top15/parameters.json new file mode 100644 index 0000000..9dac84d --- /dev/null +++ b/reports/mangueiral_top15/parameters.json @@ -0,0 +1,38 @@ +{ + "analysis_date": "2026-07-22", + "listing_data_reference_date": "2026-07-22", + "database_path": "dfimoveis_data/dfimoveis.sqlite3", + "database_main_file_sha256": "2d02c4c15f56ae60b1ce8ee1aa00c453e61cb0559d5c429ad7e20cb58802341c", + "database_mode": "read_only_transaction_with_wal", + "search_url_fragment": "/jardins-mangueiral/", + "listing_limit": 150, + "observed_listing_count": 95, + "active_listing_count": 78, + "inactive_listing_count": 17, + "database_crawl_run_count": 22, + "database_listing_count": 162, + "database_observation_count": 638, + "database_photo_record_count": 7457, + "primary_gallery_photo_count": 3521, + "active_mangueiral_primary_gallery_photo_count": 1865, + "active_three_bedroom_at_or_below_price_ceiling_count": 73, + "full_active_universe_reprocessed_after_user_feedback": true, + "full_active_universe_size": 78, + "new_inferred_fit_listing_ids_pending_user_review": ["1377683", "1371718", "1140317", "1401074", "1345745", "1357311", "1259149", "348115", "1346118"], + "ranking_size": 15, + "ranking_unit": "probable_physical_property", + "numeric_score_used": false, + "maximum_tolerated_listing_price_brl": 750000, + "price_ceiling_is_eliminatory": true, + "price_ceiling_excludes_transaction_and_renovation_costs": true, + "user_feedback_date": "2026-07-21", + "user_visual_functional_score_scale": "1_to_5", + "user_visual_functional_scores_by_listing_id": {"1279892": 4, "1350367": 2, "1397378": 1, "1359960": 2, "1319996": 4, "1324014": 3, "1333569": 3, "1359480": 1, "1290502": 3, "1368562": 2, "1202799": 2, "1357912": 3, "1363572": 2, "1290512": 3, "1354257": 2}, + "price_per_m2_used": false, + "original_three_bedroom_requires_document_confirmation": true, + "first_photo_active_universe_audit_count": 78, + "visually_unavailable_listing_ids": ["1301400", "1346017", "1346231", "1349519", "1351729", "1352943", "1356197", "1362968", "1366801"], + "source_mismatch_listing_ids": ["1369473"], + "adapted_or_inconsistent_bedroom_listing_ids": ["1026522", "1348449", "1374012"], + "context_documents_reviewed": ["docs/CURRENT_STATE.md", "docs/PROJECT_CONTEXT.md", "docs/LOCATION_CRITERIA.md", "docs/PROPERTY_CRITERIA.md", "docs/FINANCIAL_STRATEGY.md", "docs/SCRAPER_OPERATIONS.md", "docs/DATA_MODEL.md", "docs/ANALYSIS_RULES.md"] +} diff --git a/reports/mangueiral_top10/photo_similarity.py b/reports/mangueiral_top15/photo_similarity.py similarity index 92% rename from reports/mangueiral_top10/photo_similarity.py rename to reports/mangueiral_top15/photo_similarity.py index 57cc216..40265ae 100644 --- a/reports/mangueiral_top10/photo_similarity.py +++ b/reports/mangueiral_top15/photo_similarity.py @@ -22,7 +22,7 @@ DATA_ROOT = DB_PATH.parent def difference_hash(path: Path) -> int | None: try: with Image.open(path) as image: - pixels = list(image.convert("L").resize((9, 8)).getdata()) + pixels = list(image.convert("L").resize((9, 8)).get_flattened_data()) except (OSError, UnidentifiedImageError): return None value = 0 @@ -48,7 +48,7 @@ def main() -> None: ), uncommon AS ( SELECT sha256 FROM photos - WHERE sha256 IS NOT NULL + WHERE sha256 IS NOT NULL AND is_primary_gallery=1 GROUP BY sha256 HAVING COUNT(DISTINCT listing_id) <= 5 ) @@ -56,7 +56,7 @@ def main() -> None: FROM photos AS p JOIN mangueiral AS m USING (listing_id) JOIN uncommon AS u USING (sha256) - WHERE p.local_path IS NOT NULL + WHERE p.local_path IS NOT NULL AND p.is_primary_gallery=1 ORDER BY p.listing_id, p.ordinal """ ).fetchall() diff --git a/reports/mangueiral_top10/query.sql b/reports/mangueiral_top15/query.sql similarity index 92% rename from reports/mangueiral_top10/query.sql rename to reports/mangueiral_top15/query.sql index 1113b86..f8d3b18 100644 --- a/reports/mangueiral_top10/query.sql +++ b/reports/mangueiral_top15/query.sql @@ -21,11 +21,12 @@ WHERE instr(s.search_url, '/jardins-mangueiral/') > 0 ORDER BY l.price_brl, l.listing_id LIMIT 150; --- Cardinalidade de fotos por anúncio. A contagem inclui material genérico do portal. +-- Cardinalidade de fotos da galeria primária por anúncio; recomendações legadas são excluídas. SELECT p.listing_id, COUNT(*) AS photo_count FROM photos AS p JOIN listing_searches AS s USING (listing_id) WHERE instr(s.search_url, '/jardins-mangueiral/') > 0 + AND p.is_primary_gallery = 1 AND EXISTS ( SELECT 1 FROM listings AS l WHERE l.listing_id = p.listing_id AND l.inactive_at IS NULL diff --git a/reports/mangueiral_top15/results.csv b/reports/mangueiral_top15/results.csv new file mode 100644 index 0000000..b8403e0 --- /dev/null +++ b/reports/mangueiral_top15/results.csv @@ -0,0 +1,16 @@ +rank,representative_listing_id,user_score,assessment_basis,probable_duplicate_ids,qc,price_brl,area_m2,bedrooms,suites,parking_spaces,original_three_bedroom_status,visual_status,decision +1,1279892,4,user_feedback,,10,595000,68,3,1,1,probable_pending_documents,no_sale_marker,strong_candidate +2,1319996,4,user_feedback,,14,649000,68,3,1,2,probable_pending_documents,no_sale_marker,strong_candidate +3,1377683,,inferred_from_full_database_review,,11,585000,69,3,1,2,probable_pending_documents,no_sale_marker,user_visual_review_then_documents +4,1371718,,inferred_from_full_database_review,,14,650000,100,3,1,2,probable_pending_documents,no_sale_marker,user_visual_review_then_documents +5,1140317,,inferred_from_full_database_review,,5,599000,80,3,1,1,probable_pending_documents,no_sale_marker,user_visual_review_then_documents +6,1324014,3,user_feedback,,12,649000,68,3,1,,probable_pending_documents,no_sale_marker,visit +7,1290502,3,user_feedback,,11,600000,75,3,1,2,probable_pending_documents,no_sale_marker,validate_original_plan_cover_and_price_then_visit +8,1401074,,inferred_from_full_database_review,,13,720000,110,3,1,2,probable_pending_documents,no_sale_marker,user_review_then_documents_and_heat_test +9,1345745,,inferred_from_full_database_review,,12,670000,68,3,1,2,probable_pending_documents,no_sale_marker,user_review_and_heat_test +10,1333569,3,user_feedback,,6,650000,90,3,1,2,probable_pending_documents,no_sale_marker,test_glass_enclosure_heat_then_visit +11,1357311,,inferred_from_full_database_review,,1,699900,68,3,1,2,probable_pending_documents,no_sale_marker,inspect_possible_water_damage +12,1357912,3,user_feedback,,3,580000,110,3,1,2,probable_pending_documents,no_sale_marker,validate_intervention_cost_before_visit +13,1259149,,inferred_from_full_database_review,,11,590000,115,3,1,,probable_pending_documents,no_sale_marker,user_review_and_area_validation +14,348115,,inferred_from_full_database_review,,14,550000,120,3,1,2,probable_pending_documents,no_sale_marker,user_review_and_condition_validation +15,1346118,,inferred_from_full_database_review,,14,550000,110,3,1,2,probable_pending_documents,no_sale_marker,user_review_and_renovation_scope diff --git a/requirements-dfimoveis.txt b/requirements-dfimoveis.txt index 5495687..7f78d3e 100644 --- a/requirements-dfimoveis.txt +++ b/requirements-dfimoveis.txt @@ -2,7 +2,7 @@ httpx[http2]>=0.27,<1 beautifulsoup4>=4.12,<5 lxml>=5,<7 # Used by the report photo-similarity screening scripts. -Pillow>=10,<13 +pillow>=10,<13 # Default browser automation (uses the locally installed Microsoft Edge): playwright>=1.49,<2 cloudscraper>=1.2,<2 diff --git a/run_scraper.ps1 b/run_scraper.ps1 new file mode 100644 index 0000000..9857451 --- /dev/null +++ b/run_scraper.ps1 @@ -0,0 +1,5 @@ +Set-Location E:\forge\python\house-quest + +& "C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir="E:\forge\python\house-quest\dfimoveis_data\browser-profile" + +.\.venv-scraper\Scripts\python.exe .\dfimoveis_scraper.py --search-file .\search_list.txt --output .\dfimoveis_data --attach-chrome diff --git a/scripts/migrate_dfimoveis_schema_v2.py b/scripts/migrate_dfimoveis_schema_v2.py new file mode 100644 index 0000000..7b5737a --- /dev/null +++ b/scripts/migrate_dfimoveis_schema_v2.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python3 +"""Add schema-v2 quality metadata without deleting or rewriting source evidence.""" +from __future__ import annotations + +import argparse +import hashlib +import json +import re +import sqlite3 +import sys +from pathlib import Path +from urllib.parse import urlparse + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) + +from dfimoveis_scraper import ( + Database, + normalize_creci, + normalize_description_for_hash, + normalize_listing_address, + now_utc, +) + + +VISUALLY_SOLD = { + "1263868", "1301400", "1346017", "1346231", "1349519", + "1351729", "1352943", "1356197", "1362968", "1366801", +} + + +def stable_hash(row: sqlite3.Row) -> str: + payload = { + "url": row["url"], + "title": row["title"], + "description": normalize_description_for_hash(row["description"]), + "transaction_type": row["transaction_type"], + "property_type": row["property_type"], + "price_brl": row["price_brl"], + "condominium_brl": row["condominium_brl"], + "iptu_brl": row["iptu_brl"], + "area_m2": row["area_m2"], + "bedrooms": row["bedrooms"], + "suites": row["suites"], + "parking_spaces": row["parking_spaces"], + "address_normalized": normalize_listing_address(row["url"], row["address"]), + "neighborhood_normalized": "Jardins Mangueiral" if "jardins-mangueiral" in row["url"] else None, + "advertiser_name": row["advertiser_name"], + "creci_normalized": normalize_creci(row["creci"]), + "latitude": row["latitude"], + "longitude": row["longitude"], + "published_at": row["published_at"], + } + return hashlib.sha256(json.dumps(payload, sort_keys=True, ensure_ascii=False).encode()).hexdigest() + + +def upsert_issue(conn: sqlite3.Connection, listing_id: str, code: str, severity: str, evidence: str) -> None: + ts = now_utc() + conn.execute( + """INSERT INTO data_quality_issues(listing_id,issue_code,severity,evidence,first_seen_at,last_seen_at) + VALUES(?,?,?,?,?,?) ON CONFLICT(listing_id,issue_code) DO UPDATE SET + severity=excluded.severity,evidence=excluded.evidence,last_seen_at=excluded.last_seen_at""", + (listing_id, code, severity, evidence, ts, ts), + ) + + +def migrate(database: Path) -> None: + # Database initialization performs only additive CREATE/ALTER operations. + bootstrap = Database(database) + bootstrap.close() + conn = sqlite3.connect(database) + conn.row_factory = sqlite3.Row + conn.execute("PRAGMA foreign_keys=ON") + with conn: + for row in conn.execute("SELECT * FROM listings"): + normalized_address = normalize_listing_address(row["url"], row["address"]) + normalized_neighborhood = "Jardins Mangueiral" if "jardins-mangueiral" in row["url"] else None + normalized_creci = normalize_creci(row["creci"]) + conn.execute( + """UPDATE listings SET address_normalized=?,neighborhood_normalized=?, + creci_normalized=?,raw_content_hash=COALESCE(raw_content_hash,content_hash), + stable_content_hash=? WHERE listing_id=?""", + (normalized_address, normalized_neighborhood, normalized_creci, stable_hash(row), row["listing_id"]), + ) + description = (row["description"] or "").lower() + if row["price_brl"] and row["price_brl"] > 20_000_000: + upsert_issue(conn, row["listing_id"], "implausible_price", "high", str(row["price_brl"])) + if row["area_m2"] and row["area_m2"] < 10: + upsert_issue(conn, row["listing_id"], "implausible_area", "high", str(row["area_m2"])) + if "procuro casa para comprar" in description: + upsert_issue(conn, row["listing_id"], "source_mismatch_buyer_request", "high", "description declares a purchase request") + if "quarto adaptado" in description or "escritório adaptado" in description: + upsert_issue(conn, row["listing_id"], "adapted_room", "medium", "description mentions an adapted room") + + mismatch_counts: dict[str, int] = {} + for photo in conn.execute("SELECT listing_id,source_url FROM photos"): + owner = re.search(r"/fotos/(\d+)/", urlparse(photo["source_url"]).path, re.I) + is_primary = bool(owner and owner.group(1) == photo["listing_id"]) + status = "unreviewed" if is_primary else ("excluded_recommendation" if owner else "excluded_site_asset") + conn.execute( + "UPDATE photos SET discovery_source=?,is_primary_gallery=?,review_status=? WHERE listing_id=? AND source_url=?", + ("listing_id_url" if is_primary else "legacy_page_wide_scan", int(is_primary), status, photo["listing_id"], photo["source_url"]), + ) + if owner and not is_primary: + mismatch_counts[photo["listing_id"]] = mismatch_counts.get(photo["listing_id"], 0) + 1 + for listing_id, count in mismatch_counts.items(): + upsert_issue(conn, listing_id, "photo_owner_mismatch", "high", f"{count} legacy photos do not belong to this listing id") + + # Confirmed manual exceptions whose structured description is truncated. + manual_issues = [ + ("1369473", "source_mismatch_buyer_request", "high", "full captured page declares PROCURO CASA PARA COMPRAR"), + ("1348449", "adapted_room", "medium", "full description declares an adapted office/room"), + ("1374012", "adapted_room", "medium", "full description declares an adapted bedroom"), + ("1026522", "bedroom_count_conflict", "medium", "structured three bedrooms conflicts with four bedrooms in description"), + ] + for listing_id, code, severity, evidence in manual_issues: + if conn.execute("SELECT 1 FROM listings WHERE listing_id=?", (listing_id,)).fetchone(): + upsert_issue(conn, listing_id, code, severity, evidence) + + for listing_id in VISUALLY_SOLD: + exists = conn.execute( + "SELECT 1 FROM availability_observations WHERE listing_id=? AND classification='sold_visual' AND source='manual_first_photo_review'", + (listing_id,), + ).fetchone() + if not exists and conn.execute("SELECT 1 FROM listings WHERE listing_id=?", (listing_id,)).fetchone(): + active = conn.execute("SELECT inactive_at IS NULL FROM listings WHERE listing_id=?", (listing_id,)).fetchone()[0] + conn.execute( + """INSERT INTO availability_observations + (listing_id,observed_at,portal_active,classification,source,evidence) + VALUES(?,?,?,?,?,?)""", + (listing_id, now_utc(), active, "sold_visual", "manual_first_photo_review", "VENDIDO or equivalent marker on first photo"), + ) + + latest_run = conn.execute("SELECT * FROM crawl_runs ORDER BY id DESC LIMIT 1").fetchone() + if latest_run and latest_run["searches_json"] == "[]" and latest_run["finished_at"]: + searches = [ + row[0] for row in conn.execute( + """SELECT DISTINCT search_url FROM listing_searches + WHERE last_seen_at BETWEEN ? AND ? ORDER BY search_url""", + (latest_run["started_at"], latest_run["finished_at"]), + ) + ] + stats = json.loads(latest_run["stats_json"] or "{}") + conn.execute( + """UPDATE crawl_runs SET searches_json=?,config_json=?,scope_complete=? WHERE id=?""", + (json.dumps(searches, ensure_ascii=False), json.dumps({"legacy_backfill": True}), + int(latest_run["status"] == "ok" and stats.get("details_failed", 0) == 0), latest_run["id"]), + ) + result = conn.execute("PRAGMA quick_check").fetchone()[0] + counts = { + "listings": conn.execute("SELECT count(*) FROM listings").fetchone()[0], + "history": conn.execute("SELECT count(*) FROM listing_history").fetchone()[0], + "photos": conn.execute("SELECT count(*) FROM photos").fetchone()[0], + "non_gallery_photos": conn.execute("SELECT count(*) FROM photos WHERE is_primary_gallery=0").fetchone()[0], + "quality_issues": conn.execute("SELECT count(*) FROM data_quality_issues").fetchone()[0], + "availability_observations": conn.execute("SELECT count(*) FROM availability_observations").fetchone()[0], + } + conn.close() + print(json.dumps({"quick_check": result, **counts}, ensure_ascii=False, indent=2)) + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--database", default="dfimoveis_data/dfimoveis.sqlite3") + args = parser.parse_args() + migrate(Path(args.database).resolve()) + + +if __name__ == "__main__": + main() diff --git a/search_list.txt b/search_list.txt index e005498..ef036e5 100644 --- a/search_list.txt +++ b/search_list.txt @@ -1,3 +1,2 @@ # One complete DFImoveis search URL per line -https://www.dfimoveis.com.br/venda/df/brasilia/jardins-mangueiral/casa/3,4-quartos -https://www.dfimoveis.com.br/venda/df/cruzeiro/novo/apartamento/3-quartos \ No newline at end of file +https://www.dfimoveis.com.br/venda/df/brasilia/jardins-mangueiral/casa/3,4-quartos \ No newline at end of file diff --git a/tests/test_dfimoveis_schema_v2.py b/tests/test_dfimoveis_schema_v2.py new file mode 100644 index 0000000..9435484 --- /dev/null +++ b/tests/test_dfimoveis_schema_v2.py @@ -0,0 +1,64 @@ +import tempfile +import unittest +from pathlib import Path + +from dfimoveis_scraper import Database, Parser, normalize_creci, normalize_listing_address + + +class SchemaV2Tests(unittest.TestCase): + def test_normalization(self): + self.assertEqual(normalize_creci("26.903 Ver mais qualquer texto"), "26903") + self.assertEqual( + normalize_listing_address( + "https://www.dfimoveis.com.br/imovel/casa-venda-jardins-mangueiral-qc-13-rua-g-123", + "texto contaminado " * 100, + ), + "Jardins Mangueiral - QC 13 - Rua G", + ) + + def test_parser_rejects_recommendation_photos(self): + page = """ + + + + + """ + data, photos = Parser.detail( + "https://www.dfimoveis.com.br/imovel/casa-3-quartos-venda-jardins-mangueiral-qc-13-1401074", + page, + ) + self.assertEqual(photos, ["https://img.dfimoveis.com.br/fotos/1401074/a.webp"]) + self.assertEqual(data["creci_normalized"], None) + self.assertEqual(data["address_normalized"], "Jardins Mangueiral - QC 13") + + def test_schema_migration_is_additive(self): + with tempfile.TemporaryDirectory() as tmp: + path = Path(tmp) / "test.sqlite3" + db = Database(path) + columns = {row[1] for row in db.conn.execute("PRAGMA table_info(listings)")} + self.assertIn("stable_content_hash", columns) + self.assertIn("creci_normalized", columns) + self.assertTrue(db.conn.execute("SELECT 1 FROM sqlite_master WHERE name='data_quality_issues'").fetchone()) + db.close() + + def test_raw_ui_noise_does_not_create_material_change(self): + page = '' + url = "https://www.dfimoveis.com.br/imovel/casa-venda-jardins-mangueiral-qc-13-123" + data, _ = Parser.detail(url, page) + with tempfile.TemporaryDirectory() as tmp: + db = Database(Path(tmp) / "test.sqlite3") + run_id = db.start_run([url], {"test": True}) + self.assertTrue(db.upsert_listing(data, url, run_id)) + data["creci"] = "texto instável da interface" + data["address"] = "outro bloco contaminado" + data["raw_content_hash"] = "different-raw-hash" + self.assertFalse(db.upsert_listing(data, url, run_id)) + self.assertEqual(db.conn.execute("SELECT count(*) FROM listing_history").fetchone()[0], 1) + self.assertEqual(db.conn.execute("SELECT count(*) FROM listing_change_events").fetchone()[0], 1) + self.assertEqual(db.mark_inactive(url, set(), "9999-01-01T00:00:00+00:00"), 1) + self.assertEqual(db.mark_inactive(url, set(), "9999-01-01T00:00:00+00:00"), 0) + db.close() + + +if __name__ == "__main__": + unittest.main()