Python Requests ile Başlangıç – GET İstekleri
Python programlama dili, web tabanlı uygulamalarla etkileşim kurmak için güçlü araçlar sunar. Bu araçların başında, HTTP isteklerini yönetmek için tasarlanmış requests kütüphanesi gelir. Web’den veri çekmek, API’lerle iletişim kurmak veya web sitelerinin işleyişini otomatikleştirmek istediğinizde, requests kütüphanesi vazgeçilmez bir yardımcıdır. Bu makalede, requests kütüphanesinin temel özelliklerini ve özellikle “GET” isteklerini nasıl kullanacağınızı ayrıntılı bir şekilde ele alacağız. Amacımız, okuyucuyu Python requests ile başarılı bir şekilde web’den veri çekebilecek seviyeye getirmektir.
requests Kütüphanesi Neden Önemli?
İnternet, milyarlarca bilgi kaynağını barındıran devasa bir ağdır. Bu kaynaklara programatik olarak erişmek, verileri işlemek ve otomatikleştirmek, modern yazılım geliştirmenin temel taşlarından biridir. HTTP (Hypertext Transfer Protocol), web üzerinde veri alışverişini sağlayan protokoldür. Bir web sitesini ziyaret ettiğinizde, aslında tarayıcınız o siteye bir HTTP isteği gönderir ve site de size bir HTTP yanıtı döndürür. Python requests kütüphanesi, bu HTTP isteklerini Python kodu içinden kolayca yapmanızı sağlar.
Python’ın standart kütüphanesinde urllib adında benzer bir modül bulunsa da, requests kütüphanesi çok daha kullanıcı dostu, okunabilir ve güçlüdür. requests ile karmaşık HTTP isteklerini bile birkaç satır kodla gerçekleştirebilirsiniz. Geliştiriciler arasında “HTTP for Humans” (İnsanlar için HTTP) sloganıyla anılması, kütüphanenin ne kadar sezgisel olduğunun bir göstergesidir.
GET isteği, HTTP protokolünün en yaygın kullanılan yöntemlerinden biridir. Bir web sunucusundan belirli bir kaynağı (örneğin bir HTML sayfası, bir resim, bir JSON verisi) talep etmek için kullanılır. GET istekleri, sunucuda herhangi bir veri değişikliği yapmamalıdır; sadece veri almalıdır. Bu, onları veri okuma işlemleri için ideal kılar.
Kurulum ve İlk Adımlar
requests kütüphanesini kullanmaya başlamadan önce, Python ortamınızda kurulu olması gerekir. Eğer kurulu değilse, Python’ın paket yöneticisi pip aracılığıyla kolayca kurabilirsiniz:
pip install requests
Kurulum tamamlandıktan sonra, kütüphaneyi Python betiğinizde import ederek kullanmaya başlayabilirsiniz:
import requests
Artık requests kütüphanesini kullanarak ilk GET isteğimizi yapmaya hazırız.
Temel Bir GET İsteği Yapmak
Bir GET isteği yapmak, requests kütüphanesi ile oldukça basittir. Tek yapmanız gereken, requests.get() fonksiyonuna hedef URL’yi iletmektir. Örnek olarak, herkese açık bir API olan JSONPlaceholder’dan sahte gönderi verilerini çekelim:
import requests
Hedef URL
url = "https://jsonplaceholder.typicode.com/posts/1"
GET isteği yapma
response = requests.get(url)
Yanıtı kontrol etme
if response.status_code == 200:
print("İstek başarılı!")
print(response.json()) # JSON yanıtını Python sözlüğüne dönüştür
else:
print(f"İstek başarısız! Durum Kodu: {response.status_code}")
Yukarıdaki kodda, requests.get(url) çağrısı belirtilen URL’ye bir GET isteği gönderir ve bize bir Response objesi döndürür. Bu obje, sunucudan gelen yanıtla ilgili tüm bilgileri içerir.
Yanıt Objelerini Anlamak (Response Object)
requests.get() fonksiyonunun döndürdüğü Response objesi, bir HTTP yanıtının birçok yönünü temsil eder. Bu objenin farklı özelliklerini inceleyerek, isteğimizin sonucunu ve sunucudan gelen verileri anlayabiliriz.
Durum Kodu (Status Code)
response.status_code özelliği, HTTP durum kodunu içerir. Bu kodlar, isteğin başarılı olup olmadığını veya bir hata oluşup oluşmadığını gösteren üç haneli sayılardır.
* 200 OK: İstek başarılı oldu.
* 201 Created: İstek başarılı oldu ve yeni bir kaynak oluşturuldu (genellikle POST istekleri için).
* 204 No Content: İstek başarılı oldu ancak döndürülecek içerik yok.
* 301 Moved Permanently: Kaynak kalıcı olarak başka bir yere taşındı.
* 302 Found: Kaynak geçici olarak başka bir yere taşındı.
* 400 Bad Request: İstek yanlış biçimlendirilmiş.
* 401 Unauthorized: Kimlik doğrulama gerekli.
* 403 Forbidden: Sunucu isteği anlamış ancak yetkilendirme reddedilmiş.
* 404 Not Found: Kaynak bulunamadı.
* 500 Internal Server Error: Sunucu tarafında beklenmeyen bir hata oluştu.
response.raise_for_status() yöntemi, durum kodu 4xx veya 5xx ise bir HTTPError istisnası yükseltir. Bu, hata kontrolünü otomatikleştirmek için çok kullanışlıdır.
import requests
url = "https://jsonplaceholder.typicode.com/posts/9999" # Olmayan bir gönderi
try:
response = requests.get(url)
response.raise_for_status() # 4xx veya 5xx durum kodları için hata fırlatır
print(response.json())
except requests.exceptions.HTTPError as err:
print(f"HTTP Hatası: {err}")
except requests.exceptions.RequestException as err:
print(f"Diğer bir hata oluştu: {err}")
Yanıt İçeriği (Content)
Yanıtın ana içeriğine farklı şekillerde erişebilirsiniz:
* response.text: Yanıtın metin içeriğini döndürür. Genellikle HTML veya düz metin yanıtları için kullanılır. requests kütüphanesi, metin kodlamasını otomatik olarak algılamaya çalışır.
* response.json(): Eğer yanıt içeriği geçerli bir JSON formatındaysa, bu metot içeriği bir Python sözlüğüne veya listesine dönüştürür. API’lerden veri çekerken en sık kullanılan yöntemdir.
* response.content: Yanıtın ham bayt içeriğini döndürür. Resimler, ses dosyaları veya diğer ikili verileri indirirken kullanışlıdır.
import requests
JSON yanıtı için
json_url = "https://jsonplaceholder.typicode.com/posts/1"
json_response = requests.get(json_url)
print("JSON İçeriği (Python Sözlüğü):", json_response.json())
Düz metin/HTML yanıtı için (örneğin bir web sitesi)
html_url = "https://www.google.com"
html_response = requests.get(html_url)
print("HTML İçeriğinin ilk 200 karakteri:", html_response.text[:200])
İkili veri (resim) için (örnek olarak küçük bir resim URL'si)
ÖNEMLİ: Gerçek bir resim URL'si kullanmalısınız. Bu sadece bir örnektir.
image_url = "https://www.python.org/static/img/python-logo.png"
image_response = requests.get(image_url)
with open("python_logo.png", "wb") as f:
f.write(image_response.content)
print("Resim indirildi.")
Yanıt Başlıkları (Headers)
response.headers özelliği, sunucudan gelen HTTP başlıklarını bir sözlük olarak içerir. Bu başlıklar, yanıt hakkında ek bilgiler sağlar (örneğin içerik türü, sunucu bilgisi, çerezler, önbellekleme talimatları).
import requests
url = "https://jsonplaceholder.typicode.com/posts/1"
response = requests.get(url)
print("Yanıt Başlıkları:")
for header, value in response.headers.items():
print(f"{header}: {value}")
print("Content-Type:", response.headers.get("Content-Type"))
Diğer Yararlı Özellikler
* response.url: İsteğin gönderildiği nihai URL’yi döndürür (yönlendirmelerden sonraki URL).
* response.request: İsteği oluşturan PreparedRequest objesine erişim sağlar. İsteğin başlıkları, gövdesi gibi detaylarını inceleyebilirsiniz.
* response.elapsed: İsteğin gönderilmesinden yanıtın alınmasına kadar geçen süreyi gösteren bir timedelta objesidir. Performans analizi için faydalıdır.
* response.cookies: Yanıtta gelen çerezleri içeren bir RequestsCookieJar objesidir.
GET İsteklerinde Parametre Kullanımı
Çoğu API, verileri filtrelemek, sıralamak veya aramak için URL’ye eklenen sorgu parametreleri (query parameters) kullanır. requests kütüphanesi, bu parametreleri bir Python sözlüğü olarak params argümanı aracılığıyla iletmenizi sağlar. Kütüphane, bu sözlüğü otomatik olarak URL’ye doğru bir şekilde kodlar.
Örnek olarak, JSONPlaceholder API’sinden belirli bir kullanıcıya ait tüm gönderileri çekelim:
import requests
base_url = "https://jsonplaceholder.typicode.com/posts"
params = {
"userId": 1 # userId'si 1 olan tüm gönderileri getir
}
response = requests.get(base_url, params=params)
if response.status_code == 200:
posts = response.json()
for post in posts:
print(f"ID: {post['id']}, Başlık: {post['title']}")
else:
print(f"Hata: {response.status_code}")
Bu örnekte, requests kütüphanesi base_url ve params sözlüğünü birleştirerek şu URL’yi oluşturur: https://jsonplaceholder.typicode.com/posts?userId=1. Birden fazla parametre eklemek için sözlüğe yeni anahtar-değer çiftleri eklemeniz yeterlidir.
params_multiple = {
"userId": 2,
"_limit": 5 # userId'si 2 olan ilk 5 gönderiyi getir
}
response_multiple = requests.get(base_url, params=params_multiple)
if response_multiple.status_code == 200:
print("\nuserId 2 ve limit 5 olan gönderiler:")
for post in response_multiple.json():
print(f"ID: {post['id']}, Başlık: {post['title']}")
GET İsteklerinde Özel Başlıklar (Headers) Kullanımı
Bazen bir API’ye istek gönderirken özel HTTP başlıkları eklemeniz gerekebilir. Örneğin, API anahtarları (Authorization başlığı), içeriğin hangi formatta kabul edileceğini belirtmek (Accept başlığı) veya isteği yapan istemci hakkında bilgi vermek (User-Agent başlığı) için başlıklar kullanılır. requests kütüphanesi, headers argümanı aracılığıyla bir Python sözlüğü olarak özel başlıkları iletmenizi sağlar.
import requests
url = "https://api.github.com/users/octocat" # GitHub API örneği
headers = {
"User-Agent": "MyPythonApp/1.0", # Kendi uygulamanızın adını belirtin
"Accept": "application/vnd.github.v3+json" # GitHub API için özel bir başlık
# "Authorization": "token YOUR_GITHUB_TOKEN" # Eğer kimlik doğrulaması gerekiyorsa
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
user_data = response.json()
print(f"GitHub Kullanıcı Adı: {user_data['login']}")
print(f"Adı: {user_data['name']}")
print(f"Konum: {user_data['location']}")
else:
print(f"Hata: {response.status_code}, Mesaj: {response.json().get('message', 'Bilinmeyen Hata')}")
User-Agent başlığı, sunucuya isteği kimin yaptığını bildirir. Bazı sunucular, belirli User-Agent değerlerine sahip isteklere farklı davranabilir veya botları engellemek için bu bilgiyi kullanabilir. Accept başlığı ise istemcinin hangi medya türlerini kabul edebileceğini belirtir.
Zaman Aşımı (Timeouts)
Bir HTTP isteği gönderdiğinizde, yanıtın ne kadar sürede geleceği her zaman belli değildir. Ağ sorunları, sunucu yoğunluğu veya diğer nedenlerden dolayı bir istek sonsuza kadar bekleyebilir. Bu durumu önlemek için timeout argümanını kullanarak bir zaman aşımı süresi belirleyebilirsiniz. Eğer belirtilen süre içinde yanıt gelmezse, requests.exceptions.Timeout istisnası yükseltilir.
timeout argümanı, isteğin sunucuya bağlanması için maksimum süreyi (saniye cinsinden) ve sunucudan yanıtın ilk baytını alma süresini tanımlayan bir float veya tuple olabilir.
import requests
url = "http://httpbin.org/delay/5" # 5 saniye gecikmeli yanıt veren bir test URL'si
try:
# 3 saniye zaman aşımı belirle
response = requests.get(url, timeout=3)
print("Yanıt alındı:", response.text)
except requests.exceptions.Timeout:
print("İstek zaman aşımına uğradı!")
except requests.exceptions.RequestException as e:
print(f"Bir hata oluştu: {e}")
Bu örnekte, sunucu 5 saniye gecikmeli yanıt verirken, biz 3 saniyelik bir zaman aşımı belirledik. Bu durumda, Timeout istisnası fırlatılacak ve programın donmasını engelleyecektir.
Hata Yönetimi
Sağlam uygulamalar geliştirmek için HTTP isteklerinde meydana gelebilecek hataları doğru bir şekilde yönetmek çok önemlidir. requests kütüphanesi, farklı hata türleri için özel istisnalar sunar:
* requests.exceptions.ConnectionError: Ağ bağlantısı sorunları (örneğin, sunucuya ulaşılamıyor, DNS hatası).
* requests.exceptions.Timeout: İstek zaman aşımına uğradı.
* requests.exceptions.HTTPError: 4xx veya 5xx durum koduna sahip bir yanıt alındı ( response.raise_for_status() ile fırlatılır).
* requests.exceptions.RequestException: Yukarıdaki tüm istisnaların temel sınıfı. Genel hata yakalama için kullanılabilir.
Her zaman try-except blokları kullanarak bu istisnaları yakalamalı ve uygun şekilde işlemelisiniz.
import requests
invalid_url = "http://nonexistent-domain-12345.com"
bad_api_url = "https://jsonplaceholder.typicode.com/nonexistent-path"
try:
# Bağlantı hatası denemesi
response = requests.get(invalid_url, timeout=5)
response.raise_for_status()
print(response.text)
except requests.exceptions.ConnectionError as e:
print(f"Bağlantı Hatası: {e}")
except requests.exceptions.Timeout:
print("İstek zaman aşımına uğradı.")
except requests.exceptions.HTTPError as e:
print(f"HTTP Hatası (4xx/5xx): {e}")
print(f"Yanıt metni: {e.response.text}")
except requests.exceptions.RequestException as e:
print(f"Genel İstek Hatası: {e}")
print("\n--- İkinci Deneme (Bad API Path) ---")
try:
# HTTP hatası denemesi (404 Not Found)
response = requests.get(bad_api_url, timeout=5)
response.raise_for_status()
print(response.text)
except requests.exceptions.ConnectionError as e:
print(f"Bağlantı Hatası: {e}")
except requests.exceptions.Timeout:
print("İstek zaman aşımına uğradı.")
except requests.exceptions.HTTPError as e:
print(f"HTTP Hatası (4xx/5xx): {e}")
print(f"Yanıt metni: {e.response.text}")
except requests.exceptions.RequestException as e:
print(f"Genel İstek Hatası: {e}")
Bu kapsamlı try-except yapısı, uygulamanızın farklı hata senaryolarında çökmeden çalışmaya devam etmesini sağlar.
Oturum Objeleri (Session Objects)
Birden fazla istek yaparken (özellikle aynı ana bilgisayara), her seferinde yeni bir bağlantı açmak ve kapatmak verimsiz olabilir. requests.Session objesi, bu durumu ele almak için tasarlanmıştır. Bir Session objesi, aynı ana bilgisayara yapılan tüm istekler için çerezleri, varsayılan başlıkları ve TCP bağlantılarını kalıcı hale getirir. Bu, hem performansı artırır hem de karmaşık etkileşimleri (örneğin, oturum açma ve sonra kimliği doğrulanmış istekler yapma) basitleştirir.
import requests
Bir Session objesi oluştur
session = requests.Session()
Varsayılan başlık ekle (tüm istekler için geçerli olacak)
session.headers.update({
"User-Agent": "MySessionApp/1.0",
"Accept": "application/json"
})
İlk isteği yap
response1 = session.get("https://jsonplaceholder.typicode.com/posts/1")
print(f"İlk istek URL: {response1.url}, Status: {response1.status_code}")
print(f"İlk istekten gelen çerezler: {session.cookies.get_dict()}")
İkinci isteği yap (aynı oturum üzerinden, çerezler ve başlıklar korunur)
response2 = session.get("https://jsonplaceholder.typicode.com/comments?postId=1")
print(f"İkinci istek URL: {response2.url}, Status: {response2.status_code}")
print(f"İkinci istekten gelen çerezler: {session.cookies.get_dict()}")
Oturumu kapat (isteğe bağlı, genellikle Python programı bittiğinde otomatik kapanır)
session.close()
Bu örnekte, session objesi üzerinden yapılan her iki istek de aynı User-Agent ve Accept başlıklarını kullanır ve sunucudan gelen çerezleri otomatik olarak yönetir.
Proxy Kullanımı
Bazen, HTTP isteklerinizi bir proxy sunucusu üzerinden yönlendirmeniz gerekebilir. Bu, IP adresinizi gizlemek, coğrafi kısıtlamaları aşmak veya şirket ağınızın gereksinimlerini karşılamak için yapılabilir. requests kütüphanesi, proxies argümanı ile proxy ayarlarını kolayca yapmanızı sağlar.
import requests
proxies = {
"http": "http://user:pass@10.10.1.10:3128", # HTTP proxy
"https": "http://user:pass@10.10.1.10:1080", # HTTPS proxy
}
veya kimlik doğrulaması olmayan basit bir proxy
proxies = {
"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080",
}
try:
response = requests.get("http://httpbin.org/ip", proxies=proxies, timeout=5)
print("Proxy üzerinden alınan IP:", response.json()['origin'])
except requests.exceptions.RequestException as e:
print(f"Proxy isteği sırasında hata oluştu: {e}")
Unutmayın ki proxy sunucusu adresleri ve kimlik bilgileri gerçekçi olmalıdır. Yukarıdaki örnek sadece bir şablon niteliğindedir.
SSL/TLS Sertifika Doğrulaması
Güvenli web iletişiminin temelini SSL/TLS sertifikaları oluşturur. requests kütüphanesi, varsayılan olarak tüm HTTPS istekleri için SSL sertifikalarını doğrular. Bu, bağlandığınız sunucunun gerçekten iddia ettiği sunucu olduğundan emin olmanızı sağlar ve “ortadaki adam” (man-in-the-middle) saldırılarını önler.
Ancak, bazı durumlarda (örneğin, yerel geliştirme ortamları veya kendi imzalı sertifikalarla çalışan sunucular) bu doğrulamayı devre dışı bırakmanız gerekebilir. verify argümanını False olarak ayarlayarak bunu yapabilirsiniz:
import requests
Kendi imzalı sertifikası olan bir sunucuya istek (Örnek: test amaçlı)
Gerçek dünyada bu genellikle önerilmez!
insecure_url = "https://self-signed.badssl.com/"
try:
response = requests.get(insecure_url, verify=False, timeout=10)
print("Güvenli olmayan URL'den yanıt alındı:", response.status_code)
except requests.exceptions.RequestException as e:
print(f"Hata: {e}")
verify=False kullanıldığında InsecureRequestWarning uyarısı alabilirsiniz. Bu uyarı, potansiyel güvenlik riskini hatırlatmak içindir ve genellikle production ortamlarında bu ayarın kullanılmaması tavsiye edilir. Güvenlik nedenleriyle, mümkün olduğunca verify=True (varsayılan değer) kullanmaya özen gösterin.
GET İstekleri için En İyi Uygulamalar
requests kütüphanesini kullanırken uygulamanızın sağlam, verimli ve güvenli olmasını sağlamak için bazı en iyi uygulamaları takip etmek önemlidir:
1. Hata Yönetimini Ciddiye Alın: Her zaman try-except blokları kullanarak ağ hatalarını, zaman aşımlarını ve HTTP durum kodu hatalarını yakalayın. response.raise_for_status() kullanmak, 4xx/5xx hatalarını otomatik olarak yakalamak için harika bir yoldur.
2. Zaman Aşımı Belirleyin: İsteklerinizin süresiz olarak takılmasını önlemek için her zaman timeout argümanını kullanın. Bu, uygulamanızın tepki süresini kontrol altında tutar.
3. Oturumları Kullanın (Session Objects): Aynı ana bilgisayara birden fazla istek yapıyorsanız, requests.Session objesi kullanın. Bu, performans artışı sağlar ve çerez yönetimini basitleştirir.
4. API Rate Limit’lerine Dikkat Edin: Çoğu API, belirli bir zaman diliminde yapabileceğiniz istek sayısını sınırlar (rate limiting). Bu limitleri aşmamak için API dokümantasyonunu okuyun ve gerekirse istekler arasına gecikmeler ekleyin (time.sleep()).
5. Hassas Bilgileri Güvenli Saklayın: API anahtarları, kullanıcı adları ve şifreler gibi hassas bilgileri doğrudan kodunuzda saklamaktan kaçının. Ortam değişkenleri, yapılandırma dosyaları veya güvenli bir anahtar kasası kullanın.
6. Kullanıcı Aracısı (User-Agent) Başlığı Belirtin: Özellikle halka açık API’lere istek yaparken, isteğinizin kaynağını belirten anlamlı bir User-Agent başlığı göndermek iyi bir uygulamadır. Bu, API sağlayıcılarının trafiği anlamasına yardımcı olur.
7. Yeniden Deneme Mekanizmaları: Geçici ağ sorunları için, başarısız olan istekleri belirli bir gecikmeyle ve sınırlı sayıda yeniden denemek için bir mekanizma uygulayın. urllib3.Retry ile requests kütüphanesini kullanarak bu özelliği entegre edebilirsiniz.
8. SSL Doğrulamasını Devre Dışı Bırakmaktan Kaçının: verify=False kullanmak, uygulamanızı güvenlik açıklarına karşı savunmasız hale getirir. Yalnızca çok özel ve kontrol altındaki durumlarda kullanın ve riskleri anladığınızdan emin olun.
Sonuç
Bu makale boyunca, Python requests kütüphanesinin GET istekleri için nasıl kullanılacağını ayrıntılı bir şekilde inceledik. Temel bir GET isteği yapmaktan, yanıt objesini anlamaya, parametreler ve başlıklar eklemeye, zaman aşımı yönetimine ve hata işlemeye kadar birçok konuyu ele aldık. Ayrıca, oturum objeleri, proxy kullanımı ve SSL doğrulaması gibi daha gelişmiş konulara da değindik.
requests kütüphanesi, Python ile web’den veri çekmek ve API’lerle etkileşim kurmak için güçlü, esnek ve kullanımı kolay bir araçtır. Bu makaledeki bilgileri kullanarak, web tabanlı projelerinizde güvenle ve etkin bir şekilde HTTP GET istekleri yapabilir, verileri toplayabilir ve işleyebilirsiniz. Unutmayın, pratik yapmak ve farklı API’lerle denemeler yapmak, bu kütüphanede ustalaşmanın en iyi yoludur.