Google'ın hiç ziyaret etmediği sayfaları loglarla bulmak

Sitemap'e bir URL eklemek, Google'ın o sayfaya geleceği anlamına gelmez. Bazı sayfalar aylarca tek bir Googlebot isteği almadan bekler; sitenin sahibi de bunu genelde sayfa hiç trafik almayınca fark eder.

Search Console bu soruya tam cevap vermez. URL denetimi tek tek çalışır, dizine ekleme raporu en fazla 1000 örnek gösterir. Oysa elinizde iki liste var: sitemap'teki URL'ler ve Googlebot'un sunucu loglarında istediği URL'ler. Bu iki listeyi karşılaştırmak, sorunu birkaç saniyede ortaya çıkarır.

Mantık: iki küme, üç liste

Karşılaştırma basit bir küme işlemi:

  • Sitemap'te var, logda yok: Google'ın dönem boyunca hiç ziyaret etmediği sayfalar. Asıl aradığımız liste bu.
  • Logda var, sitemap'te yok: Googlebot'un taradığı ama sizin sitemap'e koymadığınız URL'ler. Parametreli adresler, eski URL'ler, unutulmuş sayfalar burada çıkar.
  • İkisinde de var: Sağlıklı kısım. Yine de durum kodlarına bakmak gerekir; sitemap'teki bir URL'nin 301 ya da 404 döndüğünü burada görürsünüz.

Dönem seçimi önemli. Ben en az 30 gün, tercihen 90 gün log kullanıyorum. Az taranan sayfalar bir haftalık logda doğal olarak görünmeyebilir; bu onları "hiç taranmamış" yapmaz. 90 günlük pencerede tek bir istek almamış bir sayfa ise gerçekten bir sorun işaretidir.

Hazırlık

İki şeye ihtiyacınız var. Birincisi sitemap adresi; sitemap index kullanıyorsanız index dosyasının adresi yeterli, betik alt sitemap'leri kendisi okur. İkincisi erişim logları. cPanel'de logları nasıl arşivleyip indireceğinizi cPanel loglarından Googlebot analizi yazısında anlattım.

Aynı yazıda sahte Googlebot'ları DNS ile ayıklamayı da gösterdim. Bu betik hız için sadece user agent'a bakıyor. Bizim amacımız için sahte satırlar sonucu fazla bozmaz, çünkü "hiç taranmamış" listesine etkileri sınırlı; ama en doğrusu logu önce doğrulayıp doğrulanmış dosyayı bu betiğe vermek.

Betik

Sadece Python 3 standart kütüphanesini kullanıyor, kurulum gerektirmiyor. Düz ya da .gz sitemap ve log dosyalarını okuyabiliyor.

tarama_karsilastir.py
#!/usr/bin/env python3
# Kullanım: python3 tarama_karsilastir.py SITEMAP LOG [LOG ...]
# SITEMAP bir URL ya da yerel dosya olabilir; sitemap index de desteklenir.
import gzip, re, sys
import urllib.request
import xml.etree.ElementTree as ET
from urllib.parse import urlsplit, unquote

NS = "{http://www.sitemaps.org/schemas/sitemap/0.9}"
ISTEK = re.compile(r'"(?:GET|HEAD) (\S+) HTTP/[^"]*" (\d{3})')
STATIK = (".css", ".js", ".png", ".jpg", ".jpeg", ".gif", ".webp", ".avif",
          ".svg", ".ico", ".woff", ".woff2", ".xml", ".txt")

def normalize(url):
    # Alan adını ve fragment'ı at; yolu ve sorguyu çözülmüş haliyle karşılaştır
    p = urlsplit(url)
    yol = unquote(p.path) or "/"
    return yol + ("?" + unquote(p.query) if p.query else "")

def oku(kaynak):
    if kaynak.startswith(("http://", "https://")):
        istek = urllib.request.Request(kaynak, headers={"User-Agent": "sitemap-kontrol/1.0"})
        veri = urllib.request.urlopen(istek, timeout=30).read()
    else:
        with open(kaynak, "rb") as f:
            veri = f.read()
    return gzip.decompress(veri) if veri[:2] == b"\x1f\x8b" else veri

