İçeriğe Atla
Mustafa Erbay
Kariyer · 8 dk okuma · görüntülenme Read in English
100%

İlan Fiyatı ile Gerçek Kira Aynı Şey Değil: Veri Toplamanın Gerçeği

Web'den çekilen ilan verilerinin neden gerçek piyasayı yansıtmadığını ve veri temizleme süreçlerindeki teknik zorlukları kendi tecrübelerimle anlatıyorum.

Veri madenciliği ve emlak piyasası analizini temsil eden bir görsel

Mart başında, kira piyasasındaki saçmalığı anlamak için kendi VPS’ime küçük bir scraper script’i attım. Amacım hesapciyiz.com için daha gerçekçi bir kira çarpanı motoru kurmaktı ama ilk 48 saatin sonunda elimdeki verinin aslında koca bir yalan olduğunu fark ettim.

Ekranda gördüğüm 45.000 TL’lik Beşiktaş ilanı ile o evin kontratına atılan imza arasında bazen uçurumlar oluyor. Veri toplarken sadece selector yazıp json basmak yetmiyor; sahadaki “pazarlık marjını” ve “fake ilan” gürültüsünü temizlemek asıl işin kendisiymiş.

Veri Setindeki Gürültü: “Sahibinden” Değil “İsteyen” Fiyatı

Topladığım ilk 10 bin satırlık veriyi SQLite üzerine bastığımda garip bir şey fark ettim: Bazı ilanlar 3 aydır yayında ve fiyatı sürekli %5 artıyor. Kimse tutmuyor ama fiyat artıyor. Bu, aslında piyasanın fiyatı değil, mülk sahibinin “keşke bu fiyata gitse” dediği hayal dünyası.

Kendi VPS’imde çalışan 13 container’dan biri olan bu scraper, başlangıçta sshd’yi bile cevap veremez hale getirdi. Çünkü 28 Nisan’da yaşadığım o meşhur disk dolması vakasındaki gibi, logları tmpfs yerine doğrudan /var/log altına kontrolsüzce basmışım. Veri büyüdükçe, temizlenmemiş veri setinin sistem kaynaklarını nasıl sömürdüğünü bir kez daha gördüm.

İlan fiyatlarını “gerçek” kabul edip bir model kurmaya kalktığımda, sistem bana İstanbul’da kiraların son 2 ayda %15 düştüğünü söyledi. Ama sokağa çıktığımda durum tam tersiydi. Meğer emlakçılar, arama sonuçlarında üstte kalmak için eski ilanları silip 2.000 TL daha ucuza “yeni” ilan giriyor, sonra telefonda “o tutuldu ama şuna bak” diyorlarmış.

Pipeline’da Veri Temizleme: SQLite ve Heuristic Filtreler

Bu kirliliği çözmek için Node.js tarafında basit bir preflight resource guard mekanizması kurdum. Her gelen veri satırı, daha önce gördüğüm “spam pattern”lerine uyuyor mu diye kontrol ediliyor. Eğer bir ilan 30 günden uzun süredir yayındaysa ve fiyatı 3 kereden fazla değişmişse, onu “piyasa belirleyici” değil “gürültü” kategorisine alıyorum.

SQLite üzerinde bu sorguları koştururken index’lerin canına okuduğum bir an oldu. VACUUM komutunu çalıştırmayı unuttuğum için 2 GB’lık veritabanı diskte 5 GB yer kaplıyordu.

-- Gürültülü verileri temizlemek için kullandığım basit bir mantık
DELETE FROM listings 
WHERE updated_at < date('now', '-30 days') 
AND price_change_count > 3;

-- Gerçekçi fiyat tahmini için %15 'pazarlık/fake' payı düşüyorum
UPDATE listings 
SET estimated_real_price = price * 0.85 
WHERE source = 'web_scraper';

Bu temizleme işlemi sonrası elimde kalan veri, “ilan fiyatı” değil, “olası işlem fiyatı” haline geldi. Kendi VPS’imdeki kaynakları korumak için bu işlemleri gece 03:00’te, GitHub Actions runner’larını meşgul etmeden, systemd timer’ları ile yapıyorum.

