the holy quest for the holy home
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

15 KiB

Avaliação inicial 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

1. Pergunta respondida

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?

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.

2. Segurança e método

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.

Identificação do arquivo analisado:

  • 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;
  • PRAGMA quick_check: ok;
  • PRAGMA foreign_key_check: nenhuma violação.

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 esquema completo e as decisões de interpretação estão em docs/ACTUAL_SCHEMA.md.

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
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.

Imóvel físico

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.

Logo, as unidades válidas hoje são:

  • 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.

5. Qualidade dos dados

5.1 Integridade estrutural

Pontos positivos:

  • 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.

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:

  • 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.

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.

5.5 Fotos e arquivos brutos

Das 5.386 linhas em photos:

  • 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.

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.

6. Duplicidades e imóveis físicos prováveis

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 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.

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.

Uma futura camada derivada deve combinar, com confiança e revisão manual:

  • 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.

7. Possíveis quebras de coleta

  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.

8. Limitações para qualquer conclusão imobiliária

  • 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.

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.

9. Próximas ações recomendadas

Antes da análise dos imóveis:

  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.

10. Consultas de 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.

-- Objetos do esquema
SELECT type, name, tbl_name, sql
FROM sqlite_master
ORDER BY type, name;

-- 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;

-- 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;

11. Implicação para a decisão de compra

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.