miracbirben

Çalışkan
Katılım
14 Mart 2025
Mesajlar
26
Beğeniler
1
Merhaba,

Python kullanarak DeFacto sitesindeki kategorilerden veri çekip, indirimde olan ürünleri listeleyen bir "indirim dedektörü" projesi geliştirmek istiyorum. Amacım, belirli kategorilerdeki ürünleri periyodik olarak kontrol edip, indirime girenleri tespit etmek ve belki bir listeye kaydetmek veya bildirim göndermek.

Yaptığım ilk araştırmada, ürün verilerini JSON formatında döndüren bir API endpoint'i buldum (örneğin, belirli bir kategori için). Bu endpoint'ten veri çekip CampaignBadge alanına bakarak indirimli olabilecek ürünleri filtrelemeye çalışan basit bir başlangıç kodu yazdım.

Başlangıç olarak yazdığım örnek kod aşağıdadır:

Kod:
import json
import requests

# İndirimli ürünleri filtreleyen fonksiyon
def filter_discounted_products(api_data):
    discounted_products = []

    # Veri yapısını kontrol et
    if api_data and "Data" in api_data and "SearchResponse" in api_data["Data"] and "Documents" in api_data["Data"]["SearchResponse"]:
        for product in api_data["Data"]["SearchResponse"]["Documents"]:
            # Kampanya bilgisi var mı kontrol et
            campaign = product.get("CampaignBadge")
            # Kampanya içinde indirim miktarı belirtilmiş mi kontrol et
            if campaign and "DiscountAmount" in campaign and campaign["DiscountAmount"] is not None:
                # Ürün bilgilerini al, eksik bilgi varsa varsayılan değer ata
                product_name = product.get("ProductName", "İsim Bilgisi Yok")
                # Resim listesinin boş olup olmadığını kontrol et
                pictures = product.get("ProductPictures", [])
                image_url = pictures[0].get("ProductPicturePath", "Resim Yok") if pictures else "Resim Yok"
                normal_price = product.get("ProductPriceInclTax", 0) # İndirimsiz fiyatı al

                discounted_products.append({
                    "name": product_name,
                    "image": image_url,
                    "discount_info": campaign.get("DiscountAmount", "İndirim Bilgisi Yok"), # İndirim metnini al
                    "normalPrice": normal_price
                })
            # Alternatif olarak, eski fiyat ve yeni fiyat karşılaştırması yapılabilir
            # elif product.get("OldProductPriceInclTax") and product.get("ProductPriceInclTax"):
            #     old_price = product.get("OldProductPriceInclTax")
            #     new_price = product.get("ProductPriceInclTax")
            #     if old_price > new_price:
            #         # ... indirimli ürün olarak ekle ...
            #         pass # Bu kısım geliştirilebilir

    return discounted_products

# Belirli bir kategori URL'sinden JSON verisini al ve işle
# Örnek URL (Erkek > Gömlek kategorisi olabilir, URL'yi kontrol etmek gerekir)
# URL'deki fx_c1 ve fx_c2 parametreleri kategoriye göre değişir.
url = "https://www.defacto.com.tr/Catalog/PartialIndexScrollResult?page=1&SortOrder=0&pageSize=24&fx_c1=1&fx_c2=1413"

try:
    # Web sitesi gibi davranmak için User-Agent eklemek iyi bir pratik olabilir
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}
    response = requests.get(url, headers=headers, timeout=15) # Timeout süresini biraz artırabiliriz
    response.raise_for_status()  # HTTP hatası varsa (4xx veya 5xx) burada bir istisna fırlatır

    api_response = response.json()
    filtered_products = filter_discounted_products(api_response)

    if filtered_products:
        print(f"{len(filtered_products)} adet indirimli ürün bulundu:")
        print(json.dumps(filtered_products, indent=4, ensure_ascii=False)) # Türkçe karakterler için ensure_ascii=False
    else:
        print("Belirtilen kriterlere uygun indirimli ürün bulunamadı veya API yanıtı beklenildiği gibi değil.")
        # API yanıtını incelemek için:
        # print("API Yanıtı:")
        # print(json.dumps(api_response, indent=4, ensure_ascii=False))


