Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce bilgisayarınızda Node.js'in güncel bir sürümünün (LTS sürümü önerilir) yüklü olması gerekir. Ayrıca, HTTP isteklerini yönetmek için axios kütüphanesini ve HTML ayrıştırmak için cheerio kütüphanesini kullanacağız.
Terminalinizde yeni bir klasör oluşturun ve gerekli paketleri yüklemek için aşağıdaki komutları çalıştırın:
mkdir web-kazima-projesi
cd web-kazima-projesi
npm init -y
npm install axios cheerio
Bu komutlar, projenizin temelini atar ve gerekli bağımlılıkları package.json dosyanıza ekler. axios, hedef web sitesine GET isteği göndererek ham HTML içeriğini almamızı sağlar; cheerio ise bu ham veriyi işlenebilir bir ağaç yapısına dönüştürür.
Adım Adım Web Kazıma: İlk HTTP İsteği
İlk adım, hedeflediğimiz web sayfasının HTML içeriğini çekmektir. Axios kullanarak bir URL'ye istek gönderiyoruz. Aşağıdaki kod, bir web sayfasından veriyi nasıl alacağınızı gösterir:
const axios = require('axios');
async function veriGetir(url) {
try {
const { data } = await axios.get(url);
console.log("Sayfa içeriği başarıyla alındı.");
return data;
} catch (error) {
console.error("İstek sırasında hata oluştu:", error.message);
}
}
veriGetir('https://example.com');
Burada async/await yapısını kullanarak işlemin asenkron gerçekleşmesini sağlıyoruz. Bu, Node.js'in bloklanmadan diğer işlemlere devam etmesine olanak tanır. try-catch bloğu ise ağ hatalarını yönetmek için kritik öneme sahiptir.
Cheerio ile HTML Ayrıştırma ve Veri Seçme
HTML içeriği elimize ulaştıktan sonra, Cheerio ile bu içeriği jQuery benzeri bir nesneye dönüştürüyoruz. Bu sayede CSS seçicilerini (selectors) kullanarak istediğimiz veriye ulaşabiliriz.
const cheerio = require('cheerio');
const html = 'Merhaba Dünya
';
const $ = cheerio.load(html);
const baslikMetni = $('.baslik').text();
console.log(baslikMetni);
cheerio.load() fonksiyonu, HTML dizisini alır ve $ değişkenine atar. Artık $('.baslik') gibi ifadelerle sayfa içindeki öğeleri seçebilir, .text() veya .attr() gibi metotlarla içeriklerini çekebilirsiniz.
Dinamik Veri Çıkarma ve Liste İşleme
Gerçek dünya senaryolarında genellikle bir liste içindeki öğeleri çekmeniz gerekir. Örneğin, bir haber sitesindeki manşetleri veya bir e-ticaret sitesindeki ürün isimlerini listeleyelim.
const $ = cheerio.load(htmlIcerigi);
const liste = [];
$('.haber-basligi').each((index, element) => {
const baslik = $(element).text().trim();
liste.push(baslik);
});
console.log(liste);
.each() metodu, eşleşen tüm öğeler üzerinde döngü kurar. .trim() metodu ise metinlerin başındaki ve sonundaki gereksiz boşlukları temizler. Bu, veri temizliği için standart bir uygulamadır.
Web Kazıma Yöntemlerinin Karşılaştırılması
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Cheerio + Axios | Çok hızlı, hafif, düşük kaynak tüketimi | JavaScript ile render edilen sitelerde çalışmaz |
| Puppeteer / Playwright | Dinamik içerikleri işler, tam tarayıcı simülasyonu | Ağır, yavaş, yüksek RAM tüketimi |
Güvenlik ve Etik Uyarılar
Web kazıma işlemi yaparken hedef sitenin robots.txt dosyasını mutlaka kontrol edin. Aşırı hızlı ve yoğun istekler, hedef sunucunun çökmesine veya IP adresinizin engellenmesine neden olabilir. Kişisel verilerin korunması kanunlarına (KVKK) uyun ve telif hakkı içeren içerikleri izinsiz paylaşmayın.
Güvenlik açısından, kazıdığınız verileri veritabanına kaydederken mutlaka "sanitizasyon" (temizleme) yapın. Kullanıcıdan gelen veriyi veya dış kaynaktan gelen veriyi doğrudan SQL sorgularına sokmak, SQL Injection açıklarına davetiye çıkarır.
Hata Ayıklama ve Debug İpuçları
Kodunuz çalışmadığında veya boş veri döndüğünde şu adımları izleyin:
- İsteğin başarılı olup olmadığını kontrol edin (Status Code 200).
- CSS seçicilerinizin doğruluğunu tarayıcı konsolundan (F12) test edin.
- Hedef sitenin "User-Agent" doğrulaması yapıp yapmadığını kontrol edin.
// User-Agent ekleyerek engellenmeyi önleme
const { data } = await axios.get(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
}
});
Sıkça Sorulan Sorular
Cheerio neden Puppeteer'dan daha hızlıdır?
Cheerio sadece HTML ayrıştırır ve DOM oluşturmaz. Puppeteer ise gerçek bir tarayıcı (Chromium) başlattığı için çok daha fazla bellek ve işlemci gücü gerektirir.
Web sitesi JavaScript ile içerik yüklüyorsa ne yapmalıyım?
Cheerio sadece statik HTML'i okur. Eğer içerik JS ile yükleniyorsa, Puppeteer veya Playwright kullanmanız gerekir.
IP engellemesini nasıl aşarım?
İstekler arasına setTimeout ile gecikmeler koyarak (rate limiting) ve farklı User-Agent değerleri kullanarak engellenme riskini azaltabilirsiniz.
Cheerio ile form gönderilebilir mi?
Hayır, Cheerio bir tarayıcı değildir. Sadece HTML okuma ve ayrıştırma kütüphanesidir. Form işlemleri için Axios ile POST isteği göndermelisiniz.
Verileri nasıl CSV olarak kaydederim?
Node.js'in dahili fs (File System) modülünü kullanarak verileri bir dosyaya yazdırabilirsiniz.
Gerçek Dünya Senaryosu: E-Ticaret Fiyat Takip Botu Geliştirme
Cheerio'nun gücünü tam anlamıyla görmek için, bir e-ticaret sitesinden ürün ismi ve fiyat bilgilerini anlık olarak çeken bir otomasyon senaryosunu inceleyelim. Bu senaryoda, belirli bir ürünün fiyatı düştüğünde konsola uyarı veren basit bir yapı kuracağız.
Fiyat Takip Mantığı
Web siteleri genellikle fiyatları belirli HTML sınıfları (class) içerisinde tutar. Aşağıdaki kod örneği, bir ürün sayfasındaki fiyat etiketini seçip sayısal bir değere dönüştürerek mantıksal bir karşılaştırma yapar.
const axios = require('axios');
const cheerio = require('cheerio');
async function fiyatTakipEt(url) {
const { data } = await axios.get(url);
const $ = cheerio.load(data);
const urunAdi = $('.product-title').text().trim();
const fiyatStr = $('.price-tag').text().replace('TL', '').trim();
const fiyat = parseFloat(fiyatStr);
const hedefFiyat = 500;
if (fiyat < hedefFiyat) {
console.log(`Fırsat! ${urunAdi} şu an ${fiyat} TL. Hemen satın al!`);
} else {
console.log(`${urunAdi} fiyatı henüz hedeflenen seviyeye düşmedi: ${fiyat} TL`);
}
}
fiyatTakipEt('https://ornek-site.com/urun-detay');
Web Kazıma Projelerinde Performans Optimizasyonu
Büyük ölçekli veri çekme işlemlerinde, Node.js'in asenkron yapısını doğru kullanmak hayati önem taşır. Özellikle yüzlerce sayfayı aynı anda taramanız gerektiğinde, sistem kaynaklarını tüketmemek için "Concurrency" (eşzamanlılık) yönetimi yapmalısınız.
Eşzamanlı İstek Yönetimi
Tüm istekleri aynı anda Promise.all ile göndermek, hedef sunucunun sizi engellemesine veya yerel ağınızın tıkanmasına neden olabilir. Bunun yerine, istekleri gruplandırarak (batch) işlemek daha güvenlidir.
const pLimit = require('p-limit'); // npm install p-limit
const limit = pLimit(5); // Aynı anda en fazla 5 istek
const urlListesi = ['url1', 'url2', 'url3', 'url4', 'url5', 'url6'];
const islemler = urlListesi.map(url => {
return limit(() => axios.get(url).then(res => {
const $ = cheerio.load(res.data);
return $('h1').text();
}));
});
Promise.all(islemler).then(sonuclar => {
console.log('Tüm sayfalar işlendi:', sonuclar);
});
Bellek Yönetimi İpuçları
- DOM Temizliği: Cheerio ile işiniz bittikten sonra büyük HTML değişkenlerini null yaparak garbage collector'ın tetiklenmesini sağlayın.
- Stream Kullanımı: Çok büyük HTML dosyalarıyla çalışıyorsanız, dosyayı belleğe almak yerine
fs.createReadStreamyöntemini tercih edin. - Gereksiz Veri Seçimi: Sadece ihtiyacınız olan elementleri seçin; tüm sayfayı DOM ağacına yüklemek yerine, gerekirse regex ile ön filtreleme yapın.
Profesyonel Not: Web kazıma projelerinde "User-Agent" başlığını mutlaka değiştirin. Standart Axios veya Node.js başlıkları, sunucular tarafından "bot" olarak kolayca tespit edilir.
const axios = require('axios');
const config = {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
}
};
axios.get('https://hedef-site.com', config);
Sonuç
Node.js ve Cheerio ikilisi, statik web sayfalarından veri çekmek için en verimli çözümdür. Öğrendiğiniz bu yöntemlerle, web sitelerinden veri toplama süreçlerini otomatize edebilir ve kendi veri setlerinizi oluşturabilirsiniz. Bir sonraki adım olarak, topladığınız verileri MongoDB veya PostgreSQL gibi bir veritabanına kaydetmeyi deneyebilir, ardından bu verileri bir API üzerinden sunmayı öğrenebilirsiniz.
Yasal Sorumluluk Reddi: Bu makalede paylaşılan bilgiler sadece eğitim amaçlıdır. Web kazıma işlemleri sırasında hedef sitenin hizmet şartlarına ve yerel yasalara uygun hareket etmek kullanıcının sorumluluğundadır. İzinsiz veri toplama hukuki sonuçlar doğurabilir.


Yorumlar (0)
Yorum Yaz