Belirlediğin ürünlerin fiyatını otomatik olarak takip eden, bir değişiklik olduğunda Telegram üzerinden anında bildirim gönderen bir Python botu. Hem statik sayfalar (JSON-LD) hem de JavaScript ile içerik yükleyen siteler (Playwright) için destek sunar; ağ hatalarına karşı otomatik tekrar deneme ve yedek veri çekme yöntemleriyle güvenilir çalışır.
Proje birkaç Python kütüphanesine ihtiyaç duyuyor (web sayfası indirme, HTML okuma, JavaScript'li sayfaları render etme gibi işler için). Hepsini requirements.txt dosyasında listeledik, tek komutla kurabilirsin:
pip install -r requirements.txtBu modülün tek görevi
Bir ürün linki al, o ürünün fiyatını bir sayı olarak döndür. Telegram, dosya kaydetme gibi başka hiçbir işle ilgilenmez — sadece "linkten fiyat çıkarma" işini yapar.
Nasıl çalışır?
- Verilen linke bir HTTP isteği atılır (sayfa indirilir).
- Önce sayfanın JSON-LD verisinde (
<script type="application/ld+json">bloğu — arama motorları için siteye gömülen, makine-okunur ürün bilgisi) fiyat aranır. Bu yöntem, sitenin görsel tasarımı değişse bile genelde bozulmaz. - JSON-LD'de fiyat bulunamazsa, verilmişse bir CSS selector ile doğrudan sayfanın görünen HTML'inden okunur.
- Ağ hatası (zaman aşımı, bağlantı kopması) olursa, birkaç saniye bekleyip otomatik olarak tekrar dener.
- Sonuç, hem fiyatı hem de fiyatın hangi yöntemle bulunduğunu (
"json-ld"ya da"selector") içeren birFetchResultnesnesi olarak döner — bu, ileride hangi sitenin hangi yöntemle çalıştığını takip etmeyi kolaylaştırır.
JSON-LD ve CSS selector'un Aynı Anda Tercih Edilme Sebebi
Büyük ve modern e-ticaret siteleri genelde arama motorlarında (Google gibi) daha iyi görünebilmek için sayfalarına JSON-LD verisi ekler — bu yüzden JSON-LD ilk denenen, en güvenilir yöntemdir. Ancak her site bunu kullanmaz; bu projede demo olarak kullanılan books.toscrape.com gibi basit sitelerde bu veri bulunmayabilir. Böyle durumlarda, ikinci bir yöntem olarak CSS selector'a "yedek yöntem" (fallback) şeklinde başvurulur — bu sayede araç, JSON-LD kullanan ve kullanmayan siteler arasında esnek bir şekilde çalışabilir.
scraper.py modülünü, projenin geri kalanına ihtiyaç duymadan tek başına test edebilirsin.
- Proje klasöründeyken bir terminal aç.
- Python'un etkileşimli konsolunu başlat:
python>>>işareti göründüğünde, aşağıdaki satırları tek tek yapıştır:
from scraper import fetch_price
sonuc = fetch_price(
"https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html",
selector="p.price_color"
)
print(sonuc.price)
print(sonuc.method) scraper.py, sayfanın ilk indirilen halini okur. Ama bazı siteler fiyatı sayfa açıldıktan sonra, JavaScript çalıştırarak ekler (örneğin çoğu modern e-ticaret uygulaması, tek sayfa uygulamaları - SPA). Bu durumda scraper.py boş/fiyatsız bir sayfa görür.
js_scraper.py, bu sorunu Playwright kütüphanesiyle çözer — görünmez (headless) gerçek bir Chromium tarayıcısı açar, sayfanın JavaScript'inin çalışmasını bekler, ondan sonra fiyatı okur.
Ekstra özellikler:
- Kaynak engelleme: Resim, video, font ve CSS dosyalarının indirilmesi engellenir — hem işlemi hızlandırır hem siteye binen yükü azaltır, çünkü bizim tek ihtiyacımız olan metin (fiyat), görsel içerik değil.
- Birim fiyat filtreleme: Bazı sitelerde "(199,98 TL/kg)" gibi birim fiyatlar da sayfada geçebilir; bunlar gerçek ürün fiyatı olmadığı için taramadan önce elenir.
- İndirim paterni tanıma: Selector verilmediğinde, sayfadaki tüm fiyat benzeri değerler toplanır. İki değer bulunur ve ikincisi birincisinden küçükse (yani "eski fiyat → yeni/indirimli fiyat" düzeni varsa), doğru olan (ikinci, güncel) fiyat seçilir.
Kurulum (bir kereye mahsus):
pip install playwright
python -m playwright install chromiumKullanım örneği:
from js_scraper import fetch_price_js
sonuc = fetch_price_js(
"https://www.scrapingcourse.com/javascript-rendering",
selector=".product-price"
)
print(sonuc.price)
print(sonuc.method) Bu iki modülün gerçekten farklı işler yaptığını göstermek için, aynı sayfada (scrapingcourse.com/javascript-rendering — JavaScript olmadan ürünlerin hiç görünmediği bir eğitim/demo sitesi) ikisini de test ettik:
| Modül | Yöntem | Sonuç |
|---|---|---|
scraper.py |
Basit HTTP isteği (requests) |
FetchResult(price=None, method=None) — başarısız |
js_scraper.py |
Gerçek tarayıcı (Playwright) | FetchResult(price=52.0, method='js-selector') — başarılı |
Bu sonuç, js_scraper.py'ın neden gerekli olduğunu somut olarak gösteriyor: bazı siteler fiyatı JavaScript ile sonradan yüklüyor, ve bu durumda sadece gerçek bir tarayıcı motoru doğru sonucu verebiliyor. İki modül birlikte, projeyi hem hızlı (statik siteler için) hem kapsamlı (JavaScript'li siteler için) hale getiriyor.