except requests.exceptions.Timeout:
    print(f"Hata: İstek zaman aşımına uğradı. URL: {url}")
except requests.exceptions.HTTPError as e:
    print(f"Hata: HTTP Hatası oluştu. Durum Kodu: {e.response.status_code}, URL: {url}")
except requests.exceptions.RequestException as e:
    print(f"Hata: Veri çekilemedi. Detaylar: {e}")
except json.JSONDecodeError as e:
    print(f"Hata: JSON verisi ayrıştırılamadı. Muhtemelen API yanıtı JSON formatında değil. Detaylar: {e}")
    # print("Alınan Ham Yanıt:", response.text) # Ham yanıtı görmek için bu satırı açabilirsiniz

Ancak projeyi daha işlevsel hale getirmek için bazı konularda yardıma ihtiyacım var:

  1. Tüm Kategorileri Tarama: Sitedeki farklı kategorileri (örneğin, erkek, kadın, çocuk giyim vb.) nasıl dinamik olarak tespit edip hepsinden veri çekebilirim? Tek bir URL yerine tüm siteyi nasıl kapsarım? Kategori URL'lerini veya ID'lerini (fx_c1, fx_c2 gibi parametreleri) nasıl bulabilirim?
  2. Sayfalama (Pagination): Kategori sayfalarında genellikle birden fazla sayfa bulunur (page=1, page=2...). Tüm sayfalardaki ürünleri almak için page parametresini artırarak istekleri nasıl otomatize edebilirim? Kaç sayfa olduğunu nasıl anlarım?
  3. Veri Doğruluğu ve İndirim Tespiti: Mevcut kod CampaignBadge kullanıyor. İndirimi tespit etmenin daha güvenilir yolları var mı (örneğin, eski fiyat/yeni fiyat karşılaştırması)? API'den gelen veride bu bilgiler (OldProductPriceInclTax vs ProductPriceInclTax) nasıl daha doğru ve tutarlı bir şekilde kullanılabilir?
  4. API Güvenilirliği ve Alternatifler: Kullandığım bu PartialIndexScrollResult endpoint'i ne kadar güvenilir? Bu tür iç API'lar sıkça değişebilir. DeFacto'nun resmi bir API'si var mı? Bu yöntem dışında (örneğin, requests ve BeautifulSoup veya Scrapy gibi kütüphanelerle doğrudan HTML sayfasını kazımak) daha stabil bir yol olabilir mi?
  5. Hata Yönetimi ve Dayanıklılık: Kodun daha sağlam çalışması için ne gibi ek hata kontrolleri (örneğin, network sorunları, sitedeki yapısal değişiklikler, beklenmedik API yanıtları) eklemeliyim? try-except bloklarını nasıl daha iyi kullanabilirim?
  6. Veri Saklama ve Sunum: Tespit edilen indirimli ürünleri nasıl saklayabilirim (örneğin, bir veri tabanı (SQLite gibi), CSV dosyası)? Belki basit bir arayüzle (Flask/Django veya sadece terminal çıktısı) nasıl gösterebilirim?
  7. Etik ve Yasal Konular: Bu tür bir otomasyonun sitenin kullanım koşullarına uygun olup olmadığını nasıl kontrol edebilirim? Siteye aşırı yük bindirmemek için nelere dikkat etmeliyim (örneğin, istekler arasına time.sleep() eklemek)?
Bu konularda fikirlerinizi, olası çözüm yollarını, kod önerilerini veya kullanabileceğim kütüphaneler/teknikler hakkındaki tavsiyelerinizi bekliyorum.

Yardımlarınız için şimdiden teşekkür ederim!