VPS Üzerinde Veri Operasyonu Yapmanın Acı Gerçekleri

Eğer benim gibi her şeyi bir kutuya (box) sığdırmaya çalışıyorsanız, disk yangını kaçınılmazdır. Bir ara Docker build cache’i 33 GB’a ulaşmış, yanına bir de 23 GB’lık unused image eklenmişti. Sunucu %100 disk doluluğuna ulaştığında, scraper’ın çektiği veriler null olarak kaydedilmeye başlandı.

O gün öğrendim ki; veri toplamak sadece kod yazmak değil, o verinin yaşayacağı disk alanını ve swap alanını da yönetmektir. 7.6 GB sistem belleğinde Astro build’i ayağa kalkmaya çalışırken, bir yandan SQLite’a toplu INSERT yapmak tam bir intihar girişimi.

SorunSemptomÇözüm
Disk DoluluğuVerilerin null gelmesidocker system prune -af
OOM-KilledContainer’ların rastgele çökmesiSwap file artırımı + polling wait
SSH Timeoutsshd paket kabul edememesiCPU limit (cgroups)

Kendi projelerimde (örneğin spamkalkani.com veya islistesi.com) bu tarz veri anomali durumlarını artık auto-fix pattern’leri ile çözüyorum. Eğer bir işlem 10 saniyeden uzun sürerse, pipeline otomatik olarak kaynak kullanımını kısıyor ve bana bir dedup-alert fırlatıyor.

Pipeline Reliability: Neden Otomasyon Şart?

Veri toplama sürecinde en büyük düşmanınız “değişen web yapıları” değil, “dolup taşan diskler ve cache’ler”dir. GitHub Actions üzerinde kendi runner’ımı (self-hosted) koştururken, _work/_temp altındaki dizinlerin silinmemesi yüzünden kaç kere pipeline’ın patladığını hatırlamıyorum bile.

Cloudflare tarafında Astro’nun max-age=0 döndürmesi yüzünden tüm trafiğin doğrudan VPS’e gelmesi de ayrı bir dertti. Nginx tarafında bu header’ları override ederek sunucunun üzerindeki yükü biraz olsun hafifletebildim. Aksi halde, veri çekerken aynı zamanda siteye gelen ziyaretçilere “502 Bad Gateway” izletmek zorunda kalıyordum.

Sonuç olarak, internetten çektiğiniz her satır veri “saf gerçek” değildir. O veri, bir insanın (genelde bir emlakçının veya satıcının) manipülasyonuna uğramış bir dijital izdir. Gerçek veriye ulaşmak için o izi kazımak, temizlemek ve en önemlisi kendi altyapınızı bu yük altında ezilmeyecek şekilde optimize etmek zorundasınız.

Şu sıralar bu temizlenmiş verilerle hesapciyiz.com’un backend’ini besliyorum. Bir sonraki yazıda, bu kadar veriyi Cloudflare R2 üzerinde nasıl daha ucuza depolarım ondan bahsedeceğim. Senin de benzer bir scraper tecrüben veya “disk doldu, site çöktü” anın varsa yorumlarda (ya da mailde) buluşalım.

Paylaş:

Bu yazı faydalı oldu mu?

Yükleniyor...

Bu yazı nasıldı?

Sıkça Sorulanlar

Bu makale ile ilgili okurların sorduğu yaygın sorular.

