İçeriğe geç

Python ile Sorumlu Web Kazıma: Fiyat Takibi İçin Sağlam Bir Başlangıç

robots.txt kontrolü, requests ile Selenium 4 arasında seçim, Türkçe fiyatları Decimal ile okumak ve veriyi SQL Server'a toplu yazmak. Siteye yük bindirmeyen, bozulduğunda haber veren bir kazıyıcının parçaları.

Python güncellendi 25.10.2026 4 dk okuma Atılay Berber

Rakip fiyatlarını, kampanyaları ya da kamuya açık katalogları takip etmek için web kazıma (web scraping) çok güçlü bir araç. Ama iyi bir kazıyıcı sadece veriyi çeken değil, siteye yük bindirmeyen, kurallara uyan ve bozulduğunda kendini belli eden kazıyıcıdır. Bu yazıda Python ile işe yarar ve sorumlu bir kazıyıcının temel parçalarını anlatıyorum.

1. Önce kuralları okuyun

Başlamadan önce sitenin kullanım koşullarına ve robots.txt dosyasına bakın. Bir API ya da veri dışa aktarma seçeneği varsa her zaman onu tercih edin. robots.txt kontrolü Python’un standart kütüphanesiyle yapılabilir:

from urllib import robotparser

rp = robotparser.RobotFileParser()
rp.set_url("https://www.ornek-magaza.com/robots.txt")
rp.read()

url = "https://www.ornek-magaza.com/kategori/sut-urunleri"
if not rp.can_fetch("FiyatTakipBotu", url):
    raise SystemExit("Bu sayfanın taranmasına izin verilmiyor.")

bekleme = rp.crawl_delay("FiyatTakipBotu") or 2  # saniye

CAPTCHA, giriş duvarı ya da bot korumasıyla karşılaşırsanız bunu “aşılacak bir engel” değil, sitenin “istemiyorum” demesi olarak okuyun ve durun.

2. Sayfa statikse requests yeterli

Fiyatlar HTML içinde geliyorsa tarayıcı açmaya gerek yok; requests ve BeautifulSoup çok daha hızlı ve hafiftir. Kendinizi tanıtan bir User-Agent kullanın ve istekler arasında bekleyin:

import time
import requests
from bs4 import BeautifulSoup

oturum = requests.Session()
oturum.headers["User-Agent"] = "FiyatTakipBotu/1.0 (+https://www.atilayberber.com)"

def sayfa_getir(url):
    yanit = oturum.get(url, timeout=20)
    yanit.raise_for_status()
    time.sleep(bekleme)
    return BeautifulSoup(yanit.text, "html.parser")

3. JavaScript ile yükleniyorsa Selenium 4

Ürünler sayfa açıldıktan sonra JavaScript ile yükleniyorsa Selenium gerekir. Selenium 4’te eski find_element_by_* metotları kaldırıldı; artık By ile çalışılıyor. time.sleep yerine açık bekleme (explicit wait) kullanmak hem daha hızlı hem daha güvenilirdir:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

secenekler = webdriver.ChromeOptions()
secenekler.add_argument("--headless=new")
surucu = webdriver.Chrome(options=secenekler)  # Selenium Manager sürücüyü kendisi bulur

try:
    surucu.get(url)
    WebDriverWait(surucu, 15).until(
        EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".urun-kart"))
    )
    kartlar = surucu.find_elements(By.CSS_SELECTOR, ".urun-kart")
    for kart in kartlar:
        ad = kart.find_element(By.CSS_SELECTOR, ".urun-ad").text
        fiyat = kart.find_element(By.CSS_SELECTOR, ".urun-fiyat").text
finally:
    surucu.quit()

4. Türkçe fiyatları doğru okuyun

“1.249,90 TL” gibi bir metni float‘a çevirmeye çalışmak hem hata verir hem de kuruş hassasiyetini bozar. Para birimi için Decimal kullanın:

from decimal import Decimal, InvalidOperation
import re

def fiyat_oku(metin: str) -> Decimal | None:
    temiz = re.sub(r"[^\d,\.]", "", metin)          # "1.249,90"
    temiz = temiz.replace(".", "").replace(",", ".")  # "1249.90"
    try:
        return Decimal(temiz)
    except InvalidOperation:
        return None