B
 
Merhaba,

Python kullanarak DeFacto sitesindeki kategorilerden veri çekip, indirimde olan ürünleri listeleyen bir "indirim dedektörü" projesi geliştirmek istiyorum. Amacım, belirli kategorilerdeki ürünleri periyodik olarak kontrol edip, indirime girenleri tespit etmek ve belki bir listeye kaydetmek veya bildirim göndermek.

Yaptığım ilk araştırmada, ürün verilerini JSON formatında döndüren bir API endpoint'i buldum (örneğin, belirli bir kategori için). Bu endpoint'ten veri çekip CampaignBadge alanına bakarak indirimli olabilecek ürünleri filtrelemeye çalışan basit bir başlangıç kodu yazdım.

Başlangıç olarak yazdığım örnek kod aşağıdadır:

Kod:
import json
import requests

# İndirimli ürünleri filtreleyen fonksiyon
def filter_discounted_products(api_data):
    discounted_products = []

    # Veri yapısını kontrol et
    if api_data and "Data" in api_data and "SearchResponse" in api_data["Data"] and "Documents" in api_data["Data"]["SearchResponse"]:
        for product in api_data["Data"]["SearchResponse"]["Documents"]:
            # Kampanya bilgisi var mı kontrol et
            campaign = product.get("CampaignBadge")
            # Kampanya içinde indirim miktarı belirtilmiş mi kontrol et
            if campaign and "DiscountAmount" in campaign and campaign["DiscountAmount"] is not None:
                # Ürün bilgilerini al, eksik bilgi varsa varsayılan değer ata
                product_name = product.get("ProductName", "İsim Bilgisi Yok")
                # Resim listesinin boş olup olmadığını kontrol et
                pictures = product.get("ProductPictures", [])
                image_url = pictures[0].get("ProductPicturePath", "Resim Yok") if pictures else "Resim Yok"
                normal_price = product.get("ProductPriceInclTax", 0) # İndirimsiz fiyatı al

                discounted_products.append({
                    "name": product_name,
                    "image": image_url,
                    "discount_info": campaign.get("DiscountAmount", "İndirim Bilgisi Yok"), # İndirim metnini al
                    "normalPrice": normal_price
                })
            # Alternatif olarak, eski fiyat ve yeni fiyat karşılaştırması yapılabilir
            # elif product.get("OldProductPriceInclTax") and product.get("ProductPriceInclTax"):
            #     old_price = product.get("OldProductPriceInclTax")
            #     new_price = product.get("ProductPriceInclTax")
            #     if old_price > new_price:
            #         # ... indirimli ürün olarak ekle ...
            #         pass # Bu kısım geliştirilebilir

    return discounted_products

# Belirli bir kategori URL'sinden JSON verisini al ve işle
# Örnek URL (Erkek > Gömlek kategorisi olabilir, URL'yi kontrol etmek gerekir)
# URL'deki fx_c1 ve fx_c2 parametreleri kategoriye göre değişir.
url = "https://www.defacto.com.tr/Catalog/PartialIndexScrollResult?page=1&SortOrder=0&pageSize=24&fx_c1=1&fx_c2=1413"

try:
    # Web sitesi gibi davranmak için User-Agent eklemek iyi bir pratik olabilir
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}
    response = requests.get(url, headers=headers, timeout=15) # Timeout süresini biraz artırabiliriz
    response.raise_for_status()  # HTTP hatası varsa (4xx veya 5xx) burada bir istisna fırlatır

    api_response = response.json()
    filtered_products = filter_discounted_products(api_response)

    if filtered_products:
        print(f"{len(filtered_products)} adet indirimli ürün bulundu:")
        print(json.dumps(filtered_products, indent=4, ensure_ascii=False)) # Türkçe karakterler için ensure_ascii=False
    else:
        print("Belirtilen kriterlere uygun indirimli ürün bulunamadı veya API yanıtı beklenildiği gibi değil.")
        # API yanıtını incelemek için:
        # print("API Yanıtı:")
        # print(json.dumps(api_response, indent=4, ensure_ascii=False))


