Web'den Veri Çekmek: requests ve HTTP İstekleri

Bir önceki derste (5/8) openpyxl ile Excel dosyalarını Python üzerinden okuyup yazmayı, satır satır veri işlemeyi öğrenmiştik. Artık verinin sadece bilgisayarımızdaki dosyalarda değil, internetteki web sayfalarında ve web servislerinde de bulunabileceğini biliyoruz. Bu derste verinin kaynağını değiştiriyoruz: dosya sisteminden internete geçiyoruz. Bir sonraki derste (7/8) burada öğrendiğimiz HTTP isteklerinin sonucunda gelen HTML içeriğini BeautifulSoup ile ayrıştırıp istediğimiz bilgiyi (başlık, fiyat, tarih gibi) süzmeyi göreceğiz. Bu yüzden bu ders, web kazımanın (web scraping) temel taşı olan “veriye nasıl ulaşırım” sorusuna cevap verir.

Bu derste ne yapacağız?

Amacımız, Python'dan bir web sunucusuna HTTP isteği göndermeyi, sunucunun döndürdüğü yanıtı (response) okumayı, yanıt kodunu (status code) kontrol etmeyi ve gelen veriyi hem düz metin (HTML) hem de yapılandırılmış (JSON) biçimde almayı öğrenmektir. Ders sonunda kendi başınıza bir web adresine istek gönderip sonucu ekrana yazdırabilecek, hataları fark edip yönetebilecek düzeye geleceksiniz.

Ön koşul: Python'da değişkenler, koşul ifadeleri (if/else), fonksiyon çağırma ve önceki derslerde gördüğümüz kütüphane kurma (pip ile paket yükleme) bilgisine sahip olmanız beklenir. Ayrıca internet bağlantınızın olması gerekir, çünkü bu derste gerçek bir web sunucusuna istek göndereceğiz.

Kavram

Web tarayıcınızda bir adres yazıp Enter'a bastığınızda aslında arka planda şu olur: tarayıcınız o adresteki sunucuya “bana bu sayfayı gönder” diye bir istek (request) yollar, sunucu da “işte sayfan” diyerek bir yanıt (response) döndürür. Bu iletişim kuralına HTTP (HyperText Transfer Protocol) denir. Bunu bir restoranda garsona sipariş vermeye benzetebiliriz: siz (istemci/client) garsona (sunucu/server) “bana şu yemeği getir” dersiniz (istek), garson da mutfaktan yemeği getirir ya da “o yemek bitti” diye haber verir (yanıt). Python'da bu garson-müşteri ilişkisini kurmamızı sağlayan araç, requests adlı kütüphanedir. Biz tarayıcı yerine Python kodu kullanarak aynı isteği gönderiyoruz, sadece sonucu ekranda görsel olarak değil, metin veya veri olarak alıyoruz.

Sunucudan gelen yanıtın bir de “durum kodu” (status code) vardır. Bu, garsonun size verdiği kısa bir işaret gibidir: “200” kodu “her şey yolunda, işte istediğin” demektir; “404” kodu “aradığın şey burada yok” anlamına gelir; “500” kodu ise “mutfakta bir sorun var, bizim hatamız” demektir. Kodumuzun bu kodları kontrol etmesi, gelen verinin güvenilir olup olmadığını anlamamız için önemlidir.

