İyinet'e Hoşgeldiniz!

Türkiye'nin En Eski Webmaster Forum'una Hemen Kayıt Olun!

Kayıt Ol!

Python ile SEO Crawl Analizi, Analytics ve Search Console Verilerinin İncelenmesi: Temel Kodlar

kutluseo

İyinet Üyesi
Katılım
29 Kasım 2019
Mesajlar
277
Reaction score
2
Konum
İzmir
Excel ve Google Sheets hepimizin eli ayağı olmuş durumda. En temel işlerden en komplike işlere kadar illa bir yerlerde günlük rutinimize dahil oluyorlar. Özellikle SEO analistleri için ileri seviye formülleri öğrenip işlerini daha hızlı yapabilme ekstra bir beceri. Ancak veri büyüdükçe yazılan en mantıklı formül bile anlamını beklerken yitirebiliyor. Excel patlayabiliyor, Sheets yanıt vermeyebiliyor, dönüş alsak da o kadar geç dönüyor ki saatlerimiz formül yazıp beklemekle geçebiliyor. Çeşitli dualar, yalvarış ve totemler ile ekran karşısında iş yapmaya çalıştığınız illa ki olmuştur. Özetle fazla veriye sahip büyük websiteleri ile çalışmak kimi zaman kaosa dönüşebiliyor.

Python işte burada devreye giriyor ve son dönemlerde özellikle SEO dünyasında da popülaritesi oldukça artmaya başlayan bir dil. Temel seviyede öğrenme ve kullanım kolaylığı, çok büyük verilerde dahi hızlıca proses edip dönüş yapması gibi artıları var. Bu yazıda amacım en temel ve basit kodlar ile Python’ın Excel’i Pandas kütüphanesini kullanarak Excel’de yaptığımız işleri nasıl hızlıca yapabildiğimizi göstermek. Hatta aklımıza gelmeyenleri, gelse de oldukça vakit alacak işleri bir kaç satır kod ile hızlıca çözümleyip ön görü elde etmeye çalışacağım. Gözünüz korkmasın, kodlama ve dil öğrenmek bambaşka bir dünya, bambaşka bir uğraş ancak günlük rutin işlerinizi hızlıca yapabilecek kadar kod biliyor olmanız, (ki burada hemen hemen bir çoğunu vermeye gayret edeceğim) işinizi görecek kadarını almanız dahi size oldukça vakit kazandıracaktır. Siz çok sever, modellemeler yaparak Makine Öğrenmesi ve Derin Öğrenmeye kadar devam edebilirsiniz tabi ki :)

Python’ı ileri seviye öğrendiğinizde SEO’da neler yapabileceğinizi görmek istiyorsanız Hamlet Batista’nın yazıları veya JR Oakes’un yazıları ufkunuzu fazlasıyla açacaktır.

Şimdi başlayalım:

Python’ı bilgisayarınıza nasıl indireceğiniz ve kullanacağınız konusu ile ilgili internette oldukça fazla bilgi var. Biz doğrudan kodlara geçelim.

Kütüphanelerin Yüklenmesi
Bu yazıda yalnızca dataframe’ler için Pandas’ı, grafikler için Mathplotlib’i kullanacağız ancak Python’da bir çok kütüphane mevcut. Burada örnek olması açısından diğer kütüphaneleri de ekliyorum, veri analizlerinde ilerlemek isterseniz bu kütüphaneler de oldukça işinize yarayacak.

  1. import pandas as pd
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. import warnings
  5. import seaborn as sns
  6. import scipy.stats as stats
  7. warnings.filterwarnings('ignore')
Temel Kodlar ile Tarama Dosyasının Analizi
Şimdi örneğin Screaming Frog'da yaptığımız taramanın dosyasını buraya alalım:

  1. df1 = pd.read_excel('crawl.xlsx',skiprows=1)
  2. df1.head()
3-1024x426.png


Burada pd.read_xlsx ile tarama dosyamızı okuduk ve bu dosyanın bilgilerini df1'de sakladık. 'csv' dosyası için de pd.read_csv uzantısını kullanabiliriz. head() komutu ile de ilk beş satırımızı görüntülüyoruz. skiprows=1 yapmamızın sebebi ise Screaming Frog çıktısında ilk satırda değil ikinci satırda kolon isimlerinin yer alması.

Diyelim ki 404 yanıt kodu veren sayfalarınızı görmek ve bunları farklı bir dosyaya kaydetmek istiyorsunuz:

  1. df404 = df1[df1['Status Code'] == 404]
  2. df404
5-1024x479.png


Python'da eşitliği göstermek için == işaretini ,eşit değili göstermek için != işaretlerini kullanıyoruz.