except requests.exceptions.Timeout:
    print(f"Hata: İstek zaman aşımına uğradı. URL: {url}")
except requests.exceptions.HTTPError as e:
    print(f"Hata: HTTP Hatası oluştu. Durum Kodu: {e.response.status_code}, URL: {url}")
except requests.exceptions.RequestException as e:
    print(f"Hata: Veri çekilemedi. Detaylar: {e}")
except json.JSONDecodeError as e:
    print(f"Hata: JSON verisi ayrıştırılamadı. Muhtemelen API yanıtı JSON formatında değil. Detaylar: {e}")
    # print("Alınan Ham Yanıt:", response.text) # Ham yanıtı görmek için bu satırı açabilirsiniz

Ancak projeyi daha işlevsel hale getirmek için bazı konularda yardıma ihtiyacım var:

  1. Tüm Kategorileri Tarama: Sitedeki farklı kategorileri (örneğin, erkek, kadın, çocuk giyim vb.) nasıl dinamik olarak tespit edip hepsinden veri çekebilirim? Tek bir URL yerine tüm siteyi nasıl kapsarım? Kategori URL'lerini veya ID'lerini (fx_c1, fx_c2 gibi parametreleri) nasıl bulabilirim?
  2. Sayfalama (Pagination): Kategori sayfalarında genellikle birden fazla sayfa bulunur (page=1, page=2...). Tüm sayfalardaki ürünleri almak için page parametresini artırarak istekleri nasıl otomatize edebilirim? Kaç sayfa olduğunu nasıl anlarım?
  3. Veri Doğruluğu ve İndirim Tespiti: Mevcut kod CampaignBadge kullanıyor. İndirimi tespit etmenin daha güvenilir yolları var mı (örneğin, eski fiyat/yeni fiyat karşılaştırması)? API'den gelen veride bu bilgiler (OldProductPriceInclTax vs ProductPriceInclTax) nasıl daha doğru ve tutarlı bir şekilde kullanılabilir?
  4. API Güvenilirliği ve Alternatifler: Kullandığım bu PartialIndexScrollResult endpoint'i ne kadar güvenilir? Bu tür iç API'lar sıkça değişebilir. DeFacto'nun resmi bir API'si var mı? Bu yöntem dışında (örneğin, requests ve BeautifulSoup veya Scrapy gibi kütüphanelerle doğrudan HTML sayfasını kazımak) daha stabil bir yol olabilir mi?
  5. Hata Yönetimi ve Dayanıklılık: Kodun daha sağlam çalışması için ne gibi ek hata kontrolleri (örneğin, network sorunları, sitedeki yapısal değişiklikler, beklenmedik API yanıtları) eklemeliyim? try-except bloklarını nasıl daha iyi kullanabilirim?
  6. Veri Saklama ve Sunum: Tespit edilen indirimli ürünleri nasıl saklayabilirim (örneğin, bir veri tabanı (SQLite gibi), CSV dosyası)? Belki basit bir arayüzle (Flask/Django veya sadece terminal çıktısı) nasıl gösterebilirim?
  7. Etik ve Yasal Konular: Bu tür bir otomasyonun sitenin kullanım koşullarına uygun olup olmadığını nasıl kontrol edebilirim? Siteye aşırı yük bindirmemek için nelere dikkat etmeliyim (örneğin, istekler arasına time.sleep() eklemek)?
Bu konularda fikirlerinizi, olası çözüm yollarını, kod önerilerini veya kullanabileceğim kütüphaneler/teknikler hakkındaki tavsiyelerinizi bekliyorum.

Yardımlarınız için şimdiden teşekkür ederim!


B

1. Tüm Kategorileri Tarama​