Adım adım uygulama

  1. Önce requests kütüphanesinin kurulu olup olmadığını kontrol edelim. Komut satırını (Windows'ta PowerShell veya Komut İstemi) açın ve şunu yazın:

    pip install requests

    Bu komut, requests kütüphanesini bilgisayarınıza indirir. Zaten kuruluysa “requirement already satisfied” benzeri bir mesaj görürsünüz, bu normaldir.

  2. Yeni bir Python dosyası oluşturun, örneğin web_istek.py adıyla kaydedin. İlk satırda kütüphaneyi içe aktaralım:

    import requests

    Bu satır, requests kütüphanesindeki tüm araçları kodumuzda kullanılabilir hâle getirir.

  3. Basit bir GET isteği gönderelim. GET, sunucudan veri “almak” istediğimizde kullandığımız istek türüdür (tarayıcıda bir sayfa açmakla aynı mantık):

    yanit = requests.get("https://httpbin.org/get")
    print(yanit.status_code)

    Burada requests.get(...) belirtilen adrese bir istek gönderir ve sonucu yanit değişkenine kaydeder. yanit.status_code ise sunucunun döndürdüğü durum kodunu (başarılıysa 200) ekrana yazdırır. httpbin.org, deneme amaçlı isteklerin test edilmesi için hazırlanmış açık bir servistir; öğrenirken güvenle kullanabilirsiniz.

  4. Yanıtın içeriğini (gövdesini, yani gerçek veriyi) görüntüleyelim:

    print(yanit.text)

    yanit.text, sunucudan gelen ham içeriği düz metin (string) olarak verir. Eğer sunucu bir HTML sayfası döndürdüyse, burada HTML etiketlerini (<html>, <body> gibi) görürsünüz.

  5. Birçok web servisi veriyi JSON biçiminde döndürür – bu, Python'daki sözlük (dictionary) yapısına çok benzeyen, anahtar-değer çiftlerinden oluşan bir veri formatıdır. requests, JSON yanıtını doğrudan Python sözlüğüne çevirebilir:

    veri = yanit.json()
    print(veri["url"])

    yanit.json() metodu, gelen metni otomatik olarak bir Python sözlüğüne dönüştürür. Ardından normal sözlük erişimi gibi veri["url"] yazarak içindeki belirli bir alana ulaşabiliriz.

  6. Gerçek hayatta her istek başarılı olmaz. Bu yüzden durum kodunu kontrol etmek iyi bir alışkanlıktır:

    if yanit.status_code == 200:
        print("İstek başarılı!")
    else:
        print("Bir sorun oluştu, kod:", yanit.status_code)

    Bu blok, sunucunun 200 (başarılı) kodu döndürüp döndürmediğini kontrol eder ve duruma göre farklı bir mesaj yazdırır. Böylece programımız sessizce çökmek yerine, ne olduğunu bize anlatır.

  7. Bağlantı sorunlarına karşı da önlem alalım. İnternet kesilirse ya da sunucu yanıt vermezse programın çökmemesi için try/except kullanabiliriz:

    try:
        yanit = requests.get("https://httpbin.org/get", timeout=5)
        yanit.raise_for_status()
        print("Veri geldi:", yanit.status_code)
    except requests.exceptions.RequestException as hata:
        print("İstek sırasında hata oluştu:", hata)

    timeout=5, sunucu 5 saniye içinde yanıt vermezse beklemeyi durdurup hata fırlatmamızı sağlar. raise_for_status(), durum kodu 400 veya üzeri (yani bir hata kodu) ise otomatik olarak bir istisna (exception) oluşturur. except bloğu ise bu hataları yakalayıp programın çökmesini engeller, bunun yerine anlaşılır bir mesaj gösterir.

Sık karşılaşılan sorunlar

Hata / BelirtiOlası NedenÇözüm
ModuleNotFoundError: No module named 'requests'Kütüphane bilgisayarınıza kurulmamışKomut satırında pip install requests komutunu çalıştırın
Program uzun süre takılı kalıyor, yanıt gelmiyortimeout parametresi belirtilmemiş, sunucu yanıt vermiyorİsteğe timeout=5 gibi bir süre sınırı ekleyin
status_code 404 dönüyorYazılan adres (URL) yanlış veya sayfa artık mevcut değilAdresi tarayıcıda açıp doğruluğunu kontrol edin
status_code 403 veya 401 dönüyorSunucu isteğinizi bir bot olarak görüp reddediyor ya da giriş/izin gerekiyorBazı siteler otomatik istekleri engeller; eğitim amaçlı httpbin.org gibi açık servisleri tercih edin
yanit.json() çalıştırıldığında hata veriyorSunucu JSON değil, HTML veya başka bir format döndürmüşÖnce yanit.text ile içeriğe bakıp gerçekten JSON olup olmadığını kontrol edin
SSLError veya bağlantı hatasıİnternet bağlantısı yok ya da güvenlik sertifikası sorunu varİnternet bağlantınızı kontrol edin; şirket ağı/VPN kullanıyorsanız ağ yöneticinize danışın

Mini görev

Kendi başınıza şu görevi tamamlayın: https://httpbin.org/json adresine bir GET isteği gönderin, gelen yanıtın durum kodunu ekrana yazdırın, ardından yanıtı JSON olarak alıp içindeki “slideshow” anahtarının altındaki “title” değerini ekrana yazdırın. İsteği try/except ile hatalara karşı koruyun ve timeout parametresi ekleyin.

  • Kütüphaneyi doğru şekilde içe aktardınız mı? (import requests)
  • İstek için timeout değeri belirlediniz mi?
  • Durum kodunu kontrol edip ekrana yazdırdınız mı?
  • Yanıtı .json() ile sözlüğe çevirip doğru anahtara eriştiniz mi?
  • Olası hataları try/except ile yakaladınız mı?

Kendini sına

1) HTTP isteğinde “GET” ne anlama gelir?

2) Durum kodu (status code) 200 ne ifade eder?

3) requests kütüphanesinde gelen yanıtın ham metnine hangi özellik ile ulaşılır?

4) Bir isteğin sunucudan uzun süre yanıt alamaması durumunda programın sonsuza kadar beklememesi için hangi parametre kullanılır?

5) yanit.json() metodu ne işe yarar?

Cevaplar

1) GET, sunucudan veri “almak” (okumak) için kullanılan istek türüdür; tarayıcıda bir sayfa açmakla aynı mantıktadır.

2) 200 kodu, isteğin başarılı olduğunu ve sunucunun istenen veriyi sorunsuz şekilde döndürdüğünü ifade eder.

3) yanit.text özelliği, gelen yanıtın ham içeriğini düz metin (string) olarak verir.

4) timeout parametresi kullanılır; örneğin timeout=5 yazılarak sunucunun en fazla 5 saniye içinde yanıt vermesi beklenir.

5) yanit.json() metodu, sunucudan gelen JSON formatındaki metni otomatik olarak bir Python sözlüğüne (dictionary) dönüştürür, böylece içindeki verilere anahtar-değer mantığıyla kolayca erişilir.

Bu derste web sunucularına istek göndermeyi, yanıtları ve durum kodlarını kontrol etmeyi, hem düz metin hem JSON veriyi almayı öğrendik. Bir sonraki derste (7/8), burada elde ettiğimiz HTML içeriğini BeautifulSoup kütüphanesi ile ayrıştırıp içinden istediğimiz belirli bilgileri (bir başlık, bir fiyat, bir liste) nasıl süzüp çıkaracağımızı öğreneceğiz; yani gerçek anlamda web kazımaya başlayacağız.

Bu dersi kayıt olmadan izleyebilirsin. İlerlemeni kaydetmek, sertifika almak ve puan tablosuna girmek için ücretsiz üye ol: Kayıt Ol