Screaming Frog, çoğu SEO için tercih edilen tarayıcıdır, ancak muhtemelen sınırlarına tosladınız: ücretsiz sürümde 500 URL sınırı, büyük sitelerde RAM’in tükenmesi veya bir GUI’yi izlemeden taramaları otomatikleştirme isteği. Scrapy, bu sınırları kaldıran açık kaynaklı Python çerçevesidir.
npm install veya git clone çalıştırabiliyorsanız, Scrapy’yi çalıştırabilirsiniz. Öğrenme eğrisi gerçek ama yönetilebilir, özellikle ajantik kodlama iş akışları aracılığıyla CLI araçlarıyla zaten rahat hissediyorsanız.
Neden Scrapy?
Screaming Frog hızlı denetimler için harika çalışır. Ama sınırları var:
| Sınırlama | Etki |
|---|---|
| 500 URL ücretsiz limiti | Daha büyük siteler için yılda 259$ lisans gerektirir |
| Bellek aç | Büyük taramalar 8GB+ RAM tüketebilir |
| GUI bağımlı | Otomatikleştirmek veya zamanlamak zor |
| Sınırlı özelleştirme | Yapılandırma seçenekleri sabit |
Scrapy bunları çözer:
| Scrapy | Ne elde edersiniz |
|---|---|
| Ücretsiz ve açık kaynak | URL limiti yok, lisans ücreti yok |
| Daha düşük bellek ayak izi | Disk destekli kuyruklar RAM’i kontrol altında tutar |
| CLI-yerel | Scriptlenebilir, cron’lanabilir, CI/CD’ye hazır |
| Tam Python özelleştirmesi | İhtiyacınız olanı çıkarın, istediğiniz gibi filtreleyin |
| Duraklat/Devam Et | Büyük taramaları istediğiniz zaman durdurun ve devam ettirin |
Kurulum
Scrapy Python üzerinde çalışır. Her şeyi temiz tutmak için sanal ortam kullanın:
Debian/Ubuntu:
sudo apt install python3.11-venv
python3 -m venv venv
source venv/bin/activate
pip install scrapy
macOS:
python3 -m venv venv
source venv/bin/activate
pip install scrapy
Windows:
python -m venv venv
venv\Scripts\activate
pip install scrapy
Proje Oluşturma
Scrapy kuruluyken:
scrapy startproject myproject
cd myproject
scrapy genspider sitename example.com
Bu şunları oluşturur:
myproject/
scrapy.cfg
myproject/
__init__.py
items.py
middlewares.py
pipelines.py
settings.py
spiders/
__init__.py
sitename.py
Spider kodu spiders/sitename.py‘ye gider. Yapılandırma settings.py‘de bulunur.
Nazik Tarama için Ayarlar
Herhangi bir şey çalıştırmadan önce settings.py‘yi yapılandırın. Engellenmek, yavaş taramadan daha fazla zaman kaybettirir.
# Nazik tarama
CONCURRENT_REQUESTS_PER_DOMAIN = 5
DOWNLOAD_DELAY = 1
ROBOTSTXT_OBEY = True
# AutoThrottle - sunucu yanıtına göre hızı ayarlar
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 5
AUTOTHROTTLE_MAX_DELAY = 60
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
AUTOTHROTTLE_DEBUG = True
# Güvenlik limitleri
CLOSESPIDER_PAGECOUNT = 10000
# Çıktı
FEED_EXPORT_ENCODING = "utf-8"
AutoThrottle
AutoThrottle, sunucu yanıt sürelerini izler ve tarama hızını otomatik olarak ayarlar:
- Hızlı yanıtlar → hızlanır
- Yavaş yanıtlar → yavaşlar
- Hatalar/zaman aşımları → önemli ölçüde yavaşlar
Screaming Frog’un sabit gecikmelerinin aksine, gerçek sunucu koşullarına uyum sağlar.
Durum Kodu İşleme
Varsayılan olarak, Scrapy’nin HttpErrorMiddleware’i 2xx olmayan yanıtları sessizce düşürür. Bu, 404’lerin, 301’lerin, 500’lerin callback’inize ulaşmadan atıldığı anlamına gelir. Taramanız %100 200 durum kodu gösterebilir, site mükemmel olduğu için değil, hatalar filtrelendiği için.
Tüm durum kodlarını yakalamak için spider sınıfınıza bunu ekleyin:
handle_httpstatus_list = [200, 301, 302, 403, 404, 500, 502, 503]
Screaming Frog varsayılan olarak tüm durum kodlarını yakalar. Bu ayar Scrapy’yi bu davranışla uyumlu hale getirir.
Gerçek Dünya Performansı
5 eşzamanlı istek ve AutoThrottle etkinken test taramasından gerçek rakamlar:
| Tarama İlerlemesi | Sayfa/Dakika | Notlar |
|---|---|---|
| 0-200 sayfa | 14-22 | Rampa |
| 200-500 sayfa | 10-12 | Stabilize oluyor |
| 500-1.000 sayfa | 7-10 | AutoThrottle ayarlanıyor |
| 1.000+ sayfa | 5-7 | Sabit durum |
Özellik Karşılaştırması
| Özellik | Screaming Frog | Scrapy |
|---|---|---|
| Maliyet | Ücretsiz <500 URL, ~259$/yıl | Ücretsiz, açık kaynak |
| Maks tarama boyutu | Bellek sınırlı | Disk destekli kuyruklar |
| Özelleştirme | Sınırlı yapılandırma seçenekleri | Tam Python kodu |
| Zamanlama | Manuel veya üçüncü taraf | Yerel CLI, cron’lanabilir |
| Duraklat/Devam Et | Evet | Evet (JOBDIR ile) |
| Öğrenme eğrisi | Düşük (GUI) | Orta (kod) |
| Hız sınırlama | Temel sabit gecikmeler | AutoThrottle (uyarlanabilir) |
| JavaScript renderlama | İsteğe bağlı (Chrome) | İsteğe bağlı (playwright/splash) |
| Durum kodları | Varsayılan olarak tümü | Yapılandırma gerektirir |
| Alt alan filtreleme | GUI onay kutuları | Kod (esnek regex) |
| Dışa aktarma formatları | CSV, Excel, vb. | JSON, CSV, XML, özel |
| CI/CD entegrasyonu | Zor | Yerel |
URL Filtreleme
Screaming Frog onay kutuları kullanır. Scrapy kod kullanır. Değiş tokuş, hassasiyet için öğrenme eğrisidir.
Uluslararası yolları hariç tutma:
import re
from urllib.parse import urlparse
class MySiteSpider(scrapy.Spider):
name = "mysite"
allowed_domains = ["example.com", "www.example.com"]
start_urls = ["https://www.example.com/"]
# /uk/, /fr/, /de/ gibi uluslararası yolları atla
EXCLUDED_PATTERNS = re.compile(
r"/(in|au|th|es|hk|sg|ph|my|ca|cn|uk|kr|id|fr|vn|de|jp|nl|it|tw)/"
)
def filter_links(self, links):
filtered = []
for link in links:
hostname = urlparse(link.url).hostname or ""
if hostname not in ("example.com", "www.example.com"):
continue
if self.EXCLUDED_PATTERNS.search(link.url):
continue
filtered.append(link)
return filtered
URL desenleri, sorgu parametreleri, yanıt başlıkları, sayfa içeriği veya herhangi bir kombinasyona göre filtreleyebilirsiniz.
Duraklat ve Devam Et
1.000 sayfanın üzerindeki taramalar için, JOBDIR ile duraklat/devam et’i etkinleştirin:
scrapy crawl myspider -o output.json -s JOBDIR=crawl_state
Scrapy durumu crawl_state/‘e kaydeder. Duraklatmak için Ctrl+C‘ye basın. Devam etmek için aynı komutu çalıştırın.
Durum, bekleyen URL’leri, görülen URL’leri ve istek kuyruğunu içerir. Bu, dosya tabanlı olduğu ve sistem yeniden başlatmalarını atladığı için Screaming Frog’un kaydet/yükle özelliğinden daha sağlamdır.
JavaScript Renderlama
Scrapy sadece ham HTML getirir. JavaScript renderlamaz. Bu, curl‘ün döndürdüğüyle aynıdır.
Çoğu SEO taraması için bu iyidir:
- Meta etiketleri, canonical’lar ve h1’ler genellikle ilk HTML’dedir
- Arama motorları öncelikle sunucu tarafında renderlanan içeriği indexler
- Çoğu e-ticaret ve içerik sitesi sunucu tarafında renderlenir
Hedef siteniz içeriği istemci tarafında renderlıyorsa, seçenekleriniz var:
| Paket | Notlar |
|---|---|
| scrapy-playwright | Chromium/Firefox/WebKit kullanır. Modern JS siteleri için önerilir |
| scrapy-splash | Hafif, Docker tabanlı renderlayıcı |
| scrapy-selenium | Eski yaklaşım, hala çalışır |
JS renderlama önemli ölçüde daha yavaş ve kaynak yoğundur. Sadece site gerektiriyorsa ekleyin.
Screaming Frog benzer bir değiş tokuşa sahiptir. JavaScript renderlamayı etkinleştirmek arka planda Chrome kullanır ve taramaları önemli ölçüde yavaşlatır.
Bellek Yönetimi
Tam alan çıkarma ile ~1.300 sayfada:
- Bellek: ~265 MB
- CPU: ~%4
JOBDIR kullanmak istek kuyruklarını diske taşır ve belleği düşük tutar. Çok büyük taramalar (100k+ URL) için bu ayarları ekleyin:
MEMUSAGE_LIMIT_MB = 1024
MEMUSAGE_WARNING_MB = 800
SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleFifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.FifoMemoryQueue'
Bu, bellek kullanımını sınırlar ve zamanlayıcı için disk destekli kuyrukları zorlar.
Çıktı Verileri
Temel spider çıktısı:
{
"url": "https://www.example.com/page/",
"title": "Sayfa Başlığı Burada",
"status": 200
}
SEO taramaları için, Screaming Frog’un dışa aktardığına benzer alanlar istersiniz:
def parse_page(self, response):
yield {
"url": response.url,
"status": response.status,
"title": response.css("title::text").get(),
"meta_description": response.css("meta[name='description']::attr(content)").get(),
"meta_robots": response.css("meta[name='robots']::attr(content)").get(),
"h1": response.css("h1::text").get(),
"canonical": response.css("link[rel='canonical']::attr(href)").get(),
"og_title": response.css("meta[property='og:title']::attr(content)").get(),
"og_description": response.css("meta[property='og:description']::attr(content)").get(),
"word_count": len(response.text.split()) if response.status == 200 else None,
"content_type": response.headers.get("Content-Type", b"").decode("utf-8", errors="ignore"),
}
İhtiyacınıza göre alan ekleyin veya kaldırın. CSS seçicileri herhangi bir sayfa içi öğe için çalışır.
Dışa aktarma formatları: JSON (-o output.json), JSON Lines (-o output.jsonl), CSV (-o output.csv), XML (-o output.xml).
JSON Lines büyük taramalar için en iyisidir. Dosyalar tarama sırasında satır satır geçerlidir, böylece tail -f ile izleyebilirsiniz. Standart JSON, tarama tamamlanana kadar geçerli değildir.
Screaming Frog → Scrapy
SF iş akışlarını Scrapy’ye eşleme:
| Screaming Frog Eylemi | Scrapy Karşılığı |
|---|---|
| Yeni tarama başlat | scrapy crawl spidername |
| Tarama gecikmesi ayarla | Ayarlarda DOWNLOAD_DELAY |
| Eşzamanlı thread’leri sınırla | CONCURRENT_REQUESTS_PER_DOMAIN |
| robots.txt’ye uy | ROBOTSTXT_OBEY = True |
| CSV’ye dışa aktar | -o output.csv |
| Taramayı kaydet/yükle | -s JOBDIR=crawl_state |
| Alt alanları filtrele | Spider’da kod (regex) |
| Özel çıkarma | parse()‘da CSS/XPath seçiciler |
Zihniyet değişimleri:
- Yapılandırma koddur. Onay kutularını tıklamak yerine
settings.py‘yi düzenleyin. - Çıkarma açıktır. Hangi verilerin yakalanacağını siz yazarsınız.
- Zamanlama yereldir. cron veya CI/CD’ye komutlar ekleyin.
- Hata ayıklama loglar demektir. Neler olduğunu görmek için
AUTOTHROTTLE_DEBUG‘ı etkinleştirin.
Tam İş Akışı
Yukarıdaki standart ayarlarla, Scrapy’yi 15 dakikadan kısa sürede kurabilir ve taramaya başlayabilirsiniz:
python3 -m venv venv
source venv/bin/activate # Windows'ta venv\Scripts\activate
pip install scrapy
scrapy startproject urlcrawler
cd urlcrawler
scrapy genspider mysite example.com
# settings.py'yi nazik tarama yapılandırmasıyla düzenleyin
# spiders/mysite.py'yi parse mantığınızla düzenleyin
scrapy crawl mysite -o urls.jsonl -s JOBDIR=crawl_state
Scrapy Shell
Özel yapılandırmalar oluştururken, seçicilerinizi ve ayarlarınızı etkileşimli olarak test etmek için Scrapy Shell‘i kullanın:
scrapy shell "https://example.com"
Bu, yanıt zaten yüklenmiş olarak etkileşimli bir Python konsolu açar. Spider’ınıza eklemeden önce CSS ve XPath seçicileri gerçek zamanlı test edin:
>>> response.css('title::text').get()
'Example Domain'
>>> response.xpath('//h1/text()').get()
'Example Domain'
Scrapy Shell, iterasyon süresini önemli ölçüde azaltır. Tam taramalar çalıştırmadan çıkarma mantığını doğrulayın.
Tam Spider Şablonu
URL filtreleme, durum kodu işleme ve tam SEO alan çıkarma ile üretime hazır bir spider:
import re
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from urllib.parse import urlparse
class SEOSpider(CrawlSpider):
name = "seospider"
allowed_domains = ["example.com"]
start_urls = ["https://www.example.com"]
# Capture all HTTP status codes, not just 2xx
handle_httpstatus_list = [200, 301, 302, 403, 404, 500, 502, 503]
# URL patterns to exclude
EXCLUDED_PATTERNS = re.compile(
r"/(in|au|th|es|hk|sg|ph|my|ca|cn|uk|kr|id|fr|vn|de|jp|nl|it|tw)/"
)
rules = (
Rule(
LinkExtractor(allow=()),
callback="parse_page",
follow=True,
process_links="filter_links",
),
)
def filter_links(self, links):
filtered = []
for link in links:
parsed = urlparse(link.url)
hostname = parsed.hostname or ""
if hostname not in ("example.com", "www.example.com"):
continue
if self.EXCLUDED_PATTERNS.search(link.url):
continue
filtered.append(link)
return filtered
def parse_page(self, response):
yield {
"url": response.url,
"status": response.status,
"title": response.css("title::text").get(),
"meta_description": response.css("meta[name='description']::attr(content)").get(),
"meta_robots": response.css("meta[name='robots']::attr(content)").get(),
"h1": response.css("h1::text").get(),
"canonical": response.css("link[rel='canonical']::attr(href)").get(),
"og_title": response.css("meta[property='og:title']::attr(content)").get(),
"og_description": response.css("meta[property='og:description']::attr(content)").get(),
"word_count": len(response.text.split()) if response.status == 200 else None,
"content_type": response.headers.get("Content-Type", b"").decode("utf-8", errors="ignore"),
}
example.com‘u hedef alan adınızla değiştirin. EXCLUDED_PATTERNS‘ı sitenizin URL yapısına göre ayarlayın.
Hangisini Ne Zaman Kullanmalı
Screaming Frog:
- 500 URL’nin altında hızlı denetimler
- Dakikalar içinde sonuçlar gerekiyor
- Görsel site keşfi
- CLI ile rahat değilsiniz
- Screaming Frog verilerini Redirects.net ile kullanma
Scrapy:
- 10.000 URL’nin üzerinde siteler
- Otomatik, zamanlanmış taramalar
- Özel çıkarma ihtiyaçları
- CI/CD entegrasyonu
- Bellek kısıtlamaları
- Sürüm kontrollü yapılandırmalar
Sonuç
Scrapy, Screaming Frog’dan daha dik bir kurulum eğrisine sahip, ancak GUI tarayıcılarının dayattığı pratik sınırları kaldırır. URL sınırları yok, lisans ücretleri yok, daha düşük bellek kullanımı ve yerel otomasyon.
Küçük başlayın. Bildiğiniz bir siteyi tarayın. Muhafazakar ayarlar kullanın. Çıktıyı Screaming Frog ile karşılaştırın. Veriler eşleşecek, ancak ölçeklenen bir aracınız olacak.