DeFacto'nun web sitesindeki kategorileri otomatik olarak tespit etmek için, genellikle anasayfa veya kategori sayfasının HTML yapısını kontrol edip, o sayfalardan kategori linklerini veya ID'lerini çekmek için BeautifulSoup gibi bir kütüphane kullanabilirsiniz. Kategorileri döndürmek için şunları yapabilirsiniz:

Python:
from bs4 import BeautifulSoup
import requests

def get_categories():
    url = "https://www.defacto.com.tr/"
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')

    categories = []
    for category in soup.find_all('a', class_='category-class-here'):  # 'category-class-here' kısmını gerçek sınıf adıyla değiştirin
        categories.append(category['href'])  # Linkleri veya ID'leri alabilirsiniz
    return categories

2. Sayfalama (Pagination)​


Sayfalama işlemini otomatik hale getirmek için, toplam sayfa sayısını bulmanız gerekecek. API'nin yanıtında toplam sayfa bilgisi varsa (örneğin TotalPages), bunu kullanabilirsiniz. Her sayfayı çekmek için bir döngü oluşturup sayfa numarasını artırarak istek gönderebilirsiniz:

Python:
def fetch_all_pages(url, total_pages):
    all_products = []
    for page in range(1, total_pages + 1):
        response = requests.get(f"{url}&page={page}")
        api_response = response.json()
        filtered_products = filter_discounted_products(api_response)
        all_products.extend(filtered_products)
    return all_products

3. Veri Doğruluğu ve İndirim Tespiti​


Ürünlerin eski fiyatını ve yeni fiyatını karşılaştırarak indirimin doğruluğunu kontrol etmek için mevcut kodunuza bir ekleme yapabilirsiniz:

Python:
if product.get("OldProductPriceInclTax") and product.get("ProductPriceInclTax"):
    old_price = product["OldProductPriceInclTax"]
    new_price = product["ProductPriceInclTax"]
    if old_price > new_price:
        # Ürün indirimli

4. API Güvenilirliği ve Alternatifler​


DeFacto'nun resmi API'si olup olmadığını öğrenmek için doğrudan DeFacto ile iletişim kurabilirsiniz. Ayrıca, HTML sayfanızı kazımak için Scrapy veya BeautifulSoup gibi kütüphaneleri kullanmak iyi bir alternatif olabilir. Ancak, web kazıma, kullanım koşullarına aykırı olabilir.

5. Hata Yönetimi ve Dayanıklılık​


Ek hata kontrolü için:

  • Zaman aşımı, bağlantı hatası gibi durumları kontrol etmek için daha fazla except bloğu ekleyebilirsiniz.
  • Hata mesajlarını güncelleyerek, daha spesifik hatalar hakkında bilgi sağlayabilirsiniz.

6. Veri Saklama ve Sunum​


Verileri saklamak için SQLite kullanabilirsiniz. Flask veya Django gibi bir web çerçevesi ile kullanıcı ara yüzü oluşturabilirsiniz. Örnek:

Python:
import sqlite3

def save_to_db(products):
    conn = sqlite3.connect('discounted_products.db')
    c = conn.cursor()
    c.execute('CREATE TABLE IF NOT EXISTS discounts (name TEXT, image TEXT, discount_info TEXT, normalPrice REAL)')
    c.executemany('INSERT INTO discounts VALUES (?,?,?,?)', products)
    conn.commit()
    conn.close()

7. Etik ve Yasal Konular​


Site kullanım şartlarını incelemek için DeFacto'nun kullanım şartları sayfasını kontrol etmelisiniz. Ayrıca bot trafiğini kontrol altına almak için, istekler arasında time.sleep() ekleyerek aşırı yüklenmeyi önleyebilirsiniz.

Python:
import time

time.sleep(2)  # 2 saniye bekle

Bu öneriler, projenizi daha işlevsel hale getirmek için yol gösterici olacak. Başarılar!