Scraper'ı ilk kez kurarken hangi araçları ve ortamı tercih etmeliyim?
Ben VPS üzerinde bir Node.js tabanlı scraper kullandım; `puppeteer` ve `cheerio` kombinasyonu işimi gördü. Öncelikle Ubuntu 22.04 LTS bir sunucu kiraladım, Docker ile izole ortamlar oluşturdum ve her bir scraper konteynerini ayrı bir image olarak paketledim. `git` ile kodu yönetip, `pm2` ile süreçleri izlemek, log rotasyonu için `logrotate` ayarlamak kritik oldu. Ayrıca `sqlite` yerine veri geçici olarak `CSV` tutup, sonrasında temizlik adımında `pandas` ile işlemek, bellek tüketimini kontrol altında tutar.
Veri toplarken karşılaştığım sahte ilanları nasıl ayıklamalıyım?
Ben ilk 10 bin satırda fiyatların %5 artış gösterdiği ilanları fark ettiğimde, zaman damgası ve fiyat değişim oranı üzerinden bir filtre geliştirdim. `listing_age > 90 days` ve `price_change_rate > 0.04` gibi kurallar koyarak şüpheli satırları ayırdım. Ayrıca ilan açıklamasındaki “acil satılır”, “fırsat” gibi anahtar kelimeleri bir kara listeye ekleyerek metin analizi yaptım. Bu iki adım, sahte ve spekülatif ilanları %70 oranında temizledi, fakat her zaman manuel bir kontrolle doğrulama yapmak gerekir.
Scraper çalışırken OOM hatası alırsam ne yapmalıyım?
Ben 8 GB RAM'li bir sunucuda 2.5 GB RAM tüketen bir Astro build'iyle aynı anda veri işleme yaptığımda OOM hatası aldım. İlk adım, `cgroup` ile konteyner limitlerini belirlemek; örneğin her scraper konteynerine 512 MB RAM sınırı koydum. İkinci olarak, `swap` alanını %20 artırdım ve `nice`/`ionice` ile süreç önceliklerini düşürdüm. Log dosyalarını `tmpfs` yerine ayrı bir disk bölümü yönlendirmek de disk dolmasını engelledi. Bu ayarlamalarla CPU ve bellek kullanımını dengeleyerek sistem çökmesini önledim.
Topladığım verinin gerçek piyasa fiyatını yansıtması için hangi temizlik adımları şart?
Ben veriyi SQLite'a aktardıktan sonra öncelikle tarihsel fiyat trendlerini analiz ettim; aynı ilan içinde fiyat artışı %5’ten fazla ise onu “güncellenen” olarak işaretledim ve ortalama fiyatı dışarıda bıraktım. Ardından, bölge, oda sayısı ve metrekare başına fiyat gibi faktörleri normalize ettim ve outlier'ları Z‑skoru > 3 olan satırları çıkardım. Son olarak, manuel bir kontrol listesi hazırlayarak yüksek fiyatlı 20 ilanı gözden geçirdim; bu adımlar veri setimin %85’ini güvenilir kıldı ve modelim gerçek piyasa hareketlerini daha iyi yakaladı.
ME

Mustafa Erbay

Sistem Mimarisi · Network Uzmanı · Altyapı, Güvenlik ve Yazılım

2006'dan bu yana sistem mimarisi, network, sunucu altyapıları, büyük yapıların kurulumu, yazılım ve sistem güvenliği ekseninde çalışıyorum. Bu blogda sahada karşılığı olan teknik deneyimlerimi paylaşıyorum.

Kişisel Notlar

Bu notlar sadece sizde saklanır. Tarayıcınızda yerel olarak tutulur.

Hazır 0 karakter

Yorumlar

Sunucu Taraflı AI Moderasyon

Yorumlar sunucuda yapay zeka ile denetlenir ve kalıcı olarak saklanır.

?
0/2000

Sunucu taraflı AI denetim

✉️ Ücretsiz · Spam yok · İstediğin an çık

Haftalık özet — AI değil, bizzat ben seçiyorum

Haftada bir mail: o haftanın en önemli yazısı, perde arkası notları, ve "bu hafta gerçekten kullandığım araç" bölümü. Az gürültü, çok sinyal.

  • 📌
    Haftanın en iyisi Sadece okumaya değer tek yazı
  • 🔧
    Alet çantası Bu hafta kullandığım araçlar
  • 🧠
    Perde arkası Blog'a girmeyen notlar

Spam yapmıyoruz. İstediğiniz zaman ayrılabilirsiniz. · Sadece Umami (self-hosted, Google yok) ile takip.

Okuma İstatistikleriniz

0

Yazı Okundu

0dk

Okuma Süresi

0

Gün Serisi

-

Favori Kategori

İlgili Yazılar