Şimdi ayrı bir dosyaya kaydedelim:

  1. df404.to_csv('export404.csv', sep='\t', encoding='utf-8')
404 yanıt kodu veren sayfaları export404.csv isimli dosyaya aktardık. Dolayısıyla farklı satırlarda yazacağınız kodlar ile duplicate sayfaları, redirect sayfaları, title etiketi bulunmayan sayfaları ve daha bir çok crawl çıktısını farklı yerlerde tutabilir ve bir sonraki crawl analizinde yalnızca bu kodları çalıştırarak manuel inceleme öncesi crawl çıktılarınızı saniyeler içinde hazır etmiş olabilirsiniz. Örneğin title etiketi bulunmayan sayfaları tespit edelim:

  1. dtitle = df1.loc[df1['Title 1'].isnull()]
Burada isnull() komutu Title 1 sütununda NaN yani olmayan değerleri tespit ediyor. .loc ise o satırların tespiti ve ekrana basılması için gerekli.

Title 1 yerine 'Meta Description 1' yazarsanız bu sefer de meta description etiketi bulunmayan sayfaları size dökecektir. Yine yukarıda 404 örneğinde gösterdiğimiz gibi bu verileri farklı dosyalara kaydederek incelemenize devam edebilirsiniz.

Örneğin bilgi bulunmayan NaN satırlarının yoğunluğunu bilmek istiyorsunuz. Bunu excel'de tek tek filtreleyerek yaptığınızı düşünün. Bunun yerine Python'da tek satırlık kod ile veriniz hakkında fikir sahibi olabilirsiniz:

  1. plt.figure(figsize=(10,8))
  2. sns.heatmap(df1.isnull(),yticklabels=False,cbar=False,cmap="viridis")
  3. plt.show()
1.png


Bu heatmap'te sarı çizgiler NaN değerlerini ifade ediyor. Bunu heatmap olarak değil de adet olarak görmek isterseniz de:

  1. df1.isnull().sum()
7.png


Crawl Analizini Google Analytics Verileri İle Birleştirme
Basit tarama analizimizi tamamladığımıza göre bu verileri Analytics verileri ile eşleştirerek biraz daha derin incelemeler yapabiliriz.

Öncelikle son 1 aylık veya incelemek istediğiniz veriye göre son 3 aylık Landing Page raporunu alın. İki dosyayı URL'lere göre birleştireceğiz. Ancak öncelikle dosyamızı crawl dosyasında yaptığımız gibi okuyalım:

  1. df_analytics = pd.read_excel('analytics.xlsx')
  2. df_analytics.head()
9-1024x220.png


Şimdi crawl dosyamız ile analytics dosyamızı birleştireceğiz, bunun için pd.merge() komutunu kullanıyoruz:

  1. merged = pd.merge(df1, df_analytics, left_on='Landing Page', right_on='Landing Page', how='outer')
  2. merged.head()
11-1024x252.png


Landing Page'lere karşılık olarak crawl sonuçları da dosyanın sağına eklenmiş durumda.

Son merged isimli dosyanın hangi verileri tuttuğuna bakmak ve bu verilerin tiplerini görmek için info() komutunu kullanabiliriz:

  1. merged.info()
13.png


Toplam 54 kolonumuz mevcut. Kolon isimlerinin karşısında veri tipleri de bulunuyor. Object string/text türünde bir veri olduğunu, float64 virgülden sonra ondalık basamakları olan bir sayı olduğunu, burada yok ancak integer ise tam sayı olduğunu ifade ediyor.

Crawl Depth İncelemesi
Örneğin tarama sonucunda crawl depth dağılımına bakalım:

  1. plt.figure(figsize=(10,5))
  2. merged['Crawl Depth'].value_counts().sort_values().plot(kind = 'barh')
  3. plt.xlabel("URL Counts")
  4. plt.ylabel("Crawl Depth")
  5. plt.title("Crawl Depth / Pages")
14.png


Bu grafiği zaten crawler araçları ile de görebiliyoruz. Sayfalarımız 4., 5., 6. derinliklerde yoğunlaşmış görünüyor. Şimdi ise farklı bir yaklaşımda bulunalım ve Crawl Depth'e karşı Session grafiği çizelim.

  1. plt.figure(figsize=(10,5))

  2. plt.style.use('ggplot')

  3. plt.bar(merged['Crawl Depth'], merged['Sessions'], color='purple')
  4. plt.xlabel("Crawl Depth")
  5. plt.ylabel("Sessions")
  6. plt.title("Crawl Depth & Sessions")

  7. plt.show()
16.png


Enteresan bir trend ile karşılaştık. En çok oturum aldığımız sayfalar Crawl Depth 6'da toplanmış görünüyor. Kıymetli sayfalarımızın Googlebot tarafından 6 adımda ulaşılabilir olması istediğimiz bir yaklaşım değil. Önemli sayfalarımız kolay ulaşılabilir olmalı ve sıklıkla crawl edilebilmeli. Belki 6. derinlikte yer alan sayfalar çok daha iyi performans gösterebilecekken şu an onları oldukça uzakta tutuyoruz. Bu sayfaları daha öne çekmeli miyiz? Bunlar bir grup sayfa mı yoksa tek bir sayfanın yüksek session sayısı verimizi yanıltıyor olabilir mi? Crawl Depth 5'te de aynı şekilde yer alan sayfalarımız hangisi?

Sorular soruları doğuruyor, doğru yoldayız :) Bu soruları cevaplayabilmek için çıktılarımızı incelemeli, sebepleri anlamalı ve gerekliyse aksiyon alarak önemli sayfalarımızı daha öne çekebilmeliyiz. Şimdi Crawl Depth 6 da bulunan sayfalarımızı çekelim:

  1. df_CD6 = merged[merged['Crawl Depth'] == 6]
  2. df_CD6.head()
18-1024x276.png


Özellikle ilk 3 sayfayı incelemeli, eğer gerekliyse bu sayfaların crawl depth'ini düşürmeliyiz.

Internal Linking İncelemesi
Crawl Depth gibi incelemek için seçtiğimiz bir diğer metrik Unique Inlinks olsun. Bu sefer scatter grafiği çizip inlink dağılımını inceleyelim:

  1. plt.figure(figsize=(15,10))
  2. plt.scatter(merged['Unique Inlinks'], merged['Sessions'])
  3. plt.show()
20.png


İç linkleme önemli bir etken sayfaların performansı için. Sayfaların birbirine değer aktarımını da baz alırsak gereksiz yere link vermek veya iyi performans gösterebilecek bir sayfaya yeterli iç linkleme yapmamak optimizasyon gerektiren bir konu. Örneğin yukarıdaki grafiği inceleyelim. Sağ kısımda bulunan yeşil ile işaretlediğim sayfalar oldukça fazla iç linke sahipken çok iyi performans göremediğimiz sayfalar. Bu sayfalar gerçekten kötü performans gösteren sayfalarımız mı, bu kadar iç linkleme yapmamıza gerek var mı yoksa bu sayfalar yalnızca menüden linklenen sayfalarımız olduğu için mi bu kadar çok linke sahip? Yukarıdaki durumda menüden linklenen sayfalar olduğunu tespit ettik. Bu durumda da bu sayfaların menüden linklenmesine gerek olup olmadığını araştırabilirsiniz, tamamen stratejiye bağlı bir durum.

Diğer yandan mor ile işaretlediğimiz sayfalara baktığımızda site genelinde iyi performans gösteren sayfalar olduğunu görüyoruz. Ancak site içi linklemeleri dağılımsal olarak çok da yeterli gibi durmuyor. Bu sayfaları çekebilir, alakalı olan diğer sayfaları tespit ederek bu sayfaların iç linklemesini artırabilirsiniz. Tabi ki bu sayfaların optimizasyona ihtiyacı varsa. Bu durumda Search Console verilerini de veri setimize ekleyerek bunu tespit edebiliriz.

Response Time İncelemesi
Crawl genelinde sayfalarımızın ne kadar hızlı veya ne kadar yavaş yanıt verdiğini gözlemlemek için bir dağılım grafiği çizebiliriz:

  1. plt.hist(merged['Response Time'], color = 'green')
  2. plt.xlabel("Response Time (seconds)")
  3. plt.ylabel("URL Counts")
  4. plt.title("Response Time & URL counts")
  5. plt.show()
21.png


Belirli bir grup sayfamız oldukça hızlı yanıt dönmüş görünüyor. Ancak kalan sayfalarımızın bir çoğu 1.5 ve 2 saniye arasında cevap vermiş. Sayfalarımızın geç açıldığını görüyoruz. Bunun için örneğin 2 saniye üstünde yanıt veren sayfalarımızı çekebilir ve bunların hız skorlarını pagespeed insights aracı ile inceleyebiliriz.

  1. df4 = merged[merged['Response Time'] >= 2.0]
  2. df4.head()
23-1024x407.png


Orphan Sayfaların Tespiti
Analytics verisi ile crawl verisini birleştirdiğimiz için potansiyel orphan page'leri tespit edebiliriz. Eğer analytics'de session sayılan bir sayfa crawl analizinde gelmemişse bu sayfa ya yönlendirilmiştir ve site içinden kaldırılmıştır veya sayfa canlıda olmasına rağmen site içinde herhangi bir yerden linklenmiyordur.

  1. d_orphan = merged.loc[merged['Status Code'].isnull()]
  2. d_orphan