def sitemap_urlleri(kaynak):
    kok = ET.fromstring(oku(kaynak))
    locs = [e.text.strip() for e in kok.iter(NS + "loc") if e.text]
    if kok.tag == NS + "sitemapindex":
        # Sitemap index: her alt sitemap'i ayrı ayrı oku
        return set().union(*(sitemap_urlleri(u) for u in locs))
    return {normalize(u) for u in locs}

def taranan_urller(dosyalar):
    taranan = {}
    for yol in dosyalar:  # dosyaları eskiden yeniye verin; son durum kodu kalır
        ac = gzip.open if yol.endswith(".gz") else open
        with ac(yol, "rt", encoding="utf-8", errors="replace") as f:
            for satir in f:
                if "Googlebot" not in satir:
                    continue
                m = ISTEK.search(satir)
                if m and not urlsplit(m.group(1)).path.lower().endswith(STATIK):
                    taranan[normalize(m.group(1))] = m.group(2)
    return taranan

def yaz(dosya, satirlar):
    with open(dosya, "w", encoding="utf-8") as f:
        f.write("\n".join(satirlar) + ("\n" if satirlar else ""))

if len(sys.argv) < 3:
    sys.exit("Kullanım: tarama_karsilastir.py SITEMAP LOG [LOG ...]")

sitemap = sitemap_urlleri(sys.argv[1])
taranan = taranan_urller(sys.argv[2:])

hic = sorted(sitemap - taranan.keys())
disari = sorted(taranan.keys() - sitemap)
ortak = sorted(sitemap & taranan.keys())

yaz("hic_taranmamis.txt", hic)
yaz("sitemap_disi_taranan.txt", [f"{taranan[u]}\t{u}" for u in disari])
yaz("taranan_sitemap.txt", [f"{taranan[u]}\t{u}" for u in ortak])
print(f"Sitemap: {len(sitemap)} | Googlebot'un istediği: {len(taranan)}")
print(f"Hiç taranmamış: {len(hic)} | Sitemap dışı taranan: {len(disari)} | Ortak: {len(ortak)}")

Çalıştırmak için log dosyalarını eskiden yeniye sıralı verin:

python3 tarama_karsilastir.py https://example.com/sitemap_index.xml \
  alanadi.com-Jul-2026.gz alanadi.com-Aug-2026.gz alanadi.com-Sep-2026.gz

Betik çalıştığı klasöre üç dosya yazar: hic_taranmamis.txt, sitemap_disi_taranan.txt ve taranan_sitemap.txt. Son ikisinde her URL'nin önünde, dönem içinde Googlebot'a döndürülen son durum kodu var.

Normalizasyon neden önemli?