fiyat_oku("1.249,90 TL")  # Decimal('1249.90')

5. Veriyi toplu yazın

Her ürün için ayrı ayrı INSERT ve commit yapmak yavaştır. Satırları biriktirip toplu yazın; SQL Server kullanıyorsanız pyodbc‘nin fast_executemany özelliği büyük fark yaratır. Bağlantı ve imleçleri her zaman kapatın:

import pyodbc
from contextlib import closing

with closing(pyodbc.connect(BAGLANTI_METNI)) as baglanti:
    with closing(baglanti.cursor()) as imlec:
        imlec.fast_executemany = True
        imlec.executemany(
            "INSERT INTO dbo.Fiyat (Kaynak, UrunAdi, Fiyat, Tarih) VALUES (?, ?, ?, SYSDATETIME())",
            satirlar,
        )
    baglanti.commit()

6. Bozulduğunda haberiniz olsun

  • Her çalıştırmada kaç ürün çekildiğini kaydedin; sayı birden düşerse büyük ihtimalle sitenin HTML yapısı değişmiştir.
  • Sayfalamada aynı ürünün iki kez gelmesine karşı ürün kodu ya da URL ile tekilleştirme yapın.
  • Seçicileri (CSS sınıfları) kodun içine dağıtmak yerine tek bir yapılandırma bölümünde tutun; site değiştiğinde tek yerden güncellersiniz.

Kazıma işin sadece ilk adımı. Asıl değer, bu veriyi düzenli olarak bir veritabanına yazıp Power BI gibi bir araçla zaman içindeki değişimi görünür kılmakta.

Sık yapılan hatalar

  • 429 yanıtını görmezden gelmek: Site “Too Many Requests” (429) dönüyorsa yavaşlamanızı istiyordur. Retry-After başlığına uyun ve beklemeyi her denemede artırın; hemen tekrar denemeyin.
  • Kırılgan seçiciler: Uzun XPath zincirleri ya da otomatik üretilmiş sınıf adları ilk tasarım değişikliğinde bozulur. Mümkünse sabit kimlikler, data-* öznitelikleri ya da sayfadaki yapılandırılmış veri (JSON-LD) kullanın.
  • Hata durumunda sessizce devam etmek: Fiyatı okunamayan ürünü 0 olarak yazmak raporu bozar. Okunamayanları ayrı kaydedin ve sayılarını izleyin.
  • Kişisel veri toplamak: Yorumlar, kullanıcı adları gibi kişisel verileri toplamayın. Fiyat takibi için ürün ve fiyat bilgisi yeterlidir; kişisel veri KVKK kapsamına girer.

Sık sorulan sorular

Web kazıma yasal mı?

Bu bir hukuki görüş değil; ama genel çerçeve şu: kamuya açık veriyi, sitenin kullanım koşullarına ve robots.txt kurallarına uyarak, siteye yük bindirmeden ve kişisel veri toplamadan çekmek çok daha düşük risklidir. Emin değilseniz site sahibinden izin isteyin ya da varsa resmi API’yi kullanın.

Kazıyıcıyı nasıl düzenli çalıştırırım?

Windows’ta Görev Zamanlayıcı, Linux’ta cron yeterlidir. Her çalıştırmanın başlangıç, bitiş ve çekilen kayıt sayısını bir log tablosuna yazarsanız sorunları erkenden fark edersiniz. Fiyat değişimlerini SQL Server’da LAG ile hesaplayıp Power BI’da görselleştirebilirsiniz.

İlgili yazılar

HABERDAR OL

Yeni rehberler, kategorilere ayrılmış tek bir e-postada.

Her pazartesi, o hafta yayımlanan yazılar konu başlıklarına göre derlenmiş olarak gelen kutunda. Yeni yazı yoksa e-posta da yok.

Onay e-postasındaki bağlantıya tıklamadan liste aktif olmaz. İstediğin an tek tıkla çıkabilirsin.

Faydalı bulduysan paylaş
LinkedIn'de paylaş X WhatsApp

1 yorum

Yorum yaz

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir