Veri bilimi/analizi projelerinde çözülecek problem tanımlandıktan sonraki adım verinin elde edilmesidir. Analiz için kullanılacak veri “Uygulama Programlama Arayüzü (Application Programming Interface – API)” aracılığı ile herkese açık bir dış veri kaynağından elde edilebilir.

Bu yazıda Python’ın requests modülünü kullanarak API aracılığı ile veri çekmeyi deneyimleyeceğiz.

Uygulama Programlama Arayüzü (Application Programming Interfaces – API) nedir?

Türkçe’ye Uygulama Programlama Arayüzü olarak çevrilen API, iki yazılımın birbiri ile konuşmasına imkan sağlayan bir araçtır. API sayesinde bir uygulamanın sahip olduğu yeteneklere, uygulama sahibinin izin verdiği sınırlar içerisinde erişim sağlayabiliriz. Herhangi bir uygulamaya ait bir API’yi kullanabilmek için uygulama tarafından her kullanıcıya özel sunulan kimlik bilgilerine ihtiyaç duyarız.

Buraya kadar anlattığımız teknik bilgiyi bir örnek ile açıklayalım. Spotify veya Netflix gibi birçok uygulamada Facebook veya Google hesabınızla hesap oluşturabiliyorsunuz. Spotify/Netflix veya herhangi bir uygulama size bu hizmeti sunabilmek için Facebook ve Google’ın API’lerini kullanmaktadır.

API kullanımına bir diğer örnek ise harita üzerinden oynanan bir zamanların popüler oyunu Pokemon Go’dur. Pokemon oyunu kullanıcılarına harita özelliğini sunabilmek için Google Maps API kullanır.

Görsel Kaynak: Polygon

API’ler sayesinde daha önceden yazılmış kodları özelleştirerek çok hızlıca uygulamalar geliştirebilir, hali hazırdaki uygulamaları geliştirecek yeni özellikler ekleyebilir ve hızlı ve anlık olarak veri akışı sağlanabilir.

Bugün akla gelen birçok şirket hem gelir elde etmek hem de sektörün gelişmesi için API’ler geliştirmekte ve ücretli veya ücretsiz olarak paylaşmaktadır.

API veri bilimi için neden önemlidir?

Veri bilimi için API kullanımının sunduğu bazı avantajlar vardır:

  • Dünya üzerinde birçok farklı konuda, API’ler yardımı ile erişilebilen açık veri kaynağı bulunmaktadır. API’ler sayesinde farklı veri kaynaklarına kolayca erişim sağlayabilirsiniz.
  • Hisse senedi değeri, hava durumu gibi veri akışının sürekli güncellendiği durumlarda API kullanımı kolaylık ve pratiklik sağlar.
  • Derya deniz bir veri seti içerisinden sadece belirli kriterlere uygun küçük bir bölümün kullanılmak istendiği durumlarda esneklik sağlar. Örneğin, Twitter API’ı ile tüm tweetleri indirmek yerine belirli kelimelerin geçtiği tweetleri filtreleyip erişebilirsiniz.
  • Kendi veri kategorizasyonunuzu yapmanın zaman aldığı ve maliyetli olduğu durumlarda hali hazırda işi bu olan bir şirketin verisini kullanmak için API’ler kullanışlıdır. Örneğin, bir restoran listeleme platformu Zomato’nun API’sinde her restoran için çok detaylı mutfak kategorileri bulunmaktadır. Kendi kategorilerinizi oluşturmak yerine buradaki hazır veriyi kullanarak zaman kazanabilirsiniz.

Peki bir API nasıl çalışır?

API’ler, iki yazılımın (uygulama, makine vs.) birbiri ile nasıl iletişim kuracağını belirleyen kurallara sahip aracılardır. Bir API 3 elemandan oluşur:

  1. Erişim (Access): Veriye erişecek kullanıcıya ait bilgilerdir.
  2. İstek (Request): Veri kaynağından yanıt alabilmek için gönderilen taleptir.
    1. Sorgu adresi (Endpoint): Veriye nasıl erişilebileceğini gösteren iletişim noktalarıdır. İstekler bu noktalara gönderilir.
    2. Metot: Veri kaynağına yönelik yapılabilecek farklı işlemlerdir.
    3. Parametre: Elde edilecek yanıtı özelleştirebilen seçeneklerdir.
  3. Yanıt (Response): İstek sonunda elde edilen sonuç.

API’lerin çalışma prensiplerini gerçek bir örnek üzerinden inceleyelim. Uçak bileti satın almak üzere bir havayolu şirketinin websitesini ziyaret ettiniz. Sonrasında:

  1. Websitesindeki arayüz/uygulama yardımı ile kalkış ve varış noktalarını, gidiş tarihinizi ve kaç kişi olduğu bilgilerini girdiniz.
  2. Girdiğiniz bilgiler API yardımı ile bir istek (request) olarak havayolu şirketinin web sunucularına gönderildi.
  3. Web sunucusu veri tabanı ile konuşarak uygun uçuşları, boşlukları ve fiyatları belirledi ve bilgiler/veriler ekranınıza bir yanıt (response) olarak gönderildi.

API Dokümanı

API’lerle ilgili en kritik bilgiler, API sağlayıcısı tarafından oluşturulan API dokümanlarında yer alır. Herhangi bir API ile etkileşime geçmeden önce ilgili dokümanı bulup okumak ve bir rehber gibi o API ile çalıştığınız süre boyunca yanınızda bulundurmak önemlidir.

Bir API dokümanında:

  • İlgili API’ye nasıl erişim sağlayacağınız,
  • Hangi verileri elde etmek için hangi sorgu adreslerini kullanacağınız,
  • Verileri hangi parametreler ile özelleştirebileceğiniz,
  • Kullanım karşılığında ücret ödeyip ödemeyeceğiniz,
  • Kullanım sırasında dikkat etmeniz gereken limitlere dair bilgiler bulabilirsiniz.

Bazı örnek API dokümanları:

requests modülü

Python’da herhangi bir API’ye istek gönderebilmek ve API’lerle çalışabilmek için “requests” modülü kullanılır. Requests, Python’da bulunan standart kütüphanelerden biri olmadığı için kullanıma başlamadan önce yüklenmesi gerekir.

pip kullanarak requests modülü yüklenebilir:

pip install requests
Collecting requests
  Downloading requests-2.25.1-py2.py3-none-any.whl (61 kB)
     |████████████████████████████████| 61 kB 1.1 MB/s eta 0:00:011
Requirement already satisfied: idna<3,>=2.5 in ./opt/anaconda3/lib/python3.7/site-packages (from requests) (2.8)
Requirement already satisfied: certifi>=2017.4.17 in ./opt/anaconda3/lib/python3.7/site-packages (from requests) (2019.11.28)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in ./opt/anaconda3/lib/python3.7/site-packages (from requests) (1.25.8)
Requirement already satisfied: chardet<5,>=3.0.2 in ./opt/anaconda3/lib/python3.7/site-packages (from requests) (3.0.4)
Installing collected packages: requests
Successfully installed requests-2.25.1
Note: you may need to restart the kernel to use updated packages.

Yükleme başarılı oldu. Kullanım için sadece ilgili çalışma dosyasını çağırmamız gerekmektedir.

import requests

requests modülü kullanım için hazır. İlk basit isteği yollamak için hazırız.

İstek (Request)

Tüm API’ler birer web servisidir. Bir web servisinden veri çekmek için istek yollanması gerekir. Yollanacak bu istek bir HTTP isteğidir.

Temel olarak baktığımızda, bu istek herhangi bir web sitesini ziyaret etmek ile aynıdır. Favori tarayıcınıza girip, haberler için bir haber sitesine girmeye çalıştığınızda da bir HTTP isteği yollamış olursunuz.

GET metodu

Çok farklı işlemlere yarayan HTTP metodları vardır. Bu yazının amacı veri çekmek olduğu için, bu işleme hizmet eden fonksiyon olan GET metodunu kullanacağız. Bir “GET isteği” yollayabilmek için requests.get() metodu kullanılır.

requests.get(url, params=None, headers=None, cookies=None, auth=None, timeout=None)
  • url (zorunlu): İstek gönderilecek adres.
  • params (isteğe bağlı): Gönderilen isteği özelleştirebilecek ifadeler.
  • headers (isteğe bağlı): İsteğin nasıl yorumlanacağına dair sunucuya bilgi veren ifadeler.
  • cookies (isteğe bağlı): İstemciye ait oturum (session) bilgilerini saklayan ifadeler.
  • auth (isteğe bağlı): İstemciye ait kimlik bilgileri.
  • timeout (isteğe bağlı): Gönderilen isteğin yanıtı için beklenecek saniye cinsinden süre.

get() metodu, istek gönderilecek kaynak noktasına (endpoint) ihtiyaç duyar.

istek = requests.get("https://api.github.com")

İstek başlığı (headers)

İstek sırasında gönderilen ve istek başlığı olarak isimlendirilen headers ile sunucuya gönderilen isteğin nasıl yorumlanması gerektiğine dair bilgi verilir.

Özel istek başlığı tanımlarken, dictionary formatında tanımlarız. İstek başlığı ile tarayıcı kaynağı (user-agent) ve içerik tipi (Content-Type) bilgileri özelleştirilebilir.

headers = {

"user-agent": "ravenfo",
'Content-Type': 'application/json'

}

istek = requests.get("https://api.github.com", headers = headers)

Yukarıdaki örnekte user-agent ile sunucuya kendi tarayıcımızın adının “ravenfo” olduğunu ve alacağımız veri tipinin JSON formatında olduğu bilgisini özellikle ilettik.

İstek başlığı çoğunlukla requests modülü tarafından otomatik olarak gönderilir. API sunucusu tarafından bağlantı için özellikle bir şart olarak belirtilmediği durumlar haricinde kullanılması gerekli değildir.

Parametre – params()

Parametreler yardımı ile API’den istediğimiz yanıtı özelleştirebiliriz. Şöyle bir örnek üzerinden ilerleyelim. Diyelim ki Spotify API‘sine bağlanıp müziklere ait verilere erişmek istiyorsunuz. Spotify API‘si ile milyonlarca şarkıya ait veriye erişme imkanınız var. Fakat araştırmanız gereği, sadece Türkiye’den yayınlanmış eserlerle ilgileniyorsunuz. Parametreler sayesinde ilgisiz diğer verileri de sorgulayıp, zaman ve güç israf etmek yerine sadece istediğiniz doğru veriye erişebilirsiniz.

Kullanacağınız API’nin ilgili API dokümantasyon sayfasında hangi sorgu adresinin hangi parametrelere izin verdiğini görebilirsiniz.

Spotify için örneğe devam edecek olursak:

parameters = {

"market": "TR",
"ids": "7ouMYWpwJ422jRcDASZB7P,4VqPOruhp5EdPBeR92t6lQ,2takcwOaAZWiXQijPHIx7B"

}

tr_song = requests.get("https://api.spotify.com/v1/tracks", params = parameters)

Yukarıdaki örnekte sadece parametreleri dair bir farkındalık sunmak istedim. Spotify API tarafından istenen diğer koşullar (Ör: API anahtarı) bu sorguda yerine getirilmediği için kod çalışmayacaktır.

Kimlik doğrulaması – auth()

Çoğu API kullanım öncesinde kimlik doğrulaması istemektedir. API kimlik bilgilerini genelde API dokümanında belirtilen şekilde tamamlayıp, karşılığında bir API anahtarı (API key) elde ederiz. Bu API key ve servis tarafından istenen diğer bilgileri auth veya params argümanlarını kullanarak sunarız. Hangi argümanı kullanacağımız ve nasıl giriş yapacağımız yine API dokümantasyonunda servis tarafından belirtilmiştir.

Örnek olarak Yandex, Translate API‘sinde API Key’i parametre olarak almayı tercih ederken, Zendesk API‘sinde auth parametresini tercih etmektedir.

#Yandex
url = 'https://translate.yandex.net/api/v1.5/tr.json/translate'
requests.get(url, params = {key=API_KEY})

#Zendesk
url = "https://your_subdomain.zendesk.com/api/v2/groups.json"
requests.get(url, auth=("username", "password"))

Zaman aşımı – timeout

Bir istek yollandığı zaman, yanıt gelene kadar başka bir işleme geçilmez. Herhangi bir sebepten dolayı bu bekleme süresi uzarsa, yani performans problemleri ortaya çıkarsa veri seti oluşturma sürecinin uzamasına ve verimsizleşmesine neden olur.

Keza, kullanıcı karşısında yani canlıda olan bir uygulama için de böylesi kötü bir performans kötü bir kullanıcı deneyimine sebep olur.

Varsayılan ayarlarda requests modülü oluşturduğu isteğe yanıt gelene kadar bekler. Bu nedenle gönderilen isteklere “timeout” yani zaman aşımı kuralı koymak performans açısından önemlidir. Bu işlem “timeout” parametresi ile gerçekleştirilir. timeout parametresi tam veya ondalık sayı değeri alır ve bu değer yanıt için kaç saniye beklenmesi gerektiğini temsil eder.

url = 'https://translate.yandex.net/api/v1.5/tr.json/translate'
requests.get(url, params = {key=API_KEY}, timeout = 1)
<Response [200]>

timeout parametresi aynı zamanda tuple veri tipinde değerleri de kabul eder. Bu veri tipinde girilen ilk değer, istemcinin sunucuya bağlanması için gereken maksimum süreyi, girilen ikinci değer ise yanıt gelmeden önce ne kadar saniye bekleneceğini temsil eder.

url = 'https://translate.yandex.net/api/v1.5/tr.json/translate'
requests.get(url, params = {key=API_KEY}, timeout = (2, 5))
<Response [200]>

Yani, yukarıdaki örneğe göre, gönderdiğimiz istek 2 saniye içerisinde sunucuya bağlanmalı ve en geç 5 saniye içerisinde bir yanıt döndürmelidir. Aksi takdirde, timeout hatası oluşur.

url = 'https://translate.yandex.net/api/v1.5/tr.json/translate'
requests.get(url, params = {key=API_KEY}, timeout = (0.0001, 5))
ConnectTimeout: HTTPSConnectionPool(host='api.github.com', port=443): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.VerifiedHTTPSConnection object at 0x10e7c4110>, 'Connection to api.github.com timed out. (connect timeout=0.001)'))

Timeout hatası oluşturmak için sunucuya bağlantı olması imkansız bir zaman seçtik ve sonrasında ConnectTimeout hatası ile karşılaştık. Try-except ile hata yakalayarak bu sorunu yönetebiliriz.

from requests.exceptions import Timeout

try:
    istek = requests.get('https://api.github.com', timeout=0.0001)
except Timeout:
    print('Zaman aşımı!')
else:
    print('Her şey yolunda!')
Zaman aşımı!
  • request kütüphanesinden timeout modülünü çağırdık.
  • try-except kalıbından “try” ile önce GET metodunu kullanarak bir istek yolladık.
  • Timeout olması durumunda “except” ile “Zaman aşımı!” uyarısını ekrana yazdırdık.
  • Timeout olmadığı durumlarda ise “Her şey yolunda!” mesajını ekrana yazdırdık.

Yanıt (Response)

Gönderilen her bir istek işlemin sonunda karşılık olarak, bir yanıt kodu ve eğer sorguya karşılık gereken bir veri varsa içerik getirir.

Yanıt/durum kodları

Yanıt kodları, gönderilen isteğin durumu ile ilgili bilgiler içerir. Gönderilen bir isteğin yanıt kodunu .status_code ile öğrenebiliriz.

Örnek olması açısından, Github API‘sine basit bir GET isteği yollayıp, yanıt koduna bakalım.

istek = requests.get("https://api.github.com")

istek.status_code
200

Gönderdiğimiz isteğin başarılı olduğunu belirten “200” yanıt kodunu aldık. Peki, yanlış bir endpoint’e istek gönderirsek ne olur?

istek = requests.get("https://api.github.com/boyle-bir-yer-yok")

istek.status_code
404

Bu sefer de isteği gönderdiğimiz adresin sunucuda olmadığını belirten “404” yanıt kodunu aldık.

En sık karşılaşılan HTTP yanıt kodlarını ve ne anlama geldiklerini şöyle özetleyebiliriz:

Yanıt koduAnlamı
200Eğer bir sonuç varsa, sonucun başarılı bir şekilde geri getirildiğini belirtir.
301Sunucu ilgili isteği farklı bir endpoint’e yönlendirmektedir. Alan adı değişikliklerinde görülür.
400Sunucu yanlış bir istek yolladığınızı düşünür.
401API kimlik bilgilerinin girilmediğini veya hatalı girildiğini belirtir.
403Erişilmek istenilen kaynağa erişmenizin yasak olduğunu belirtir.
404Erişmek istediğiniz noktanın sunucuda bulunmadığını belirtir.
503Sunucu isteğe yanıt vermek için hazır değildir.

HTTP yanıt/durum kodları karışık ve detaylı gelebilir. Basit bir kural tüm hata kodlarını şu şekilde kategorize edip daha kolay hatırlayabilirsiniz:

  • “2” ile başlayan yanıt kodları isteğin başarılı olduğunu,
  • “3” ile başlayan yanıt kodları isteğin gönderildiği adresin başka noktaya yönlendirme yaptığını,
  • “4” ile başlayan yanıt kodları isteğin gönderildiği adresin gönderici kaynaklı hatalı olduğunu,
  • “5” ile başlayan yanıt kodları ise isteğin sunucu tarafından karşılanamadığını, hata oluştuğunu belirtir.

Güncel ve ayrıntılı tüm HTTP yanıt/durum kodlarına buradan ulaşabilirsiniz.

Yanıt başlığı (headers)

Alınan yanıtın sunucu tarafından nasıl yorumlandığı istemciye yani kullanıcıya iletir.