Crawl edilen her bir URL'in bir statü kodu olacağı için NaN olarak tespit edilmemiş olanlar Analytics verisinden gelen sayfalardır diye düşünerek statü kodu boş olan satırları çağırdığımızda potansiyel orphan page olabilecek sayfaları çekmiş oluyoruz:

25-1024x322.png


Yukarıdaki grafikten de görebileceğiniz üzere crawl'da bulunmayan sayfaları tespit etmiş olduk. Şimdi o sayfaları tekrar tarayarak içlerinde 200 yanıt kodu olan var mı diye inceleyebiliriz.

Yeni Bir Kolon Ekleme ve Sayfaları Gruplandırarak Etiketleme
Diyelim ki sayfalarınızın belirli bir URL pattern'i mevcut ve siz bu sayfaları değerlendirirken gruplandırarak değerlendirmek istiyorsunuz. Bizim örneğimizde bu blog sayfaları olacak. URL'lerde /blog/ geçtiği için, ben bunları tespit etmek ve yeni bir kolona bu sayfaların karşısına blog etiketi koymak istiyorum:

  1. d_blog = merged[merged['Landing Page'].str.contains('^https://www.example.com/blog/')]
  2. d_blog['group'].fillna("blog", inplace = True)
  3. d_blog.head()
['group'] diye bir kolonum olmamasına rağmen yukarıda bu kolonu tanımladık ve str.contains komutu ile sayfaları tespit ettik. fillna() komutu ise boşlukları bununla doldur demek. Biz etiket olarak blog seçtik.

26-1024x272.png


Search Console Verisini Ekleme
Şimdi de yine bir veri dosyasını var olan veri setimize ekleyerek datamızı büyütelim:

  1. d_console = pd.read_excel('console.xlsx')
  2. merged2 = pd.merge(merged, d_console, left_on='Landing Page', right_on='Landing Page', how='outer')
  3. merged2.head()
28-1024x256.png


Yukarıda görebileceğiniz üzere Console verileri de landing page'lerin karşısında yerini aldı.

Yine Crawl Depth'i inceleyerek sayfaların ortalama pozisyonlarına bakabiliriz:

  1. plt.figure(figsize=(10,5))

  2. plt.style.use('ggplot')

  3. plt.bar(merged2['Crawl Depth'], merged2['Position'], color='purple')
  4. plt.xlabel("Crawl Depth")
  5. plt.ylabel("Position")
  6. plt.title("Crawl Depth & Position")

  7. plt.show()
29.png


Örneğin sayfanın görünürlük aldığı tüm kelimelerdeki ortalama pozisyonu 20 civarında olan ancak Crawl Depth 7'de bulunan sayfalar olduğunu görüyoruz. Bir ihtimal optimizasyon yaptığımızda hızlıca etkisini görebileceğimiz sayfalar olabilir. Dolayısıyla Crawl Depth 7'de bulunan sayfaları çekerek inceleyebilir, optimizasyon için onları önceliklendirebiliriz. Ancak ortalama pozisyon verisi her zaman bizi doğru yönlendirmeyebilir. Burada kelimeleri de inceleyerek analiz etmek çok daha doğru olacaktır.

Text Bulutu Grafiği
Majestic isimli araçtan aşina olduğumuz, kullanım sıklığına göre kelime bulutu grafiği hem görsel olarak şık duran hem de kelime yoğunluğunu hızlıca tespit etmemize yarayan bir grafik. Anchor text'lerde veya belirli bir grup sayfanın title'ını incelemek için kullanabilirsiniz. Kod örneğini ve örnek görseli farklı bir veri setinden oluşturarak aşağıda paylaşıyorum:

  1. # öncelikle wordcloud kütüphanesini import ediyoruz

  2. from wordcloud import WordCloud

  3. harvard = df[df['Institution'] == 'HarvardX']

  4. wordcloud = WordCloud(background_color="white").generate(" ".join(harvard["Course Subject"]))
  5. plt.figure(figsize=(10,5))
  6. plt.imshow(wordcloud, interpolation='bilinear')
  7. plt.axis("off")

  8. plt.show()
30.png
 

Türkiye’nin ilk webmaster forum sitesi iyinet.com'da forum üyeleri tarafından yapılan tüm paylaşımlardan; Türk Ceza Kanunu’nun 20. Maddesinin, 5651 Sayılı Kanununun 4. maddesinin 2. fıkrasına göre, paylaşım yapan üyeler sorumludur.

Backlink ve Tanıtım Yazısı için iletişime geçmek için Skype Adresimiz: .cid.1580508955483fe5

Üst