Sitemap'te URL'ler tam adres olarak yazılır (https://example.com/blog/), logda ise sadece yol görünür (/blog/). Betik bu yüzden alan adını atıp yol ve sorgu kısmını karşılaştırıyor. Ayrıca yüzde kodlamasını çözüyor; %C3%A7 ile ç aynı URL sayılıyor. Türkçe karakterli URL'lerde bu adım olmazsa sonuçların yarısı yanlış çıkar.

Bilinçli olarak yapmadığım bir şey var: sondaki eğik çizgiyi silmiyorum. /blog ile /blog/ farklı URL'lerdir ve biri diğerine yönleniyorsa bunu görmek istiyorum. Ayrıca betik tek bir alan adı için yazıldı; logda birden fazla sitenin istekleri karışıksa önce ilgili alan adının logunu ayırın.

CSS, JavaScript, görsel ve robots.txt gibi istekleri de dışarıda bırakıyorum. Bunlar sitemap'te olmadığı için "sitemap dışı" listesini gereksiz yere şişirirdi.

Sonuçları yorumlamak

Hiç taranmamış sayfalar

Bu listedeki URL'ler için ilk sorduğum soru: bu sayfaya sitenin içinden kaç link var? Çoğu zaman cevap sıfır ya da bire yakındır. Sadece sitemap'te duran, hiçbir menüden, kategoriden ya da yazıdan link almayan sayfalar yetim sayfalardır (orphan pages). Google bunları keşfedebilir ama önemsiz olarak görür ve taramayı erteler.

Listede bir kalıp arayın. Hepsi aynı kategoride mi? Hepsi sayfalamanın derin sayfalarından mı erişiliyor? Hepsi son ay yayınlanan sayfalar mı? Yeni sayfalar için biraz beklemek yeterli olabilir; aylardır duran eski sayfalar içinse mimari bir düzeltme gerekir.

Düzeltme genelde şunlardan biri:

  1. İç link verin. Sayfayı ilgili kategori sayfasından, ilgili yazılardan ya da bir hub sayfasından linkleyin. Nasıl önceliklendirileceğini iç linkleme stratejisi yazısında anlattım.
  2. Tıklama derinliğini azaltın. Ana sayfadan beş altı tıklama uzaktaki sayfalar geç taranır. Kategori yapısını yassılaştırmak ya da sayfalamaya ek bağlantılar koymak işe yarar.
  3. Sayfayı sorgulayın. Bazı sayfalar hiç taranmıyor çünkü zaten değersiz. Kimsenin aramadığı, başka bir sayfanın kopyası olan içerikleri birleştirmek ya da kaldırmak, siteyi hafifletir.

Sitemap dışında taranan URL'ler

Bu listede genelde üç grup çıkar. Birincisi parametreli URL'ler: filtre, sıralama, takip kodları. Googlebot bunları iç linklerden buluyor demektir. İkincisi eski URL'ler: çoğu 301 ya da 404 döner, dış linklerden ya da eski sitemap'lerden hatırlanır. Üçüncüsü gerçekten sitemap'te olması gereken ama unutulmuş sayfalar.

Üçüncü grubu sitemap'e ekliyorum. Parametreli URL'ler çok fazlaysa bunun bir tarama israfı olup olmadığını değerlendiriyorum; küçük sitelerde genelde sorun olmaz. Eski URL'lerde ise yönlendirmelerin doğru hedefe gittiğini kontrol ediyorum.

İkisinde de olan URL'ler

Buradaki kontrol basit: durum kodu 200 olmayan her satır bir sitemap hatasıdır. Sitemap'te sadece 200 dönen, canonical, dizine girmesini istediğiniz URL'ler olmalı. Yönlendiren ya da 404 dönen URL'leri sitemap'ten çıkarın. Sitemap'i elle yönetiyorsanız sitemap oluşturucu temiz bir başlangıç listesi üretmek için işinizi görür.

Taranmak, dizine girmek değildir

Bu analiz sadece taramayı gösterir. Bir sayfanın düzenli taranıyor olması, dizinde olduğu anlamına gelmez. Taranıp dizine girmeyen sayfalar için sebep genelde içerikle ilgilidir ve o konuyu Tarandı, şu anda dizine eklenmedi yazısında ayrıca ele aldım. Ben iki analizi birlikte kullanıyorum: önce hiç taranmayanları buluyorum, sonra taranan ama dizine girmeyenlere bakıyorum.

Özetle

  • En az 30, tercihen 90 günlük erişim logunu topla ve Googlebot satırlarını doğrula.
  • Betiği sitemap index ve log dosyalarıyla çalıştır.
  • Hiç taranmamış sayfalarda iç link sayısına ve tıklama derinliğine bak.
  • Sitemap dışında taranan URL'leri üç gruba ayır: parametreli, eski, unutulmuş.
  • Sitemap'te 200 dışında kod dönen her URL'yi temizle.
  • Değişikliklerden sonra birkaç hafta bekle ve analizi tekrarla.

Comments / questions

If you have a question about any topic or wish to contact me: Telegram or send an email to [email protected] Thanks!

Related pages