istek = requests.get("https://api.github.com")
istek.headers
{'Server': 'GitHub.com', 'Date': 'Mon, 03 May 2021 13:08:10 GMT', 'Cache-Control': 'public, max-age=60, s-maxage=60', 'Vary': 'Accept, Accept-Encoding, Accept, X-Requested-With', 'ETag': '"27278c3efffccc4a7be1bf315653b901b14f2989b2c2600d7cc2e90a97ffbf60"', 'Access-Control-Expose-Headers': 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset', 'Access-Control-Allow-Origin': '*', 'Strict-Transport-Security': 'max-age=31536000; includeSubdomains; preload', 'X-Frame-Options': 'deny', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '0', 'Referrer-Policy': 'origin-when-cross-origin, strict-origin-when-cross-origin', 'Content-Security-Policy': "default-src 'none'", 'Content-Type': 'application/json; charset=utf-8', 'X-GitHub-Media-Type': 'github.v3; format=json', 'Content-Encoding': 'gzip', 'X-RateLimit-Limit': '60', 'X-RateLimit-Remaining': '53', 'X-RateLimit-Reset': '1620050296', 'X-RateLimit-Used': '7', 'Accept-Ranges': 'bytes', 'Content-Length': '496', 'X-GitHub-Request-Id': 'EB79:937C:6B4B2BB:6DF3AB4:608FF5BF'}

Buradaki detaylara baktığımızda, isteğin gönderildiği tarihi, hangi formatta olduğunu vs. görebiliyoruz.

İçerik

İsteğin başarılı bir şekilde iletildiği ve sorgunun karşılığında bir verinin olduğu durumlarda, ilgili veri sunucu tarafından yanıtta içerik olarak iletilir.

Çoğu API, verileri JSON (JavaScript Object Notation) formatında iletir. Aslında, JSON liste, dictionary ve string’lerin toplamı olan bir veri tipidir. Bir JSON verisini şu şekilde parçalarıyla gösterebiliriz:

requests kütüphanesinde bulunan .json() metodu ile gönderdiğimiz isteğin karşılığında elde edilen veriyi görüntüleyebiliriz.

istek = requests.get("https://api.github.com")
istek.json()
{'current_user_url': 'https://api.github.com/user',
 'current_user_authorizations_html_url': 'https://github.com/settings/connections/applications{/client_id}',
 'authorizations_url': 'https://api.github.com/authorizations',
 'code_search_url': 'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}',
 'commit_search_url': 'https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}',
 'emails_url': 'https://api.github.com/user/emails',
 'emojis_url': 'https://api.github.com/emojis',
 'events_url': 'https://api.github.com/events',
 'feeds_url': 'https://api.github.com/feeds',
 'followers_url': 'https://api.github.com/user/followers',
 'following_url': 'https://api.github.com/user/following{/target}',
 'gists_url': 'https://api.github.com/gists{/gist_id}',
 'hub_url': 'https://api.github.com/hub',
 'issue_search_url': 'https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}',
 'issues_url': 'https://api.github.com/issues',
 'keys_url': 'https://api.github.com/user/keys',
 'label_search_url': 'https://api.github.com/search/labels?q={query}&repository_id={repository_id}{&page,per_page}',
 'notifications_url': 'https://api.github.com/notifications',
 'organization_url': 'https://api.github.com/orgs/{org}',
 'organization_repositories_url': 'https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}',
 'organization_teams_url': 'https://api.github.com/orgs/{org}/teams',
 'public_gists_url': 'https://api.github.com/gists/public',
 'rate_limit_url': 'https://api.github.com/rate_limit',
 'repository_url': 'https://api.github.com/repos/{owner}/{repo}',
 'repository_search_url': 'https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}',
 'current_user_repositories_url': 'https://api.github.com/user/repos{?type,page,per_page,sort}',
 'starred_url': 'https://api.github.com/user/starred{/owner}{/repo}',
 'starred_gists_url': 'https://api.github.com/gists/starred',
 'user_url': 'https://api.github.com/users/{user}',
 'user_organizations_url': 'https://api.github.com/user/orgs',
 'user_repositories_url': 'https://api.github.com/users/{user}/repos{?type,page,per_page,sort}',
 'user_search_url': 'https://api.github.com/search/users?q={query}{&page,per_page,sort,order}'}

Python’da bulunan json paketi ile JSON tipindeki verileri kolaylıkla Python objelerine çevirebiliriz. json paketi Python’da bulunan standart kütüphanelerden biri olduğu için tekrardan yüklenmesine gerek yoktur. Sadece projeye çağırarak kullanılabilir. json paketinin temel olarak iki kullanışlı fonksiyonu vardır:

  1. json.dumps(): Bir Python objesini, JSON formatındaki bir stringe dönüştürür.
  2. json.loads(): Bir JSON stringini, Python objesine dönüştürür.

Uygulama: YouTube Data API

Yazının devamında YouTube Data API‘sini kullanarak veri çekeceğiz. YouTube Data API ile YouTube üzerindeki birçok farklı fonksiyona ve özelliğe erişmek mümkün. Bunlardan bazıları:

  • İçerik arama,
  • Çalma listelerini kontrol etme,
  • Video yükleme,
  • Kanal ayarlarını güncelleme.

Bu fonksiyonların yanı sıra YouTube üzerinde istediğiniz aramaları yapabilir, video ve kanallara yönelik izlenme istatistiklerini görüntüleyebilirsiniz.

YouTube Data API, günlük 10,000 isteğe kadar ücretsiz. Bu limit aşıldıktan sonra farklı özellikler için özelleştirilmiş bir fiyat tarifesi mevcut. Fiyatlandırma ile ilgili bilgilere buradan erişebilirsiniz.

Uygulama kapsamında, önce seçtiğimiz bir kanalın özel kanal numarasını bulup, daha sonrasında 2021 yılında yayınlanmış tüm videolarının video başlığı, açıklaması, video uzunluğu, yayın tarihi gibi bilgilerini çekeceğiz. Videolarla ilgili bu bilgileri edindikten sonra son olarak da izlenme, yorum ve beğeni sayısı gibi herkese açık istatistikleri listeleyeceğiz.

1. Adım: API dokümanının incelenmesi.

API ile ilgili herhangi bir aksiyon almadan önce Youtube Data API dokümantasyonuna göz atıp, dikkat etmemiz gereken kuralları not alacağız.

  • API’yi kullanabilmek için Developer Console‘dan API anahtarı elde etmemiz gerekli.
  • Her göndereceğimiz istekte mutlaka API anahtarı (API key) bulunmalı.
  • Dokümantasyonda kanaldan, kullanıcı bilgilerine dair birçok bilgiye erişmek mümkün. Bu yazının uygulamasında bir kanal seçip, ilgili kanaldaki videolarla ilgili halka açık bilgileri arayacağız. Bu sebeple dokümanın arama, kanal ve video sekmeleri ile devam ediyoruz.
  • Kanal ve videolarla ilgili insert, update gibi bazı manipülasyon işlemleri yapabiliriz. Fakat, bununla ilgilenmiyoruz. Videolarla ilgili bilgileri elde etmek istediğimiz için “list” fonksiyonuna odaklanacağız.
  • Yapacağımız her bir arama isteği 100 birim kullanım olarak maliyetlendirilirken, göndereceğimiz her bir listeleme isteği 1 birim maliyet olarak kullanım hesabımıza yansıyacak. 10,000 birim günlük ücretsiz bakiyemiz olduğunu tekrar hatırlatalım.

YouTube Data API kullanımı ile ilgili temel bilgileri edindik. Uygulamaya başlayabilmek için öncelikle API anahtarını elde etmemiz gerekiyor.

2. Adım: Kimlik bilgilerinin oluşturulması.

YouTube Data API kullanımı için öncelikle API kimlik bilgilerini oluşturmamız gereklidir. Sadece YouTube Data API için değil, kullanmak istediğiniz diğer çoğu API’ler için de ilk adım giriş bilgileri oluşturmaktır.

YouTube Data API kimlik bilgilerini elde etmek için ilk olarak bir Google hesabına ihtiyacınız vardır. Eğer bir Google hesabınız yoksa buradan oluşturabilirsiniz.

Hesap oluşturduktan veya hesabınıza giriş yaptıktan sonra Google Developer Console‘da yeni bir proje oluşturup API istekleri gönderebilmek için kimlik bilgilerini üretmemiz gerekir.

Sağ tarafta yer alan “Yeni proje oluştur (Create Project)” butonuna tıklanır.

Yeni açılan sayfada bir proje oluşturuyoruz. Bir proje çatısı oluşturduğumuz zaman, birden fazla API’yi bu proje içerisinde kullanabiliriz. Proje ismini ve organizasyon detayını girdikten sonra “Oluştur (Create)” seçeneğini tıklıyoruz.

Google, en çok API’ye sahip şirketlerden bir tanesi. Bir sonraki adımda bu proje için kullanmak istediğimiz uygun API’yi seçip, aktif hale getireceğiz. API kütüphanesine gidebilmek için panelde sol tarafta bulunan menüden “Kütüphane (Library)” seçeneği ile ilerliyoruz.

Google API Library‘de 300’den fazla, farklı işlevleri olan API bulunuyor. Bu yazıda YouTube Data API’yi kullanmak istiyoruz. Arama çubuğuna ilgili API’nin adını yazarak kolayca bulabiliriz.

Kullanmak istediğimiz API’yi bulduktan sonra aktifleştirmemiz gerekiyor. Bunun için de “Aktifleştir (Enable)” butonunu kullanıyoruz.

Kullanmak istediğimiz API’yi etkinleştirdik. Fakat hala bir giriş bilgisine sahip değiliz. Bunu elde etmek için API’nin detay sayfasında bulunan “Kimlik Oluştur (Create Credentials)” butonuna tıklıyoruz.

Bir sonraki açılan ekranda tekrardan kullanmak istediğimiz API’yi seçip, daha sonrasında da ne tür bir veriye erişeceğimizin bilgisini gireceğiz.

YouTube Data API yardımı ile videolara dair herkese açık izlenme sayısı, yorum sayısı vs. gibi bilgilere ulaşabileceğimiz gibi, ilgili YouTube kanal sahibinin özel izniyle daha hassas bilgilere yani kullanıcı verilerine de erişebiliriz. Fakat bunun için kanal sahibinin onayı gerekmektedir. Kişisel verilerin korunmasına yönelik bu küçük fark, elde edeceğimiz kimlik bilgimizi değiştirecek ve bizi toplayacağımız kişisel veriler hakkında sorumlu tutacaktır.

Bu uygulama kapsamında herkese açık (public) verilere erişmek istiyoruz. Bu nedenle ikinci seçenek ile ilerledik.

Gerekli bilgileri girdikten sonra API kimliğimiz (API Key) oluşturuldu. Bu API Key’i YouTube Data API için TC kimlik numaranız gibi düşünebilirsiniz. Nasıl ki kendi kimlik numaranızı, adınıza sahte şirket kurulmaması, suça karışılmaması için üçüncü kişilerle paylaşmıyorsanız, API Key’inizi de kullanıcıya özel olduğu için başkalarıyla paylaşmamanızı öneririm.

3. Adım: Seçilen kanalın YouTube’da aranması ve ilk istek gönderimi.

Uygulamaya başlamadan önce, uygulama sırasında kullanacağımız kütüphaneleri proje dosyamıza çağırarak başlayalım.

Veri manipülasyonu için Pandas, veri görselleştirme için Matplotlib ve Seaborn, HTTP bağlantıları oluşturmak için requests ve son olarak da kompleks metinleri manipüle edebilmek için re modüllerini çağıracağız.

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import requests
import re

Öncelikle bir adet YouTube kanalı seçip, bu kanalı YouTube’da aratarak, kanala dair ID bilgisini bulacağız. Bu ID bilgisi, kanalda yayınlanmış videoları ararken işimize yarayacak.

YouTube kanalını aktif olarak kullanan markalardan biri Red Bull. Bu uygulama için Red Bull’un global YouTube kanalını kullanmak istiyorum. Dilerseniz başka bir kanal ile ilerleyebilirsiniz. İlgili kanalı YouTube’da aratmak için bir fonksiyona ihtiyacımız var.

def yt_channel_search(channel_name):
    api_key = "YOUR_API_KEY"
    url = "https://www.googleapis.com/youtube/v3/search"
    
    parameters = {   
    "part": "snippet",
    "q": channel_name,
    "key": api_key,
    "type": "channel",
    "maxResults": 10,
    "order": "videoCount"}
    
    channel_resp = requests.get(url, params = parameters)
    
    return channel_resp.json()

channel_request = yt_channel_search("Red Bull")
  • yt_channel_search adında bir fonksiyon oluşturduk. Bu fonksiyon parametre olarak aratmak istediğimiz kanal adını kullanıyor.
  • İlgili fonksiyon yukarıda adım adım anlatımdaki gibi oluşturduğumuz API anahtarını ve girdiğimiz parametreleri kullanarak bir GET isteği yollayıp, gelen yanıtı ise JSON objesi olarak döndürüyor.
  • Kullandığımız parametreleri ve hangi değerleri alabileceğini koda dökerken API dokümanında bulunan Search sayfasından yararlandık. Kullandığımız parametreler:
    • part: kaynaktan hangi tarz bilgilere erişebileceğimizi belirtir.
    • q: arama için kullanılacak metni ifade eder.
    • key: API anahtarı
    • type: Dönecek sonuçların video, kanal veya çalma listesi mi olacağına yönelik filtredir.
    • maxResults: Sorgu sonucunda en fazla kaç adet sonuç döneceğini belirtir.
    • order: Dönen sonuçların neye göre sıralanacağını belirler.
  • Daha sonrasında requests kütüphanesindeki GET metodu ile yukarıda bahsi geçen sorgu adresine, parametreleri kullanarak istek gönderdik.
  • Son olarak istek sonucunda gelen yanıtı json() formatında geri döndürdük.

Oluşturduğumuz fonksiyonu “Red Bull” sorgusu ile çalıştırdık ve gelen yanıtı channel_request adında bir değişkene sakladık. Aşağıdaki gibi uzun uzadıya devam eden, JSON formatında bir veriye sahibiz.

{'kind': 'youtube#searchListResponse',
 'etag': '1lBWDunVboKLnhgTbKnbmAM6uJc',
 'nextPageToken': 'CAoQAA',
 'regionCode': 'TR',
 'pageInfo': {'totalResults': 12637, 'resultsPerPage': 10},
 'items': [{'kind': 'youtube#searchResult',
   'etag': 'sqlrV8SrMv0pAe1hywyh0pc4HPo',
   'id': {'kind': 'youtube#channel', 'channelId': 'UCblfuW_4rakIf2h6aqANefA'},
   'snippet': {'publishedAt': '2006-09-23T03:44:21Z',
    'channelId': 'UCblfuW_4rakIf2h6aqANefA',
    'title': 'Red Bull',
    'description': 'Experience the world of Red Bull like you have never seen it before, with the best action sports clips and original series on YouTube. Watch highlights from sport ...',
    'thumbnails': {'default': {'url': 'https://yt3.ggpht.com/ytc/AAUvwni4FH17wMEF_FdQMM0PI4i09nM4dUjU4n5QtwFRQQ=s88-c-k-c0xffffffff-no-rj-mo'},
     'medium': {'url': 'https://yt3.ggpht.com/ytc/AAUvwni4FH17wMEF_FdQMM0PI4i09nM4dUjU4n5QtwFRQQ=s240-c-k-c0xffffffff-no-rj-mo'},
     'high': {'url': 'https://yt3.ggpht.com/ytc/AAUvwni4FH17wMEF_FdQMM0PI4i09nM4dUjU4n5QtwFRQQ=s800-c-k-c0xffffffff-no-rj-mo'}},
    'channelTitle': 'Red Bull',
    'liveBroadcastContent': 'upcoming',
    'publishTime': '2006-09-23T03:44:21Z'}},

İlk sonuç için gelen bilgilere baktığımızda, kanalın 2006 yılında açılmış olduğunu, kanal isminin Red Bull olduğunu ve kanal açıklaması ile kanal görselinin aradığımız Red Bull kanalı ile aynı olduğunu görüyoruz. Bu sonuçta bununan kanal ID’sini alacağız. JSON formatındaki veri iç içe geçmiş dictionary ve liste gibi veri tiplerinden oluşmuştur. Bu Dıştan içe doğru, istediğimiz noktaya inene kadar döngüleri kullanacağız.

JSON formatındaki veriyi okumakta zorlanabilirsiniz. İnternette birçok ücretsiz JSON format düzenleyicisi vardır. Bunlardan birini kullanarak elinizdeki veriyi daha kolay okunabilir bir şekilde görebilirsiniz. Bu şekilde döngüleri nereden başlayıp, nereden ilerleteceğinize dair daha hızlı karar verebilirsiniz.

for result in channel_request["items"]:
    for k, v in result["snippet"].items(): 
        if (k == "title") and (v == "Red Bull"):
            channelId = result["snippet"]["channelId"]

print(channelId)
UCblfuW_4rakIf2h6aqANefA
  • İç içe for döngüleri kullanarak, dış katmandan içeriye doğru ilerledik. Öncelikle “items” noktasından, “snippet” alt katmanına indik.
  • Alt katmanda bulunan dictionaryde anahtarı “title” ve değeri “Red Bull” olan bölüme ulaştığımızda channelID değerini yeni bir değişkene atadık.

4. Adım: Seçilen kanalın videolarının listelenmesi.

Red Bull’un kanal kimliğine ulaştık. Şimdi sırada bu değeri kullanarak, 2021 yılında bu kanaldan yayınlanmış videolara dair verileri toplayacağız.

İlgili aramayı yapabilmek için yeni bir fonksiyon oluşturacağız. Bu yeni fonksiyon temel olarak bir önceki ile neredeyse aynı olacak. Fonksiyonda kullanılan parametrede ve gönderilecek GET isteğindeki parametrelerde farklılıklar yapacağız.

def get_videos(channelId):
    api_key = "YOUR_API_KEY"
    url = "https://www.googleapis.com/youtube/v3/search"
    
    parameters = {   
    "part": "snippet",
    "channelId": channelId,
    "key": api_key,
    "order": "date",
    "type": "video",
    "publishedAfter": "2021-01-01T00:00:00Z",
    "maxResults": "50"

    }
    
    video_resp = requests.get(url, params = parameters)
    
    return video_resp.json()

recent_videos = get_videos(channelId)
  • Yeni fonksiyonda arama yaparken bir önceki adımda bulduğumuz kanal kimliğini parametre olarak kullandık.
  • İstek parametrelerinde yaptığımız değişikliklerle, yanıtta dönecek sonuçların “video” olmasını (kanal veya çalma listesi görmemek için) ve 1 Ocak 2021’den sonra yayınlanmış olmasını belirttik.
  • Bir arama sırasında elde edebileceğimiz maksimum sonuç sayısını maxResults parametresi ile 50 adete kadar arttırabiliriz. Özel bir değer girilmediği durumlarda, arama sonunda dönecek varsayılan sonuç sayısı 5’tir.
  • 50’den fazla sonuç elde edebilmek için “nextPageToken” veya “prevPageToken” parametreleri kullanılmalıdır.

Arama sonucunda gelen yanıtı JSON formatında recent_videos değişkenine kaydettik. Kanal kimliğini bulduğumuz aşamadaki gibi JSON formatındaki veriden istediğimiz ilgili verileri çıkarmalıyız. Süreci kolaylaştırmak için yeni bir fonksiyon oluşturup, bu fonksiyonu kullanarak verileri yeni değişkenlere saklayacağız.

def data_extractor(raw_data, first_loop, second_loop, col_name):
    ext_data = [v for result in raw_data[first_loop] \
                for k, v in result[second_loop].items() \
                if k == col_name]
    
    return ext_data


video_id = data_extractor(recent_videos, "items", "id", "videoId")
publish_date = data_extractor(recent_videos, "items", "snippet", "publishedAt")
title = data_extractor(recent_videos, "items", "snippet", "title")
desc = data_extractor(recent_videos, "items", "snippet", "description")
  • data_extractor adında bir fonksiyon oluşturduk. Bu fonksiyon, JSON formatındaki ham veri kaynağını, dışarıdan içeriye doğru döngüler ile geçilecek ilk ve ikinci dönüm noktalarını ve finalde ulaşıldığında çıkarılacak veri noktasını parametre olarak kullanmaktadır.
  • Oluşturduğumuz fonksiyonda kullandığımız dönüm noktalarını yine yukarıdaki gibi JSON format düzenleyicisinde daha rahat gözlemleyebilirsiniz.

Formatlanmış bir görüntü üzerinden dönüm noktalarını kolaylıkla belirleyebilirsiniz.

5. Adım: Seçilen videoların istatistiklerinin elde edilmesi.

Bir önceki adımda videolara dair video kimlik numarasını, yayınlanma tarihini, video adını ve açıklamalarını ayrı ayrı değişkenlere sakladık. Bu bilgileri API tarafından “part” parametresinde sunulan “snippet” özelliğini kullanarak, “search” yani sorgu adresinden elde ettik.

Videolara dair istatistiklere erişmek için yine “part” parametresinde bulunan “statistics”, videoların sürelerini ise “contentDetails” özelliğini kullanarak “videos” adı verilen farklı bir sorgu adresinden elde edeceğiz.

İstek sırasındaki bazı farklılıklardan dolayı, bir önceki adımlardakine çok benzer bir fonksiyon oluşturacağız.

def get_video_stats(videoId, resource):
    api_key = "YOUR_API_KEY"
    url = "https://www.googleapis.com/youtube/v3/videos"
    
    parameters = {   
    "part": resource,
    "id": videoId,
    "key": api_key,
    "maxResults": "50"
    }
    
    video_stats_resp = requests.get(url, params = parameters)
    
    return video_stats_resp.json()

video_stats = get_video_stats(video_id, "statistics")
video_content_details = get_video_stats(video_id, "contentDetails")
  • Yeni oluşturduğumuz fonksiyonda parametre olarak, bir önceki adımda elde ettiğimiz video kimlik numaralarını ve farklı tip verileri elde etmemize imkan sağlayan özellik isimlerini parametre olarak kullandık.
  • Daha sonrasında hem istatistikleri hem de video sürelerini iki farklı değişkene kaydettik.

Bir önceki adımdaki gibi ham veri kaynağından istediğimiz veriyi çıkarmak zorundayız. Bunu yapabilmek için bir önceki adımda oluşturduğumuz data_extractor fonksiyonunu kullanacağız.

video_views = data_extractor(video_stats, "items", "statistics", "viewCount")
likes = data_extractor(video_stats, "items", "statistics", "likeCount")
dislikes = data_extractor(video_stats, "items", "statistics", "dislikeCount")
favs = data_extractor(video_stats, "items", "statistics", "favoriteCount")
comments = data_extractor(video_stats, "items", "statistics", "commentCount")
duration = data_extractor(video_content_details, "items", "contentDetails", "duration")

Kullandığımız dönüm noktalarını, elde ettiğimiz JSON verisini inceleyerek, çıkarmak istediğimiz final veriyi düşünerek karar verdik.

6. Adım: Tüm verilerin DataFrame ile birleştirilmesi.

Farklı farklı kaynakları ve sorgu adreslerini kullanarak yaklaşık istediğimiz verileri 6-7 değişkende topladık. Son veri manipülasyonu adımında dağınık olarak duran bu değişkenleri bir Pandas DataFramede birleştirip, Excel’e çıktı alabilecek şekilde hazır hale getireceğiz.

lst = zip(video_id, publish_date, title, desc, \
          video_views, likes, dislikes,  \
          favs, comments, duration)

redbull_yt = pd.DataFrame(lst, \
                          columns = ["video_id", "publish_date", "title", "desc",  
                                          "video_views", "likes", "dislikes",  \
                                          "favs", "comments", "duration"])

redbull_yt.head()
  • İlk olarak dağınık listeler halinde duran değişkenleri zip() fonksiyonu ile tek bir liste haline getirecek şekilde birleştirdik.
  • Daha sonrasında pd.DataFrame yapısını kullanarak birleştirdiğimiz listeyi, kolon isimlerini de güncelleyerek DataFrame olarak birleştirdik.
  • İlgili DataFramedeki ilk 5 kayıtı head() fonksiyonu ile görüntüledik.

Tabloyu görüntülediğimizde dikkat çeken noktalardan bir tanesi video süresinin formatı. Saat, dakika ve saniye cinsinden karmaşık olarak verilen bu değerler analiz sırasında zorluk çıkaracaktır. Bir fonksiyon yardımıyla buradaki karmaşık veriyi saniye cinsinden uzunluk birimine çevirelim.

def duration_secs(val):
    """Calculates video duration in seconds"""
    
    if re.findall("\d*H", val) == []:
        hour = 0
    else:
        hour = int(re.findall("\d*H", val)[0][:-1])
    
    mins = int(re.findall("\d*M", val)[0][:-1])
    secs = int(re.findall("\d*S", val)[0][:-1])
    
    duration = (hour * 60 * 60) + (mins * 60) + secs
    
    return duration

redbull_yt["duration_secs"] = redbull_yt["duration"].apply(duration_secs)
  • duration_secs fonksiyonu, aldığı değeri saat, dakika ve saniye cinsinden ayırarak saniye cinsinden bir değer üretir.
  • Değişkende bulunan değerlerde, saat içeren rakamlar “H”, dakika içeren rakamlar “M” ve saniye içeren rakamlar ise “S” harfi ile biter. Fonksiyon, Regex’i kullanarak ilgili rakamları hour, mins, secs isimli farklı değişkenlere kayıt eder.
  • En sonunda da dönüşüm işlemini gerçekleştirerek duration isimli bir değişkene kayıt eder.

Oluşturduğumuz fonksiyonu apply() metodunu kullanarak tabloda bulunan “duration” kolonuna uyguladık.

Veri setini çıktı olarak almadan önce son olarak değişkenlerin veri tiplerini kontrol edelim.

redbull_yt.dtypes
video_id         object
publish_date     object
title            object
desc             object
video_views      object
likes            object
dislikes         object
favs             object
comments         object
duration         object
duration_secs     int64
dtype: object

Değişkenleri incelediğimizde, tam sayı değerlere sahip video_views, likes, dislikes ve tarihsel değerlere sahip publish_date gibi değişkenlerin metin yani string olarak saklandığını görüyoruz. Bu değişkenlerle işlemler yapabilmek için uygun veri tipine dönüşüm sağlamalıyız.

Öncelikle tam sayı içeren değişkenlerden başlayalım.

ints = ["video_views", "likes", "dislikes", "favs", "comments"]

for i in ints:
    redbull_yt[i] = redbull_yt[i].astype("int")
  • Dönüşüm yapacağımız değişken isimlerini “ints” adı verilen yeni bir listeye aldık.
  • 5 farklı değişkene aynı işlemi uygulayacağımız için bir for döngüsü kullandık. Bu döngü ile aynı işlemi farklı değişkenler için uyguladık.
  • Dönüşüm işlemi için “astype” fonksiyonunu kullandık.
  • Değişkenler tam sayı değerlere sahip olduğu için veri tipini integer, yani “int” olarak değiştirdik.

Sırada, tarih değerlerine sahip “publish_date” değişkeni var. YouTube Data API’den elde ettiğimiz tarih değerleri ISO 8601 formatında tutulur. Bu formatı bir örnek üzerinden şöyle gösterebiliriz:

Format: YYYY-MM-DDThh:mm:ss.nnn±hh:mm
Örnek: 2016-08-25T15:23:22.635-07:00

Tarih değerleriyle kolayca işlem yapabilmek için ISO 8601’den datetime formatına çevireceğiz.

from datetime import datetime

redbull_yt["publish_date"] = pd.to_datetime(redbull_yt["publish_date"])

redbull_yt["publish_date"].head()
0   2021-05-03 12:12:14+00:00
1   2021-04-30 12:15:55+00:00
2   2021-04-26 12:00:34+00:00
3   2021-04-23 12:00:32+00:00
4   2021-04-16 12:00:14+00:00
  • Python’da tarih verileri ile çalışmak için geliştirilen datetime kütüphanesindeki datetime modülünü çağırdık.
  • Daha sonrasında pd.to_datetime() metodu ile gerekli dönüşümü yaptık.

Dönüşüm işleminin başarılı olup olmadığını test etmek için ilgili değişkenin veri tipini sorgulayalım.

redbull_yt["publish_date"].dtypes
datetime64[ns, UTC]

Dönüşüm işlemlerini tamamlandı. Dilerseniz bu adımdan sonra ilgili veriyi Excel veya CSV formatında indirebilirsiniz.

#Excel
redbull_yt.to_excel("redbull.xlsx")

#CSV
redbull_yt.to_csv("redbull.csv")

7. Adım: Veri setine dair basit açıklayıcı istatistikler.

Uygulamayı tamamlamadan önce elimizdeki veri seti ile akla gelebilecek bazı temel soruların cevaplarına bakalım.

2021 yılında en çok video hangi ayda yayınlandı?

Elimizdeki veri setindeki videolar 1 Ocak – 4 Mayıs 2021 tarihindeki dönemi kapsamaktadır. Öncelikle bu dönem kaç adet video yayınlandığını bulalım.

len(redbull_yt["video_id"])
43

Belirtilen tarihler arasında kaç adet video yayınlandığını bulmak için tablomuzda bulunan değişkenlerden herhangi birinin uzunluğunu saydık. Yukarıdaki tarihler arasında 43 adet video yayınlandığını görüyoruz. Peki bu videoların aylık dağılımı ne?

Bu soruyu cevaplamak için elimizdeki veriyi aylara göre gruplayıp, her ay yayınlanan video rakamını saydıracağız. Daha sonrasında da bu yeni tabloyu bir sütun grafiği ile görselleştireceğiz.

video_count_by_month = redbull_yt["video_id"].groupby(redbull_yt["publish_date"].dt.month).count().reset_index()
   publish_date	video_id
0	1	10
1	2	12
2	3	11
3	4	9
4	5	1
  • Ana tablodaki “video_id” değişkenini aylık rakama göre groupby() fonksiyonu ile grupladık.
  • Her ay kaç adet video yayınlandığını bulmak için count() fonksiyonu kullanarak sayma işlemini yaptık.
  • Elimizdeki veriyi bir DataFrame olarak tutabilmek için reset_index() fonksiyonu ile sıfırdan bir indeks yarattık ve bu sayede publish_date ve video_id adında iki değişkene sahip küçük bir DataFrame oluşturduk.

Sorunun cevabını bu tablo ile de verebiliriz. En çok video 2. ayda yani Şubat ayında (12 video) yayınlandı. Bu tabloyu bir sütun grafiği ile göze hoş gelecek şekilde görselleştirelim.

fig, ax = plt.subplots(figsize = (20, 10))

ax = sns.barplot(x = "publish_date", y = "video_id", data = video_count_by_month, palette = "hls") 
ax.set_xticklabels(["Ocak", "Şubat", "Mart", "Nisan", "Mayıs"])
ax.set_title("Aylık Video Sayısı")
ax.set_xlabel("Ay")
ax.set_ylabel("Video sayısı")


plt.show()
  • İlk adımda 20 birime 10 birimlik bir çerçeve ve çerçeveye özel alan (ax) oluşturduk.
  • Seaborn kütüphanesinin barplot fonksiyonunu kullanarak ilgili alana sütun grafiğini çizdirdik. Barplot fonksiyonuna:
    • Yatay düzlemde (x) görünmesi için ayların bulunduğu değişkeni,
    • Dikey düzlemde (y) görünmesi için video sayısının bulunduğu değişkeni,
    • Yukarıdaki değişkenleri alacağı veri kaynağı olarak da (data) oluşturduğumuz tabloyu parametre olarak girdik.
    • palette parametresi ile de göze hoş gelecek özel bir renk paleti belirledik. Seaborn kütüphanesindeki farklı renk paletlerine bu linkten ulaşabilirsiniz.
  • Çizdiğimiz sütun grafiğinin kalitesini artırmak için:
    • Yatay eksende bulunan değerleri set_xticklabels fonksiyonunu kullanarak ay isimleri ile güncelledik.
    • set_xlabel ve set_ylabel fonksiyonunu kullanarak yatay ve dikey eksendeki değişkenlerin isimlerini güncelledik.
    • set_title fonksiyonunu kullanarak da çizdirdiğimiz grafiği betimleyen bir başlık oluşturduk.

2021 yılında RedBull toplam ne kadar izlenme elde etti?

2021 yılında yayınlanan 43 videodan toplam izlenme sayısını elde etmek için “video_views” değişkeninde bulunan değerleri toplayacağız. İşlemi yaparken sum() fonksiyonunu kullanacağız.

redbull_yt["video_views"].sum()
19860938

43 videodan belirtilen tarihler arasında toplam 19,860,938 izlenme elde edildi.

2021 yılında bir video ortalama olarak ne kadar izlendi?

Ortalama video süresini bulmak için yine “video_views” değişkenini kullanacağız. Ortalama değerini hesaplamak için mean() fonksiyonunu kullanacağız.

redbull_yt["video_views"].mean()
461882.27906976745

Bir videonun ortalama izlenme sayısı 461,882 olarak hesaplandı. Peki bu değer veri setini gerçekten yansıtıyor mu?

Ortalama değeri veri setinde bulunan aykırı değerlerden etkilenir. Bu ölçü biriminin normal dağılan değişkenlerini daha iyi temsil ettiğini biliyoruz. “video_views” değişkeni normal dağılıma sahip midir?

plt.hist(redbull_yt["video_views"])
plt.show()

Sorunun cevabını bulmak için hızlıca bir histogram çizdik. Görselde verinin sol tarafında bir yoğunluk görünüyor. Bu da verinin sağa yatık bir dağılıma sahip olduğunu ve aykırı değerlere sahip olduğunu gösteriyor. Bu durumda medyan (ortanca) değeri veri setini ortalamadan daha iyi temsil edecektir. Medyan değerini hesaplamak için median() fonksiyonunu kullanacağız.

redbull_yt["video_views"].median()
243238.0

Hesaplamalara göre medyan değeri 243,238‘dir.

2021 yılında en çok beğeni alan video hangisidir?

Listedeki 43 video arasında en çok beğeni alan videoyu bulmak için bir filtreye ihtiyacımız var. Beğeni sayısı maksimum değere eşit olan satırı arıyoruz.

cond = redbull_yt["likes"] == redbull_yt["likes"].max()

redbull_yt[cond]["likes"]
redbull_yt[cond]["video_id"]
26096
ZDgM3BN4I5U

En çok beğeni alan videoyu filtrelemek için bir koşul yarattık. Yarattığımız koşulda aradığımız satırın “likes” değişkenindeki en yüksek değere sahip olmasını istediğimizi belirttik.

Daha sonrasında Pandas’ın filtreleme syntaxını kullanarak önce like sayısını daha sonrasında ilgili videonun kimlik bilgisini aldık. 26,096 beğeni alan Max Verstappen ile ilgili videonun en çok beğeni alan video olduğunu bulduk.

Not: Herhangi bir video ID değerini “youtube.com/watch?v=VIDEO_ID_NO”, linkinde bulunan “VIDEO_ID_NO” alanına ekleyip tarayıcınızda açtığınızda ilgili videoyu YouTube üzerinde görüntüleyebilirsiniz.

Video süresi ile izlenme sayısı arasında bir ilişki var mıdır?

Video süresi ile izlenme sayısı arasında bir ilişki olup olmadığını anlamak için saçılım grafiğine (scatterplot)ihtiyacımız vardır. Saçılım grafiğinde eğer iki değişken arasında bir ilişki var ise noktalar birlikte artıp veya azalırken, ilişki olmadığı durumlarda ise birbirinden bağımsız ve alakasız şekilde dağılır.

Seaborn kütüphanesinden scatterplot() fonksiyonunu kullanarak grafiği çizdirelim.

fig, ax = plt.subplots(figsize = (10, 8))
ax = sns.scatterplot(data=redbull_yt, x="duration_secs", y="video_views")
ax.set_title("Video Uzunluğu vs İzlenme Sayısı")
ax.set_xlabel("Video Uzunluğu")
ax.set_ylabel("İzlenme sayısı")


plt.show()
  • Sütun grafiğinde olduğu gibi öncelikle bir çerçeve ve alan belirledik.
  • Daha sonrasında scatterplot fonksiyonu ile ilgili değişkenleri parametre olarak girdik.
    • Dikey eksene (x), açıklayıcı değişkeni* girdik.
    • Yatay eksene (y), yanıt değişkenini** girdik.
  • Son olarak grafiği güzelleştirmek için yatay ve dikey eksendeki isimleri güncelleyip, grafiğe başlık ekledik.

*Yanıt değişken: Çalışmamızda hakkında soru sorduğumuz belirli bir niceliktir.
**Açıklayıcı değişken: Yanıt değişkenini etkileyebilecek herhangi bir faktördür.

Grafikte gözlem noktalarının birlikte hareket etmediği yorumunda bulunabiliriz. Bu sonuçlara göre iki değişken arasında bir ilişki bulunmamaktadır.

Kaynakça

Python Requests
YouTube Data API Doc