Web kazıma projesine başlayan hemen herkes aynı soruyla karşılaşır: Python mı, JavaScript mi? İki dil de bu işi rahatlıkla yapar ve iki tarafta da olgun araçlar var. Doğru seçim; hedef sitelerin yapısına, verinin sonrasında ne olacağına ve ekibinizin zaten hangi dili bildiğine bağlıdır.
Bu yazıda iki dili aynı görev üzerinden karşılaştırıyor, araç ekosistemlerini, dinamik sayfalarda ve ölçekte nasıl davrandıklarını, dağıtım ve bakım yükünü ele alıyor ve kararınızı kolaylaştıracak bir rehber sunuyoruz.
Aynı görev, iki dil
Görev basit: Bir sayfanın HTML'ini proxy üzerinden çekip başlığını okumak. Aşağıdaki iki örnek de aynı işi yapar.
Python: Requests ve Beautiful Soup
pip install requests beautifulsoup4import requests
from bs4 import BeautifulSoup
PROXY = "http://kullanici:parola@pr.proxynet.io:8000"
html = requests.get(
"https://example.com",
proxies={"http": PROXY, "https": PROXY},
timeout=20,
).text
soup = BeautifulSoup(html, "html.parser")
print(soup.select_one("h1").get_text(strip=True))JavaScript (Node.js): fetch ve Cheerio
npm install undici cheerioimport { fetch, ProxyAgent } from "undici";
import * as cheerio from "cheerio";
const dispatcher = new ProxyAgent("http://kullanici:parola@pr.proxynet.io:8000");
const html = await (await fetch("https://example.com", { dispatcher })).text();
const $ = cheerio.load(html);
console.log($("h1").first().text().trim());Görüldüğü gibi statik bir sayfa için iki dil de neredeyse aynı uzunlukta ve aynı mantıkla çalışır. Seçici sözdizimi bile aynıdır: Beautiful Soup'un select_one ve Cheerio'nun $() çağrısı CSS seçicileri kabul eder. Asıl farklar işin boyutu büyüdükçe ortaya çıkar.
Araç ekosistemleri yan yana
| Görev | Python | JavaScript (Node.js) |
|---|---|---|
| HTTP istemcisi | Requests, HTTPX, AIOHTTP | fetch (undici), Axios |
| HTML ayrıştırma | Beautiful Soup, lxml, parsel | Cheerio, jsdom |
| Tarayıcı otomasyonu | Playwright, Selenium | Puppeteer, Playwright |
| Kazıma çatısı | Scrapy | Crawlee |
| Veri işleme | pandas, NumPy, polars | Sınırlı; genelde veri tabanına yazılır |
| Zamanlama ve kuyruk | Celery, APScheduler | BullMQ, node-cron |
| Dışa aktarma | CSV, Parquet, Excel doğrudan | CSV, JSON; Parquet için ek paket |
İki sütun da eksiksizdir; fark, hangi halkanın daha güçlü olduğundadır. Python'da veri işleme halkası, JavaScript'te tarayıcı halkası öne çıkar.
Python'un güçlü olduğu yerler
- Veri işleme ekosistemi. Toplanan veriyi temizlemek, analiz etmek ve dışa aktarmak için pandas, NumPy ve benzeri kütüphaneler çok olgundur. Kazıma işinin çıktısı bir analiz veya makine öğrenmesi hattına gidiyorsa Python doğal bir seçimdir; aynı dilde kalırsınız.
- Hazır kazıma çatısı. Scrapy; istek kuyruğu, yeniden deneme, hız sınırlama, veri dışa aktarma ve ara katman (middleware) mimarisini tek pakette sunar. Büyük ve tekrarlanan tarama işleri için sağlam bir iskelet sağlar; proxy rotasyonu bir ara katmanla eklenir.
- HTTP istemcisi seçenekleri. Basit işler için Requests, yüksek eşzamanlılık için HTTPX veya AIOHTTP bulunur. Aralarındaki farkları HTTPX, Requests ve AIOHTTP karşılaştırmamızda anlattık.
- Öğrenme kolaylığı. Programlamaya yeni başlayan biri için Python'un sözdizimi genellikle daha anlaşılırdır; asenkron yapı zorunlu değildir, gerektiğinde eklenir.
- Veri bilimi ekipleriyle uyum. Analist ve veri bilimci ekipler çoğunlukla Python bilir; kazıma kodunun onların okuyup değiştirebileceği dilde olması bakım yükünü azaltır.
JavaScript'in güçlü olduğu yerler
- Dinamik sayfalar. İçeriği tarayıcıda JavaScript ile yüklenen sitelerde tarayıcıyı yöneten araçlar gerekir. Puppeteer ve Playwright bu alanın öncüleridir ve Node.js ekosisteminde doğmuşlardır. Sayfanın içinde çalışan kodla aynı dili konuşmak,
page.evaluateiçinde yazdığınız kodun betiğin geri kalanıyla aynı dil olması demektir; hata ayıklama kolaylaşır. - Doğal eşzamanlılık. Node.js baştan olay döngüsü üzerine kurulmuştur; çok sayıda isteği aynı anda beklemek dilin varsayılan çalışma biçimidir. Python'da bunun için
asynciove uyumlu kütüphaneler gerekir. - Tarayıcı araçlarıyla aynı dil. Geliştirici konsolunda denediğiniz bir seçiciyi veya kodu doğrudan betiğe taşıyabilirsiniz.
- Tam yığın ekipler. Ekibiniz zaten web uygulamasını JavaScript veya TypeScript ile yazıyorsa, kazıma kodunu aynı dilde tutmak bakım yükünü azaltır ve tür tanımlarını paylaşmanızı sağlar.
- Crawlee gibi modern çatılar. HTTP ve tarayıcı tabanlı tarayıcıları tek arayüzde birleştiren, oturum ve proxy yönetimini yerleşik sunan çatılar Node.js tarafında olgunlaşmıştır.
Karşılaştırma tablosu
| Ölçüt | Python | JavaScript (Node.js) |
|---|---|---|
| Statik sayfa kazıma | Requests + Beautiful Soup | fetch + Cheerio |
| Dinamik sayfa (tarayıcı) | Selenium, Playwright | Puppeteer, Playwright |
| Kazıma çatısı | Scrapy | Crawlee |
| Eşzamanlılık | asyncio ile | Dilin varsayılanı |
| Veri analizi | Çok güçlü | Sınırlı |
| Tür güvenliği | İsteğe bağlı (type hints) | TypeScript ile güçlü |
| Öğrenme eğrisi | Kolay | Orta (asenkron yapı nedeniyle) |
| Dağıtım | Sanal ortam, konteyner | npm, konteyner; sunucusuz ortamlarda yaygın |
| En uygun proje | Veri odaklı, analiz hattına bağlı | Tarayıcı odaklı, dinamik içerik |
Dinamik içerik: asıl ayrım noktası
Seçimi çoğu zaman dil değil, hedef sayfanın nasıl yüklendiği belirler. Sayfanın kaynağında (tarayıcıda "Sayfa kaynağını görüntüle") aradığınız veri varsa basit bir HTTP isteği yeterlidir ve her iki dil de işinizi hızla görür.
Veri, sayfa açıldıktan sonra JavaScript ile yükleniyorsa iki seçenek vardır:
- Arka plandaki API isteğini bulmak. Tarayıcının geliştirici araçlarındaki Ağ sekmesinde sayfanın veriyi hangi adresten çektiğine bakın. Çoğu zaman bu adres doğrudan JSON döndürür ve tarayıcıya hiç ihtiyacınız kalmaz. Bu yöntem hem daha hızlı hem daha az kaynak tüketir; iki dilde de aynı kolaylıkta yapılır.
- Gerçek bir tarayıcı çalıştırmak. API bulunamıyorsa veya karmaşık etkileşim gerekiyorsa Playwright (iki dilde de var), Puppeteer (JavaScript) ya da Selenium (Python) kullanılır.
Tarayıcı otomasyonunun kendi zorlukları vardır: Her sayfa için gerçek bir tarayıcı çalışır, bellek ve işlemci tüketimi HTTP isteğinin katbekat üstündedir ve bot korumaları tarayıcı izlerine bakar. CAPTCHA'nın neden tetiklendiğini Puppeteer ve CAPTCHA, Python tarafındaki araçları ise Selenium ve Undetected ChromeDriver yazılarımızda ele aldık.
Aynı görev, tarayıcıyla
Dinamik bir sayfada aynı başlığı okumak için iki dilde de Playwright kullanılabilir; sözdizimi neredeyse birebirdir.
Python:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(proxy={
"server": "http://pr.proxynet.io:8000",
"username": "kullanici",
"password": "parola",
})
page = browser.new_page()
page.goto("https://example.com")
print(page.locator("h1").first.inner_text())
browser.close()JavaScript:
import { chromium } from "playwright";
const browser = await chromium.launch({
proxy: { server: "http://pr.proxynet.io:8000", username: "kullanici", password: "parola" },
});
const page = await browser.newPage();
await page.goto("https://example.com");
console.log(await page.locator("h1").first().innerText());
await browser.close();Playwright'ın iki dilde de aynı API'yi sunması, dil kararının tarayıcı otomasyonu yüzünden verilmesini gereksiz kılar. Fark, tarayıcıdan çıkan verinin sonrasında nereye gittiğindedir.
Ölçekte ne değişir?
Yüz sayfalık bir işte dil farkı hissedilmez. Yüz bin sayfada üç konu öne çıkar:
- Eşzamanlılık yönetimi. Node.js'te doğal, Python'da
asyncioile. İki tarafta da eşzamanlılığı sınırlamak (semafor, kuyruk) gerekir; sınırsız eşzamanlılık hedef siteyi ve kendi bağlantı sınırlarınızı zorlar. - Bellek. Tarayıcı tabanlı kazımada bellek tüketimi dilden değil tarayıcıdan gelir. HTTP tabanlı kazımada iki dil de hafiftir.
- Hata ve yeniden deneme. Ağ hataları, 429 yanıtları ve proxy hataları için üstel bekleme ile yeniden deneme iki dilde de elle ya da çatı aracılığıyla yazılır. Scrapy ve Crawlee bunu yerleşik sunar.
Ölçekte belirleyici olan dördüncü konu ise dille hiç ilgili değildir: erişim.
Dilden bağımsız olan kısım: erişim
Hangi dili seçerseniz seçin, ölçek büyüdüğünde karşılaşacağınız sorunlar aynıdır: IP engelleri, hız sınırları ve konuma göre değişen içerik. Bu sorunlar kodun değil, trafiğin nereden ve nasıl geldiğinin sonucudur.
- Çok sayıda bağımsız sayfa çekiyorsanız Rotating Proxy her istekte farklı bir IP kullanarak yükü dağıtır.
- Korumalı hedeflerde gerçek kullanıcı adreslerinden gelen Residential Proxy daha az engelle karşılaşır; nedenini Residential ve Datacenter Proxy Farkı yazımızda anlattık.
- Giriş yapılan ya da çok adımlı akışlarda Sticky Proxy aynı IP'yi oturum boyunca korur.
- Farklı ülkelerdeki fiyatları veya arama sonuçlarını karşılaştırıyorsanız konum hedeflemeli IP'ler gerekir; ayrıntılar SEO ve SERP takibi ve fiyat takibi sayfalarımızda.
Sayfanın içeriğini anlamak için yapay zeka modellerinden yararlanmak da iki dilde mümkündür; bunun kazıma akışındaki yerini GPT-6 Astra ile Web Kazıma yazımızda tartıştık. Hangi verinin hangi koşullarda toplanabileceği de dilden bağımsızdır; Web Scraping Yasal mı? yazımızda ele aldık.
Hangisini seçmelisiniz?
- Python'u seçin: Veri analizi, raporlama veya makine öğrenmesi hattına veri topluyorsanız; büyük ve düzenli tarama işleri için Scrapy gibi bir çatı istiyorsanız; ekibiniz Python biliyorsa.
- JavaScript'i seçin: Hedefleriniz ağırlıklı olarak dinamik, tarayıcı gerektiren sitelerse; ekibiniz zaten Node.js veya TypeScript ile çalışıyorsa; kazıma kodu bir web uygulamasının parçası olacaksa.
Kararsız kaldığınızda ekibinizin en çok kullandığı dille başlayın. İki dilin araçları da yeterince olgundur; projeyi başarıya taşıyan şey genellikle dil değil, doğru erişim stratejisi ve sağlam hata yönetimidir.
Karar rehberi
| Durum | Öneri |
|---|---|
| Çıktı pandas ile analiz edilecek | Python |
| Çıktı bir Node.js uygulamasına akacak | JavaScript |
| Hedeflerin çoğu statik HTML | İkisi de; ekibin bildiği dil |
| Hedeflerin çoğu tarayıcı gerektiriyor | JavaScript (Puppeteer) veya Playwright ile ikisi de |
| Büyük, düzenli, çok siteli tarama | Python (Scrapy) veya JavaScript (Crawlee) |
| Ekipte veri bilimci var | Python |
| Ekipte tam yığın web geliştiricisi var | JavaScript |
| Sunucusuz ortamda kısa görevler | JavaScript |
Sık sorulan sorular
Performans açısından hangisi daha hızlı?
Kazımada zamanın büyük bölümü ağda, yani sunucunun yanıtını beklerken geçer. Her iki dilde de asenkron istemciler kullanıldığında fark belirleyici olmaz. Sayfa ayrıştırma hızı ise çoğu projede darboğaz değildir.
Playwright hangi dille daha iyi?
Playwright; JavaScript/TypeScript, Python, Java ve .NET için resmi olarak desteklenir. Yeni özellikler genellikle önce Node.js sürümüne gelir, ancak Python sürümü de günlük kazıma işleri için eksiksizdir.
İki dili aynı projede kullanabilir miyim?
Evet. Örneğin dinamik sayfaları Node.js ile tarayıp ham veriyi bir kuyruğa yazabilir, analiz ve temizleme işini Python tarafında yapabilirsiniz. Kuyruk ya da veri tabanı, iki dünyayı bağlayan doğal arayüzdür.
Scrapy ile Crawlee arasındaki fark ne?
İkisi de tam bir kazıma çatısıdır. Scrapy HTTP tabanlıdır ve tarayıcı için eklenti gerektirir; Crawlee HTTP ve tarayıcı tabanlı tarayıcıları aynı arayüzde sunar. Scrapy daha uzun süredir var ve ekosistemi geniştir; Crawlee TypeScript desteği ve yerleşik oturum yönetimiyle öne çıkar.
Kazıma için TypeScript kullanmalı mıyım?
Ekibiniz TypeScript biliyorsa evet; ayrıştırılan verinin şemasını tür olarak tanımlamak, alan adı değişikliklerini derleme zamanında yakalar. Küçük betiklerde düz JavaScript yeterlidir.
Proxy kullanımı dile göre değişir mi?
Mantık aynıdır: HTTP istemcisine ya da tarayıcıya proxy adresi ve kimlik bilgileri verilir. Sözdizimi kütüphaneye göre değişir; Python örnekleri için Python'da Proxy'ler Nasıl Döndürülür?, Node.js için JavaScript'te cURL yazımıza bakabilirsiniz.
Özetle
Python, toplanan verinin işlenmesi ve büyük tarama çatıları söz konusu olduğunda; JavaScript ise dinamik sayfalar ve tarayıcı otomasyonunda öne çıkar. Statik sayfalarda iki dil de eşit derecede iyidir ve Playwright sayesinde tarayıcı otomasyonu da dil kararını belirlemez. Seçim ne olursa olsun ölçek büyüdükçe belirleyici olan erişim altyapısıdır. Büyük ölçekli projeler için veri kazıma çözümlerimize göz atabilirsiniz.




