<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[BotBB - Web Otomasyonu, Bot Mimarileri ve Scraping Topluluğu - Fiyat ve Stok Takip Botlari]]></title>
		<link>https://botbb.tr/</link>
		<description><![CDATA[BotBB - Web Otomasyonu, Bot Mimarileri ve Scraping Topluluğu - https://botbb.tr]]></description>
		<pubDate>Mon, 19 Oct 2026 20:58:37 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[Hazır Kod: Fiyat Takip Botuna JSON Veri Loglama (Fiyat Geçmişi Ekleme)]]></title>
			<link>https://botbb.tr/Thread-hazir-kod-fiyat-takip-botuna-json-veri-loglama-fiyat-gecmisi-ekleme</link>
			<pubDate>Sat, 17 Oct 2026 19:39:36 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://botbb.tr/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://botbb.tr/Thread-hazir-kod-fiyat-takip-botuna-json-veri-loglama-fiyat-gecmisi-ekleme</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Hazır Kod: Fiyat Takip Botuna JSON Veri Loglama (Fiyat Geçmişi &amp; Grafik Altyapısı Ekleme)</span></span><br />
<br />
Fiyat takip botlarında sadece anlık bildirim almak bir süre sonra yetersiz kalır. Ürünün son 1 haftada veya 1 ayda gördüğü en dip fiyatı, hangi günlerde indirime girdiğini ve satıcının bindirim yapıp yapmadığını analiz etmek için <span style="font-weight: bold;" class="mycode_b">fiyat geçmişini yerel bir dosyada kayıt altında tutmak</span> gerekir.<br />
<br />
Node.js'in yerleşik <span style="font-weight: bold;" class="mycode_b">fs</span> (File System) modülü sayesinde harici hiçbir veritabanı (MySQL/MongoDB vb.) kurmaya gerek kalmadan, her taramada fiyatları <span style="font-weight: bold;" class="mycode_b">urun_gecmisi.json</span> dosyasına tarih ve saat damgasıyla otomatik işleyebiliriz.<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. JSON Dosyasının Yapısı Nasıl Görünecek?</span></span><br />
<br />
Bot çalıştıkça aynı dizinde otomatik olarak şu formatta temiz bir arşiv oluşacaktır:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>{
  "ASUS RTX 4070 Ti Ekran Kartı": [
    {
      "tarih": "17.10.2026",
      "saat": "14:30:15",
      "fiyat": 34500
    },
    {
      "tarih": "17.10.2026",
      "saat": "15:15:20",
      "fiyat": 31999
    }
  ]
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">2. JSON Loglama Entegre Edilmiş Tam Kod (fiyat_takip_loglu.js)</span></span><br />
<br />
Klasörünüzdeki koda sadece <span style="font-weight: bold;" class="mycode_b">fs</span> modülü ve <span style="font-weight: bold;" class="mycode_b">fiyatKaydet()</span> fonksiyonu eklenmiştir:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>const puppeteer = require('puppeteer');
const axios = require('axios');
const fs = require('fs');
const path = require('path');

// --- AYARLAR ---
const TELEGRAM_BOT_TOKEN = 'BURAYA_BOT_TOKEN';
const TELEGRAM_CHAT_ID = 'BURAYA_CHAT_ID';
const KONTROL_PERIYODU_DAKIKA = 45;
const LOG_DOSYASI = path.join(__dirname, 'urun_gecmisi.json');

const URUNLER = [
  {
    isim: 'ASUS RTX 4070 Ti Ekran Kartı',
    url: 'https://www.ornek-site.com/asus-rtx-4070-ti-p-12345',
    hedefFiyat: 32000,
    selector: '.product-price, [data-test-id="price-current-price"]'
  },
  {
    isim: 'Samsung 27" 2K 165Hz Monitör',
    url: 'https://www.ornek-site.com/samsung-27-monitor-p-67890',
    hedefFiyat: 8500,
    selector: '.product-price, .current-price-box'
  }
];

const bekle = (ms) =&gt; new Promise((resolve) =&gt; setTimeout(resolve, ms));

async function telegramBildir(mesaj) {
  const url = `https://api.telegram.org/bot&#36;{TELEGRAM_BOT_TOKEN}/sendMessage`;
  try {
    await axios.post(url, {
      chat_id: TELEGRAM_CHAT_ID,
      text: mesaj,
      parse_mode: 'HTML'
    });
  } catch (err) {
    console.error('Telegram hata:', err.message);
  }
}

function fiyatiSayiyaCevir(fiyatMetni) {
  if (!fiyatMetni) return null;
  const temiz = fiyatMetni
    .replace(/[^&#92;d,&#92;.]/g, '')
    .replace(/&#92;./g, '')
    .replace(',', '.');
  return parseFloat(temiz);
}

/**
 * Fiyatı urun_gecmisi.json dosyasına tarih ve saatle ekleyen fonksiyon
 */
function fiyatKaydet(urunAdi, guncelFiyat) {
  let gecmisVeri = {};

  // Dosya zaten varsa mevcut veriyi oku
  if (fs.existsSync(LOG_DOSYASI)) {
    try {
      const hamIcerik = fs.readFileSync(LOG_DOSYASI, 'utf8');
      gecmisVeri = hamIcerik ? JSON.parse(hamIcerik) : {};
    } catch (e) {
      gecmisVeri = {};
    }
  }

  // Bu ürün için daha önce dizi açılmadıysa oluştur
  if (!gecmisVeri[urunAdi]) {
    gecmisVeri[urunAdi] = [];
  }

  const simdi = new Date();
  const yeniKayit = {
    tarih: simdi.toLocaleDateString('tr-TR'),
    saat: simdi.toLocaleTimeString('tr-TR'),
    fiyat: guncelFiyat
  };

  // Yeni fiyat kaydını ürünün geçmişine ekle
  gecmisVeri[urunAdi].push(yeniKayit);

  // Dosyaya düzenli ve okunaklı (2 boşluk girintili) yaz
  fs.writeFileSync(LOG_DOSYASI, JSON.stringify(gecmisVeri, null, 2), 'utf8');
  console.log(`? [JSON Log] &#36;{urunAdi} için &#36;{guncelFiyat} TL kaydedildi.`);
}

/**
 * Ana Kontrol Döngüsü
 */
async function tumListeyiKontrolEt() {
  console.log(`&#92;n==================================================`);
  console.log(`[&#36;{new Date().toLocaleTimeString('tr-TR')}] Fiyat kontrolü ve loglama başlatıldı...`);
  console.log(`==================================================`);

  let browser = null;

  try {
    browser = await puppeteer.launch({
      headless: 'new',
      args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu']
    });

    const page = await browser.newPage();
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36');

    await page.setRequestInterception(true);
    page.on('request', (req) =&gt; {
      if (['image', 'font', 'media'].includes(req.resourceType())) {
        req.abort();
      } else {
        req.continue();
      }
    });

    for (let i = 0; i &lt; URUNLER.length; i++) {
      const urun = URUNLER[i];
      console.log(`&#92;n[&#36;{i + 1}/&#36;{URUNLER.length}] Kontrol: &#36;{urun.isim}`);

      try {
        await page.goto(urun.url, { waitUntil: 'domcontentloaded', timeout: 35000 });

        const fiyatMetni = await page.evaluate((secici) =&gt; {
          const eleman = document.querySelector(secici);
          return eleman ? eleman.innerText.trim() : null;
        }, urun.selector);

        if (!fiyatMetni) {
          console.log(`⚠️ Fiyat etiketi bulunamadı!`);
          continue;
        }

        const guncelFiyat = fiyatiSayiyaCevir(fiyatMetni);
        console.log(`Fiyat: &#36;{guncelFiyat} TL | Hedef: &#36;{urun.hedefFiyat} TL`);

        // 1. JSON DOSYASINA LOGLA
        if (guncelFiyat) {
          fiyatKaydet(urun.isim, guncelFiyat);
        }

        // 2. İNDİRİM VARSA TELEGRAM BİLDİRİMİ AT
        if (guncelFiyat &amp;&amp; guncelFiyat &lt;= urun.hedefFiyat) {
          const alarm = `
? &lt;b&gt;İNDİRİM ALARMI!&lt;/b&gt; ?
━━━━━━━━━━━━━━━━━━━━
? &lt;b&gt;Ürün:&lt;/b&gt; &#36;{urun.isim}
? &lt;b&gt;Hedef:&lt;/b&gt; &#36;{urun.hedefFiyat} TL
? &lt;b&gt;FİYAT:&lt;/b&gt; &lt;b&gt;&#36;{guncelFiyat} TL&lt;/b&gt;
⏰ &lt;b&gt;Tarih/Saat:&lt;/b&gt; &#36;{new Date().toLocaleString('tr-TR')}
━━━━━━━━━━━━━━━━━━━━
? &lt;a href="&#36;{urun.url}"&gt;Ürünü Aç&lt;/a&gt;
          `;
          await telegramBildir(alarm);
        }

      } catch (err) {
        console.error(`"&#36;{urun.isim}" hata:`, err.message);
      }

      await bekle(Math.floor(Math.random() * 3000) + 3000);
    }

  } catch (genelHata) {
    console.error('Genel hata:', genelHata.message);
  } finally {
    if (browser) {
      await browser.close();
      console.log(`&#92;nTarama tamamlandı. Sonraki kontrol &#36;{KONTROL_PERIYODU_DAKIKA} dakika sonra.`);
    }
  }
}

tumListeyiKontrolEt();
setInterval(tumListeyiKontrolEt, KONTROL_PERIYODU_DAKIKA * 60 * 1000);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">3. Bu Log Verisiyle İleride Neler Yapılabilir?</span></span><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Fiyat Değişmediyse Log Boyutunu Koruma:</span> İsterseniz son kaydedilen fiyat ile anlık fiyat aynıysa dosyaya tekrar yazmayıp sadece fiyat değiştiğinde satır ekletebilirsiniz.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">HTML / Chart.js ile Grafik Çizdirme:</span> Bu JSON dosyasını okuyup tarayıcıda ürünün fiyat grafiğini çizdiren tek sayfalık mini bir HTML/JS arayüzü kurulabilir.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Excel Çıktısı (CSV Export):</span> Tek fonksiyonla bu JSON dosyasını Excel'in anlayacağı `.csv` formatına dönüştürüp haftalık rapor alabilirsiniz.<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">JSON dosyasına eklemek istediğiniz farklı alanlar (satıcı adı, stok var/yok durumu vb.) varsa sorularınızı bu başlık altından paylaşabilirsiniz!</span>]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Hazır Kod: Fiyat Takip Botuna JSON Veri Loglama (Fiyat Geçmişi &amp; Grafik Altyapısı Ekleme)</span></span><br />
<br />
Fiyat takip botlarında sadece anlık bildirim almak bir süre sonra yetersiz kalır. Ürünün son 1 haftada veya 1 ayda gördüğü en dip fiyatı, hangi günlerde indirime girdiğini ve satıcının bindirim yapıp yapmadığını analiz etmek için <span style="font-weight: bold;" class="mycode_b">fiyat geçmişini yerel bir dosyada kayıt altında tutmak</span> gerekir.<br />
<br />
Node.js'in yerleşik <span style="font-weight: bold;" class="mycode_b">fs</span> (File System) modülü sayesinde harici hiçbir veritabanı (MySQL/MongoDB vb.) kurmaya gerek kalmadan, her taramada fiyatları <span style="font-weight: bold;" class="mycode_b">urun_gecmisi.json</span> dosyasına tarih ve saat damgasıyla otomatik işleyebiliriz.<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. JSON Dosyasının Yapısı Nasıl Görünecek?</span></span><br />
<br />
Bot çalıştıkça aynı dizinde otomatik olarak şu formatta temiz bir arşiv oluşacaktır:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>{
  "ASUS RTX 4070 Ti Ekran Kartı": [
    {
      "tarih": "17.10.2026",
      "saat": "14:30:15",
      "fiyat": 34500
    },
    {
      "tarih": "17.10.2026",
      "saat": "15:15:20",
      "fiyat": 31999
    }
  ]
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">2. JSON Loglama Entegre Edilmiş Tam Kod (fiyat_takip_loglu.js)</span></span><br />
<br />
Klasörünüzdeki koda sadece <span style="font-weight: bold;" class="mycode_b">fs</span> modülü ve <span style="font-weight: bold;" class="mycode_b">fiyatKaydet()</span> fonksiyonu eklenmiştir:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>const puppeteer = require('puppeteer');
const axios = require('axios');
const fs = require('fs');
const path = require('path');

// --- AYARLAR ---
const TELEGRAM_BOT_TOKEN = 'BURAYA_BOT_TOKEN';
const TELEGRAM_CHAT_ID = 'BURAYA_CHAT_ID';
const KONTROL_PERIYODU_DAKIKA = 45;
const LOG_DOSYASI = path.join(__dirname, 'urun_gecmisi.json');

const URUNLER = [
  {
    isim: 'ASUS RTX 4070 Ti Ekran Kartı',
    url: 'https://www.ornek-site.com/asus-rtx-4070-ti-p-12345',
    hedefFiyat: 32000,
    selector: '.product-price, [data-test-id="price-current-price"]'
  },
  {
    isim: 'Samsung 27" 2K 165Hz Monitör',
    url: 'https://www.ornek-site.com/samsung-27-monitor-p-67890',
    hedefFiyat: 8500,
    selector: '.product-price, .current-price-box'
  }
];

const bekle = (ms) =&gt; new Promise((resolve) =&gt; setTimeout(resolve, ms));

async function telegramBildir(mesaj) {
  const url = `https://api.telegram.org/bot&#36;{TELEGRAM_BOT_TOKEN}/sendMessage`;
  try {
    await axios.post(url, {
      chat_id: TELEGRAM_CHAT_ID,
      text: mesaj,
      parse_mode: 'HTML'
    });
  } catch (err) {
    console.error('Telegram hata:', err.message);
  }
}

function fiyatiSayiyaCevir(fiyatMetni) {
  if (!fiyatMetni) return null;
  const temiz = fiyatMetni
    .replace(/[^&#92;d,&#92;.]/g, '')
    .replace(/&#92;./g, '')
    .replace(',', '.');
  return parseFloat(temiz);
}

/**
 * Fiyatı urun_gecmisi.json dosyasına tarih ve saatle ekleyen fonksiyon
 */
function fiyatKaydet(urunAdi, guncelFiyat) {
  let gecmisVeri = {};

  // Dosya zaten varsa mevcut veriyi oku
  if (fs.existsSync(LOG_DOSYASI)) {
    try {
      const hamIcerik = fs.readFileSync(LOG_DOSYASI, 'utf8');
      gecmisVeri = hamIcerik ? JSON.parse(hamIcerik) : {};
    } catch (e) {
      gecmisVeri = {};
    }
  }

  // Bu ürün için daha önce dizi açılmadıysa oluştur
  if (!gecmisVeri[urunAdi]) {
    gecmisVeri[urunAdi] = [];
  }

  const simdi = new Date();
  const yeniKayit = {
    tarih: simdi.toLocaleDateString('tr-TR'),
    saat: simdi.toLocaleTimeString('tr-TR'),
    fiyat: guncelFiyat
  };

  // Yeni fiyat kaydını ürünün geçmişine ekle
  gecmisVeri[urunAdi].push(yeniKayit);

  // Dosyaya düzenli ve okunaklı (2 boşluk girintili) yaz
  fs.writeFileSync(LOG_DOSYASI, JSON.stringify(gecmisVeri, null, 2), 'utf8');
  console.log(`? [JSON Log] &#36;{urunAdi} için &#36;{guncelFiyat} TL kaydedildi.`);
}

/**
 * Ana Kontrol Döngüsü
 */
async function tumListeyiKontrolEt() {
  console.log(`&#92;n==================================================`);
  console.log(`[&#36;{new Date().toLocaleTimeString('tr-TR')}] Fiyat kontrolü ve loglama başlatıldı...`);
  console.log(`==================================================`);

  let browser = null;

  try {
    browser = await puppeteer.launch({
      headless: 'new',
      args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu']
    });

    const page = await browser.newPage();
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36');

    await page.setRequestInterception(true);
    page.on('request', (req) =&gt; {
      if (['image', 'font', 'media'].includes(req.resourceType())) {
        req.abort();
      } else {
        req.continue();
      }
    });

    for (let i = 0; i &lt; URUNLER.length; i++) {
      const urun = URUNLER[i];
      console.log(`&#92;n[&#36;{i + 1}/&#36;{URUNLER.length}] Kontrol: &#36;{urun.isim}`);

      try {
        await page.goto(urun.url, { waitUntil: 'domcontentloaded', timeout: 35000 });

        const fiyatMetni = await page.evaluate((secici) =&gt; {
          const eleman = document.querySelector(secici);
          return eleman ? eleman.innerText.trim() : null;
        }, urun.selector);

        if (!fiyatMetni) {
          console.log(`⚠️ Fiyat etiketi bulunamadı!`);
          continue;
        }

        const guncelFiyat = fiyatiSayiyaCevir(fiyatMetni);
        console.log(`Fiyat: &#36;{guncelFiyat} TL | Hedef: &#36;{urun.hedefFiyat} TL`);

        // 1. JSON DOSYASINA LOGLA
        if (guncelFiyat) {
          fiyatKaydet(urun.isim, guncelFiyat);
        }

        // 2. İNDİRİM VARSA TELEGRAM BİLDİRİMİ AT
        if (guncelFiyat &amp;&amp; guncelFiyat &lt;= urun.hedefFiyat) {
          const alarm = `
? &lt;b&gt;İNDİRİM ALARMI!&lt;/b&gt; ?
━━━━━━━━━━━━━━━━━━━━
? &lt;b&gt;Ürün:&lt;/b&gt; &#36;{urun.isim}
? &lt;b&gt;Hedef:&lt;/b&gt; &#36;{urun.hedefFiyat} TL
? &lt;b&gt;FİYAT:&lt;/b&gt; &lt;b&gt;&#36;{guncelFiyat} TL&lt;/b&gt;
⏰ &lt;b&gt;Tarih/Saat:&lt;/b&gt; &#36;{new Date().toLocaleString('tr-TR')}
━━━━━━━━━━━━━━━━━━━━
? &lt;a href="&#36;{urun.url}"&gt;Ürünü Aç&lt;/a&gt;
          `;
          await telegramBildir(alarm);
        }

      } catch (err) {
        console.error(`"&#36;{urun.isim}" hata:`, err.message);
      }

      await bekle(Math.floor(Math.random() * 3000) + 3000);
    }

  } catch (genelHata) {
    console.error('Genel hata:', genelHata.message);
  } finally {
    if (browser) {
      await browser.close();
      console.log(`&#92;nTarama tamamlandı. Sonraki kontrol &#36;{KONTROL_PERIYODU_DAKIKA} dakika sonra.`);
    }
  }
}

tumListeyiKontrolEt();
setInterval(tumListeyiKontrolEt, KONTROL_PERIYODU_DAKIKA * 60 * 1000);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">3. Bu Log Verisiyle İleride Neler Yapılabilir?</span></span><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Fiyat Değişmediyse Log Boyutunu Koruma:</span> İsterseniz son kaydedilen fiyat ile anlık fiyat aynıysa dosyaya tekrar yazmayıp sadece fiyat değiştiğinde satır ekletebilirsiniz.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">HTML / Chart.js ile Grafik Çizdirme:</span> Bu JSON dosyasını okuyup tarayıcıda ürünün fiyat grafiğini çizdiren tek sayfalık mini bir HTML/JS arayüzü kurulabilir.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Excel Çıktısı (CSV Export):</span> Tek fonksiyonla bu JSON dosyasını Excel'in anlayacağı `.csv` formatına dönüştürüp haftalık rapor alabilirsiniz.<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">JSON dosyasına eklemek istediğiniz farklı alanlar (satıcı adı, stok var/yok durumu vb.) varsa sorularınızı bu başlık altından paylaşabilirsiniz!</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Hazır Kod: Çoklu Ürün Fiyat Takip Botu (10+ Farklı Ürünü Sırayla Gezen Dizi Mimarisi)]]></title>
			<link>https://botbb.tr/Thread-hazir-kod-coklu-urun-fiyat-takip-botu-10-farkli-urunu-sirayla-gezen-dizi-mimarisi</link>
			<pubDate>Sat, 17 Oct 2026 19:37:16 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://botbb.tr/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://botbb.tr/Thread-hazir-kod-coklu-urun-fiyat-takip-botu-10-farkli-urunu-sirayla-gezen-dizi-mimarisi</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Hazır Kod: Çoklu Ürün Fiyat Takip Botu (10+ Farklı Ürünü Sırayla Gezen Dizi Mimarisi)</span></span><br />
<br />
Önceki rehberimizde tek bir ürün linkini kontrol eden yapıyı kurmuştuk. Ancak gerçek hayatta takip etmek istediğimiz birden fazla ürün (ekran kartı, monitör, kahve makinesi, telefon vb.) olur.<br />
<br />
Her ürün için ayrı bir script çalıştırmak RAM'i tüketir. Doğru mühendislik yaklaşımı: <span style="font-weight: bold;" class="mycode_b">Tüm ürünleri ve hedef fiyatlarını bir dizi (Array) içinde tanımlamak, tek bir tarayıcı açıp ürünleri sırayla gezmek ve işlem bitince tarayıcıyı kapatmaktır.</span><br />
<br />
Bu rehberde siteler tarafından engellenmemek (IP ban yememek) için aralara rastgele gecikmeler koyan çoklu takip mimarisini paylaşıyorum.<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. Çalışan Tam Kod (coklu_fiyat_takip.js)</span></span><br />
<br />
Klasörünüzde <span style="font-weight: bold;" class="mycode_b">coklu_fiyat_takip.js</span> dosyası oluşturup aşağıdaki kodları yapıştırın:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>const puppeteer = require('puppeteer');
const axios = require('axios');

// --- TELEGRAM AYARLARI ---
const TELEGRAM_BOT_TOKEN = 'BURAYA_BOT_TOKEN';
const TELEGRAM_CHAT_ID = 'BURAYA_CHAT_ID';

// Kaç dakikada bir tüm liste baştan kontrol edilsin?
const KONTROL_PERIYODU_DAKIKA = 45;

// --- TAKİP EDİLECEK ÜRÜNLER LİSTESİ ---
// Her ürünün adını, linkini, hedef fiyatını ve sitenin fiyat etiketini (selector) buraya ekleyin
const URUNLER = [
  {
    isim: 'ASUS RTX 4070 Ti Ekran Kartı',
    url: 'https://www.ornek-site.com/asus-rtx-4070-ti-p-12345',
    hedefFiyat: 32000,
    selector: '.product-price, [data-test-id="price-current-price"]'
  },
  {
    isim: 'Samsung 27" 2K 165Hz Monitör',
    url: 'https://www.ornek-site.com/samsung-27-monitor-p-67890',
    hedefFiyat: 8500,
    selector: '.product-price, .current-price-box'
  },
  {
    isim: 'Philips Airfryer XXL',
    url: 'https://www.ornek-site.com/philips-airfryer-xxl-p-55443',
    hedefFiyat: 5200,
    selector: '.price, .product-price-current'
  },
  {
    isim: 'Sony WH-1000XM5 Kulaklık',
    url: 'https://www.ornek-site.com/sony-wh1000xm5-p-99881',
    hedefFiyat: 11500,
    selector: '.price'
  }
];

// İnsansı rastgele bekleme fonksiyonu (ms)
const bekle = (ms) =&gt; new Promise((resolve) =&gt; setTimeout(resolve, ms));

async function telegramBildir(mesaj) {
  const url = `https://api.telegram.org/bot&#36;{TELEGRAM_BOT_TOKEN}/sendMessage`;
  try {
    await axios.post(url, {
      chat_id: TELEGRAM_CHAT_ID,
      text: mesaj,
      parse_mode: 'HTML',
      disable_web_page_preview: false
    });
  } catch (err) {
    console.error('Telegram hata:', err.message);
  }
}

function fiyatiSayiyaCevir(fiyatMetni) {
  if (!fiyatMetni) return null;
  const temiz = fiyatMetni
    .replace(/[^&#92;d,&#92;.]/g, '')
    .replace(/&#92;./g, '')
    .replace(',', '.');
  return parseFloat(temiz);
}

/**
 * Tüm ürünleri tek bir tarayıcı oturumunda sırayla gezen ana döngü
 */
async function tumListeyiKontrolEt() {
  console.log(`&#92;n==================================================`);
  console.log(`[&#36;{new Date().toLocaleTimeString('tr-TR')}] Toplam &#36;{URUNLER.length} ürün taranıyor...`);
  console.log(`==================================================`);

  let browser = null;

  try {
    browser = await puppeteer.launch({
      headless: 'new',
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage',
        '--disable-gpu'
      ]
    });

    const page = await browser.newPage();
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36');

    // Resimleri ve gereksiz medya isteklerini engelleyerek hızı 4 katına çıkarın
    await page.setRequestInterception(true);
    page.on('request', (req) =&gt; {
      if (['image', 'font', 'media'].includes(req.resourceType())) {
        req.abort();
      } else {
        req.continue();
      }
    });

    // Ürünleri sırayla gez
    for (let i = 0; i &lt; URUNLER.length; i++) {
      const urun = URUNLER[i];
      console.log(`&#92;n[&#36;{i + 1}/&#36;{URUNLER.length}] İnceleniyor: &#36;{urun.isim}`);

      try {
        await page.goto(urun.url, { waitUntil: 'domcontentloaded', timeout: 35000 });

        // Sayfadaki fiyat bilgisini oku
        const cekilenFiyatMetni = await page.evaluate((secici) =&gt; {
          const eleman = document.querySelector(secici);
          return eleman ? eleman.innerText.trim() : null;
        }, urun.selector);

        if (!cekilenFiyatMetni) {
          console.log(`⚠️ Fiyat etiketi bulunamadı! Sayfa yapısı değişmiş veya bot engeli olabilir.`);
          continue;
        }

        const guncelFiyat = fiyatiSayiyaCevir(cekilenFiyatMetni);
        console.log(`Güncel: &#36;{guncelFiyat} TL | Hedef: &#36;{urun.hedefFiyat} TL`);

        // Hedef fiyat kontrolü
        if (guncelFiyat &amp;&amp; guncelFiyat &lt;= urun.hedefFiyat) {
          console.log(`? İNDİRİM YAKALANDI! Telegram'a gönderiliyor...`);
          
          const alarm = `
? &lt;b&gt;İNDİRİM YAKALANDI!&lt;/b&gt; ?
━━━━━━━━━━━━━━━━━━━━
? &lt;b&gt;Ürün:&lt;/b&gt; &#36;{urun.isim}
? &lt;b&gt;Hedef Fiyat:&lt;/b&gt; &#36;{urun.hedefFiyat} TL
? &lt;b&gt;GÜNCEL FİYAT:&lt;/b&gt; &lt;b&gt;&#36;{guncelFiyat} TL&lt;/b&gt;
⏰ &lt;b&gt;Saat:&lt;/b&gt; &#36;{new Date().toLocaleTimeString('tr-TR')}
━━━━━━━━━━━━━━━━━━━━
? &lt;a href="&#36;{urun.url}"&gt;Hemen Ürüne Git&lt;/a&gt;
          `;

          await telegramBildir(alarm);
        } else {
          console.log(`Fiyat henüz istenen seviyede değil.`);
        }

      } catch (urunHatasi) {
        console.error(`"&#36;{urun.isim}" kontrol edilirken hata:`, urunHatasi.message);
      }

      // Sitenin bot olduğumuzu anlamaması için iki ürün arasında 3-6 saniye rastgele bekle
      const beklemeSuresi = Math.floor(Math.random() * 3000) + 3000;
      await bekle(beklemeSuresi);
    }

  } catch (genelHata) {
    console.error('Genel tarama hatası:', genelHata.message);
  } finally {
    if (browser) {
      await browser.close();
      console.log(`&#92;nTarama tamamlandı, tarayıcı kapatıldı. Bir sonraki kontrol &#36;{KONTROL_PERIYODU_DAKIKA} dakika sonra.`);
    }
  }
}

// İlk çalıştırma
tumListeyiKontrolEt();

// Belirlenen periyotta sürekli çalış
setInterval(tumListeyiKontrolEt, KONTROL_PERIYODU_DAKIKA * 60 * 1000);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">2. Neden Bu Yapıyı Kullanmalıyız?</span></span><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Tek Tarayıcı Örneği (Zero Leak):</span> 10 ürün için 10 ayrı tarayıcı açılmaz. Tek bir Chromium sayfası kullanılır ve liste bitince süreç tamamen kapatılarak RAM belleğe geri verilir.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">İnsansı Gecikme (Random Delay):</span> Döngü içinde her ürün arasında rastgele 3 ile 6 saniye beklenir (<span style="font-style: italic;" class="mycode_i">bekle(beklemeSuresi)</span>). Bu sayede pazar yeri siteleri ardı ardına makine gibi istek aldıklarını fark edip IP adresinizi bloklamaz.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Kolayca Genişletilebilir:</span> İleride 50 ürün eklemek isterseniz sadece <span style="font-weight: bold;" class="mycode_b">URUNLER</span> dizisine yeni bir süslü parantez `{ ... }` bloğu eklemeniz yeterlidir.<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">Kendi listenizdeki ürünleri denerken takıldığınız bir selector veya site olursa linki paylaşın, seçici kodunu birlikte çıkaralım!</span>]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Hazır Kod: Çoklu Ürün Fiyat Takip Botu (10+ Farklı Ürünü Sırayla Gezen Dizi Mimarisi)</span></span><br />
<br />
Önceki rehberimizde tek bir ürün linkini kontrol eden yapıyı kurmuştuk. Ancak gerçek hayatta takip etmek istediğimiz birden fazla ürün (ekran kartı, monitör, kahve makinesi, telefon vb.) olur.<br />
<br />
Her ürün için ayrı bir script çalıştırmak RAM'i tüketir. Doğru mühendislik yaklaşımı: <span style="font-weight: bold;" class="mycode_b">Tüm ürünleri ve hedef fiyatlarını bir dizi (Array) içinde tanımlamak, tek bir tarayıcı açıp ürünleri sırayla gezmek ve işlem bitince tarayıcıyı kapatmaktır.</span><br />
<br />
Bu rehberde siteler tarafından engellenmemek (IP ban yememek) için aralara rastgele gecikmeler koyan çoklu takip mimarisini paylaşıyorum.<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. Çalışan Tam Kod (coklu_fiyat_takip.js)</span></span><br />
<br />
Klasörünüzde <span style="font-weight: bold;" class="mycode_b">coklu_fiyat_takip.js</span> dosyası oluşturup aşağıdaki kodları yapıştırın:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>const puppeteer = require('puppeteer');
const axios = require('axios');

// --- TELEGRAM AYARLARI ---
const TELEGRAM_BOT_TOKEN = 'BURAYA_BOT_TOKEN';
const TELEGRAM_CHAT_ID = 'BURAYA_CHAT_ID';

// Kaç dakikada bir tüm liste baştan kontrol edilsin?
const KONTROL_PERIYODU_DAKIKA = 45;

// --- TAKİP EDİLECEK ÜRÜNLER LİSTESİ ---
// Her ürünün adını, linkini, hedef fiyatını ve sitenin fiyat etiketini (selector) buraya ekleyin
const URUNLER = [
  {
    isim: 'ASUS RTX 4070 Ti Ekran Kartı',
    url: 'https://www.ornek-site.com/asus-rtx-4070-ti-p-12345',
    hedefFiyat: 32000,
    selector: '.product-price, [data-test-id="price-current-price"]'
  },
  {
    isim: 'Samsung 27" 2K 165Hz Monitör',
    url: 'https://www.ornek-site.com/samsung-27-monitor-p-67890',
    hedefFiyat: 8500,
    selector: '.product-price, .current-price-box'
  },
  {
    isim: 'Philips Airfryer XXL',
    url: 'https://www.ornek-site.com/philips-airfryer-xxl-p-55443',
    hedefFiyat: 5200,
    selector: '.price, .product-price-current'
  },
  {
    isim: 'Sony WH-1000XM5 Kulaklık',
    url: 'https://www.ornek-site.com/sony-wh1000xm5-p-99881',
    hedefFiyat: 11500,
    selector: '.price'
  }
];

// İnsansı rastgele bekleme fonksiyonu (ms)
const bekle = (ms) =&gt; new Promise((resolve) =&gt; setTimeout(resolve, ms));

async function telegramBildir(mesaj) {
  const url = `https://api.telegram.org/bot&#36;{TELEGRAM_BOT_TOKEN}/sendMessage`;
  try {
    await axios.post(url, {
      chat_id: TELEGRAM_CHAT_ID,
      text: mesaj,
      parse_mode: 'HTML',
      disable_web_page_preview: false
    });
  } catch (err) {
    console.error('Telegram hata:', err.message);
  }
}

function fiyatiSayiyaCevir(fiyatMetni) {
  if (!fiyatMetni) return null;
  const temiz = fiyatMetni
    .replace(/[^&#92;d,&#92;.]/g, '')
    .replace(/&#92;./g, '')
    .replace(',', '.');
  return parseFloat(temiz);
}

/**
 * Tüm ürünleri tek bir tarayıcı oturumunda sırayla gezen ana döngü
 */
async function tumListeyiKontrolEt() {
  console.log(`&#92;n==================================================`);
  console.log(`[&#36;{new Date().toLocaleTimeString('tr-TR')}] Toplam &#36;{URUNLER.length} ürün taranıyor...`);
  console.log(`==================================================`);

  let browser = null;

  try {
    browser = await puppeteer.launch({
      headless: 'new',
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage',
        '--disable-gpu'
      ]
    });

    const page = await browser.newPage();
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36');

    // Resimleri ve gereksiz medya isteklerini engelleyerek hızı 4 katına çıkarın
    await page.setRequestInterception(true);
    page.on('request', (req) =&gt; {
      if (['image', 'font', 'media'].includes(req.resourceType())) {
        req.abort();
      } else {
        req.continue();
      }
    });

    // Ürünleri sırayla gez
    for (let i = 0; i &lt; URUNLER.length; i++) {
      const urun = URUNLER[i];
      console.log(`&#92;n[&#36;{i + 1}/&#36;{URUNLER.length}] İnceleniyor: &#36;{urun.isim}`);

      try {
        await page.goto(urun.url, { waitUntil: 'domcontentloaded', timeout: 35000 });

        // Sayfadaki fiyat bilgisini oku
        const cekilenFiyatMetni = await page.evaluate((secici) =&gt; {
          const eleman = document.querySelector(secici);
          return eleman ? eleman.innerText.trim() : null;
        }, urun.selector);

        if (!cekilenFiyatMetni) {
          console.log(`⚠️ Fiyat etiketi bulunamadı! Sayfa yapısı değişmiş veya bot engeli olabilir.`);
          continue;
        }

        const guncelFiyat = fiyatiSayiyaCevir(cekilenFiyatMetni);
        console.log(`Güncel: &#36;{guncelFiyat} TL | Hedef: &#36;{urun.hedefFiyat} TL`);

        // Hedef fiyat kontrolü
        if (guncelFiyat &amp;&amp; guncelFiyat &lt;= urun.hedefFiyat) {
          console.log(`? İNDİRİM YAKALANDI! Telegram'a gönderiliyor...`);
          
          const alarm = `
? &lt;b&gt;İNDİRİM YAKALANDI!&lt;/b&gt; ?
━━━━━━━━━━━━━━━━━━━━
? &lt;b&gt;Ürün:&lt;/b&gt; &#36;{urun.isim}
? &lt;b&gt;Hedef Fiyat:&lt;/b&gt; &#36;{urun.hedefFiyat} TL
? &lt;b&gt;GÜNCEL FİYAT:&lt;/b&gt; &lt;b&gt;&#36;{guncelFiyat} TL&lt;/b&gt;
⏰ &lt;b&gt;Saat:&lt;/b&gt; &#36;{new Date().toLocaleTimeString('tr-TR')}
━━━━━━━━━━━━━━━━━━━━
? &lt;a href="&#36;{urun.url}"&gt;Hemen Ürüne Git&lt;/a&gt;
          `;

          await telegramBildir(alarm);
        } else {
          console.log(`Fiyat henüz istenen seviyede değil.`);
        }

      } catch (urunHatasi) {
        console.error(`"&#36;{urun.isim}" kontrol edilirken hata:`, urunHatasi.message);
      }

      // Sitenin bot olduğumuzu anlamaması için iki ürün arasında 3-6 saniye rastgele bekle
      const beklemeSuresi = Math.floor(Math.random() * 3000) + 3000;
      await bekle(beklemeSuresi);
    }

  } catch (genelHata) {
    console.error('Genel tarama hatası:', genelHata.message);
  } finally {
    if (browser) {
      await browser.close();
      console.log(`&#92;nTarama tamamlandı, tarayıcı kapatıldı. Bir sonraki kontrol &#36;{KONTROL_PERIYODU_DAKIKA} dakika sonra.`);
    }
  }
}

// İlk çalıştırma
tumListeyiKontrolEt();

// Belirlenen periyotta sürekli çalış
setInterval(tumListeyiKontrolEt, KONTROL_PERIYODU_DAKIKA * 60 * 1000);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">2. Neden Bu Yapıyı Kullanmalıyız?</span></span><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Tek Tarayıcı Örneği (Zero Leak):</span> 10 ürün için 10 ayrı tarayıcı açılmaz. Tek bir Chromium sayfası kullanılır ve liste bitince süreç tamamen kapatılarak RAM belleğe geri verilir.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">İnsansı Gecikme (Random Delay):</span> Döngü içinde her ürün arasında rastgele 3 ile 6 saniye beklenir (<span style="font-style: italic;" class="mycode_i">bekle(beklemeSuresi)</span>). Bu sayede pazar yeri siteleri ardı ardına makine gibi istek aldıklarını fark edip IP adresinizi bloklamaz.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Kolayca Genişletilebilir:</span> İleride 50 ürün eklemek isterseniz sadece <span style="font-weight: bold;" class="mycode_b">URUNLER</span> dizisine yeni bir süslü parantez `{ ... }` bloğu eklemeniz yeterlidir.<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">Kendi listenizdeki ürünleri denerken takıldığınız bir selector veya site olursa linki paylaşın, seçici kodunu birlikte çıkaralım!</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Rehber & Hazır Kod: Puppeteer ile Fiyat Takip Botu Yapımı]]></title>
			<link>https://botbb.tr/Thread-rehber-hazir-kod-puppeteer-ile-fiyat-takip-botu-yapimi</link>
			<pubDate>Sat, 17 Oct 2026 19:35:30 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://botbb.tr/member.php?action=profile&uid=1">admin</a>]]></dc:creator>
			<guid isPermaLink="false">https://botbb.tr/Thread-rehber-hazir-kod-puppeteer-ile-fiyat-takip-botu-yapimi</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Rehber &amp; Hazır Kod: Puppeteer ile Fiyat Takip Botu Yapımı (Fiyat Düşünce Telegram'a Alarm Gönderen Senaryo)</span></span><br />
<br />
Bir önceki konumuzda cep telefonumuza tek tıkla Telegram bildirimi atan hafif modülü kurmuştuk. Şimdi bu altyapıyı gerçek bir senaryoya bağlıyoruz: <span style="font-weight: bold;" class="mycode_b">Hedef bir e-ticaret sayfasındaki ürünün fiyatını belirli aralıklarla kontrol eden ve fiyat belirlediğimiz eşiğin altına indiğinde anında cep telefonumuza bildirim fırlatan bir fiyat takip botu.</span><br />
<br />
Bu senaryoda bot; sayfayı açacak, fiyat etiketini okuyacak, metindeki gereksiz simgeleri temizleyip sayıya çevirecek ve fiyat düştüyse linkiyle birlikte Telegram'a mesaj atacaktır.<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. Gerekli Kütüphaneler</span></span><br />
<br />
Boş bir klasör oluşturup terminal (CMD) üzerinden şu iki paketi kurun:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>npm install puppeteer axios</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">2. Hazır ve Çalışan Tam Kod (fiyat_takip.js)</span></span><br />
<br />
Klasörünüzde <span style="font-weight: bold;" class="mycode_b">fiyat_takip.js</span> dosyası oluşturun ve aşağıdaki kodları yapıştırın. <span style="font-weight: bold;" class="mycode_b">BOT_TOKEN</span> ve <span style="font-weight: bold;" class="mycode_b">CHAT_ID</span> alanlarına kendi bilgilerinizi girin:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>const puppeteer = require('puppeteer');
const axios = require('axios');

// --- AYARLAR ---
const TELEGRAM_BOT_TOKEN = 'BURAYA_BOT_TOKEN';
const TELEGRAM_CHAT_ID = 'BURAYA_CHAT_ID';

// Takip edilecek ürün bilgileri
const URUN_URL = 'https://www.hepsiburada.com/ornek-urun-linki-p-HBV00000XXXXX';
const HEDEF_FIYAT = 15000; // Bu fiyatın altına düşerse bildirim gelir (TL)
const KONTROL_PERIYODU_DAKIKA = 30; // Kaç dakikada bir kontrol edilsin?

/**
 * Telegram'a HTML formatlı mesaj gönderir
 */
async function telegramBildir(mesaj) {
  const url = `https://api.telegram.org/bot&#36;{TELEGRAM_BOT_TOKEN}/sendMessage`;
  try {
    await axios.post(url, {
      chat_id: TELEGRAM_CHAT_ID,
      text: mesaj,
      parse_mode: 'HTML',
      disable_web_page_preview: false
    });
    console.log(' Telegram bildirimi gönderildi!');
  } catch (err) {
    console.error('Telegram gönderim hatası:', err.message);
  }
}

/**
 * Sayfadaki fiyat metnini (örn: "14.499,90 TL") saf sayıya (14499.90) dönüştürür
 */
function fiyatiSayiyaCevir(fiyatMetni) {
  if (!fiyatMetni) return null;
  // Boşlukları, TL simgesini ve noktaları temizle, virgülü noktaya çevir
  const temiz = fiyatMetni
    .replace(/[^&#92;d,&#92;.]/g, '')
    .replace(/&#92;./g, '')
    .replace(',', '.');
  return parseFloat(temiz);
}

/**
 * Puppeteer ile sayfayı ziyaret edip güncel fiyatı çeken ana fonksiyon
 */
async function fiyatiKontrolEt() {
  console.log(`[&#36;{new Date().toLocaleTimeString('tr-TR')}] Fiyat kontrol ediliyor...`);
  
  let browser = null;
  try {
    browser = await puppeteer.launch({
      headless: 'new',
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage',
        '--disable-gpu'
      ]
    });

    const page = await browser.newPage();

    // Gerçekçi masaüstü User-Agent tanımlayarak bot tespitini azaltın
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36');

    // Hız kazanmak ve RAM tüketmemek için gereksiz resim ve fontları engelleyin
    await page.setRequestInterception(true);
    page.on('request', (req) =&gt; {
      if (['image', 'font', 'media'].includes(req.resourceType())) {
        req.abort();
      } else {
        req.continue();
      }
    });

    await page.goto(URUN_URL, { waitUntil: 'domcontentloaded', timeout: 35000 });

    // Sayfadaki fiyat ve ürün başlığı seçicileri (Selector)
    // NOT: İncele (Inspect) diyerek hedef sitenin etiket sınıfını buraya yazın
    const veri = await page.evaluate(() =&gt; {
      const baslik = document.querySelector('h1')?.innerText?.trim() || 'Ürün Başlığı Bulunamadı';
      
      // Çoğu e-ticaret sitesinde fiyat içeren yaygın selector kalıpları
      const fiyatElemani = document.querySelector('[data-test-id="price-current-price"]') || 
                          document.querySelector('.price') || 
                          document.querySelector('.product-price');
                          
      const fiyatHam = fiyatElemani ? fiyatElemani.innerText.trim() : null;
      return { baslik, fiyatHam };
    });

    if (!veri.fiyatHam) {
      console.log(' Fiyat etiketi sayfada bulunamadı! Selector değişmiş olabilir.');
      return;
    }

    const guncelFiyat = fiyatiSayiyaCevir(veri.fiyatHam);
    console.log(`Ürün: &#36;{veri.baslik}`);
    console.log(`Güncel Fiyat: &#36;{guncelFiyat} TL | Hedef: &#36;{HEDEF_FIYAT} TL`);

    // FİYAT DÜŞTÜ MÜ KONTROLÜ
    if (guncelFiyat &amp;&amp; guncelFiyat &lt;= HEDEF_FIYAT) {
      const alarmMesaji = `
? &lt;b&gt;İNDİRİM ALARMI! FİYAT DÜŞTÜ&lt;/b&gt; ?
━━━━━━━━━━━━━━━━━━━━
? &lt;b&gt;Ürün:&lt;/b&gt; &#36;{veri.baslik}
? &lt;b&gt;Eski / Hedef Fiyat:&lt;/b&gt; &#36;{HEDEF_FIYAT} TL
? &lt;b&gt;GÜNCEL FİYAT:&lt;/b&gt; &lt;b&gt;&#36;{guncelFiyat} TL&lt;/b&gt;
⏰ &lt;b&gt;Zaman:&lt;/b&gt; &#36;{new Date().toLocaleTimeString('tr-TR')}
━━━━━━━━━━━━━━━━━━━━
? &lt;a href="&#36;{URUN_URL}"&gt;Ürüne Gitmek İçin Hemen Tıklayın&lt;/a&gt;
      `;

      await telegramBildir(alarmMesaji);
    } else {
      console.log(' Fiyat henüz hedef seviyeye düşmedi.');
    }

  } catch (hata) {
    console.error('Bot çalışma hatası:', hata.message);
  } finally {
    if (browser) {
      await browser.close();
    }
  }
}

// Botu hemen bir kez çalıştır
fiyatiKontrolEt();

// Belirlenen dakika aralığıyla döngüye sok
setInterval(fiyatiKontrolEt, KONTROL_PERIYODU_DAKIKA * 60 * 1000);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">3. Hedef Sitenin Fiyat Selector'ı Nasıl Bulunur?</span></span><br />
<br />
Her sitenin fiyat alanı farklıdır. Kendi takip etmek istediğiniz sitede doğru yeri yakalamak için:<br />
<ol type="1" class="mycode_list"><li>Ürün sayfasına gidin, fiyatın üzerine <span style="font-weight: bold;" class="mycode_b">Sağ Tık &gt; İncele (Inspect)</span> deyin.<br />
</li>
<li>Açılan kod penceresinde fiyatı barındıran etiketin <span style="font-weight: bold;" class="mycode_b">class</span> veya <span style="font-weight: bold;" class="mycode_b">id</span> değerine bakın (Örn: <span style="font-style: italic;" class="mycode_i">class="price-value"</span>).<br />
</li>
<li>Koddaki <span style="font-weight: bold;" class="mycode_b">document.querySelector('.price')</span> alanına o sınıfı yazmanız yeterlidir.<br />
</li>
</ol>
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">4. Arka Planda 7/24 Kesintisiz Çalıştırma (PM2 Taktigi)</span></span><br />
<br />
Terminali kapattığınızda botun durmasını istemiyorsanız, küresel olarak <span style="font-weight: bold;" class="mycode_b">PM2</span> sürec yöneticisini kurup botu arka plana atabilirsiniz:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>npm install -g pm2
pm2 start fiyat_takip.js --name "fiyat-botu"</code></div></div><br />
Artık bilgisayarınız veya sunucunuz açık olduğu sürece terminal penceresi kapalı olsa bile bot sessizce 30 dakikada bir kontrolü yapar, fiyat düştüğü anda telefonunuzu çaldırır.<br />
<br />
<blockquote class="mycode_quote"><cite>Alıntı:</cite><span style="font-weight: bold;" class="mycode_b">Geliştirme Önerisi:</span> Birden fazla ürünü takip etmek isterseniz kodun başındaki <span style="font-weight: bold;" class="mycode_b">URUN_URL</span> alanını bir dizi (array) haline getirip sırayla tüm linkleri döngüyle gezdirebilirsiniz.</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">Takip etmek istediğiniz sitede fiyatı yakalayamadığınız veya selector seçemediğiniz durumlar olursa sayfa linkini bu başlık altından paylaşın, birlikte bakalım!</span>]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Rehber &amp; Hazır Kod: Puppeteer ile Fiyat Takip Botu Yapımı (Fiyat Düşünce Telegram'a Alarm Gönderen Senaryo)</span></span><br />
<br />
Bir önceki konumuzda cep telefonumuza tek tıkla Telegram bildirimi atan hafif modülü kurmuştuk. Şimdi bu altyapıyı gerçek bir senaryoya bağlıyoruz: <span style="font-weight: bold;" class="mycode_b">Hedef bir e-ticaret sayfasındaki ürünün fiyatını belirli aralıklarla kontrol eden ve fiyat belirlediğimiz eşiğin altına indiğinde anında cep telefonumuza bildirim fırlatan bir fiyat takip botu.</span><br />
<br />
Bu senaryoda bot; sayfayı açacak, fiyat etiketini okuyacak, metindeki gereksiz simgeleri temizleyip sayıya çevirecek ve fiyat düştüyse linkiyle birlikte Telegram'a mesaj atacaktır.<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. Gerekli Kütüphaneler</span></span><br />
<br />
Boş bir klasör oluşturup terminal (CMD) üzerinden şu iki paketi kurun:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>npm install puppeteer axios</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">2. Hazır ve Çalışan Tam Kod (fiyat_takip.js)</span></span><br />
<br />
Klasörünüzde <span style="font-weight: bold;" class="mycode_b">fiyat_takip.js</span> dosyası oluşturun ve aşağıdaki kodları yapıştırın. <span style="font-weight: bold;" class="mycode_b">BOT_TOKEN</span> ve <span style="font-weight: bold;" class="mycode_b">CHAT_ID</span> alanlarına kendi bilgilerinizi girin:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>const puppeteer = require('puppeteer');
const axios = require('axios');

// --- AYARLAR ---
const TELEGRAM_BOT_TOKEN = 'BURAYA_BOT_TOKEN';
const TELEGRAM_CHAT_ID = 'BURAYA_CHAT_ID';

// Takip edilecek ürün bilgileri
const URUN_URL = 'https://www.hepsiburada.com/ornek-urun-linki-p-HBV00000XXXXX';
const HEDEF_FIYAT = 15000; // Bu fiyatın altına düşerse bildirim gelir (TL)
const KONTROL_PERIYODU_DAKIKA = 30; // Kaç dakikada bir kontrol edilsin?

/**
 * Telegram'a HTML formatlı mesaj gönderir
 */
async function telegramBildir(mesaj) {
  const url = `https://api.telegram.org/bot&#36;{TELEGRAM_BOT_TOKEN}/sendMessage`;
  try {
    await axios.post(url, {
      chat_id: TELEGRAM_CHAT_ID,
      text: mesaj,
      parse_mode: 'HTML',
      disable_web_page_preview: false
    });
    console.log(' Telegram bildirimi gönderildi!');
  } catch (err) {
    console.error('Telegram gönderim hatası:', err.message);
  }
}

/**
 * Sayfadaki fiyat metnini (örn: "14.499,90 TL") saf sayıya (14499.90) dönüştürür
 */
function fiyatiSayiyaCevir(fiyatMetni) {
  if (!fiyatMetni) return null;
  // Boşlukları, TL simgesini ve noktaları temizle, virgülü noktaya çevir
  const temiz = fiyatMetni
    .replace(/[^&#92;d,&#92;.]/g, '')
    .replace(/&#92;./g, '')
    .replace(',', '.');
  return parseFloat(temiz);
}

/**
 * Puppeteer ile sayfayı ziyaret edip güncel fiyatı çeken ana fonksiyon
 */
async function fiyatiKontrolEt() {
  console.log(`[&#36;{new Date().toLocaleTimeString('tr-TR')}] Fiyat kontrol ediliyor...`);
  
  let browser = null;
  try {
    browser = await puppeteer.launch({
      headless: 'new',
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage',
        '--disable-gpu'
      ]
    });

    const page = await browser.newPage();

    // Gerçekçi masaüstü User-Agent tanımlayarak bot tespitini azaltın
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36');

    // Hız kazanmak ve RAM tüketmemek için gereksiz resim ve fontları engelleyin
    await page.setRequestInterception(true);
    page.on('request', (req) =&gt; {
      if (['image', 'font', 'media'].includes(req.resourceType())) {
        req.abort();
      } else {
        req.continue();
      }
    });

    await page.goto(URUN_URL, { waitUntil: 'domcontentloaded', timeout: 35000 });

    // Sayfadaki fiyat ve ürün başlığı seçicileri (Selector)
    // NOT: İncele (Inspect) diyerek hedef sitenin etiket sınıfını buraya yazın
    const veri = await page.evaluate(() =&gt; {
      const baslik = document.querySelector('h1')?.innerText?.trim() || 'Ürün Başlığı Bulunamadı';
      
      // Çoğu e-ticaret sitesinde fiyat içeren yaygın selector kalıpları
      const fiyatElemani = document.querySelector('[data-test-id="price-current-price"]') || 
                          document.querySelector('.price') || 
                          document.querySelector('.product-price');
                          
      const fiyatHam = fiyatElemani ? fiyatElemani.innerText.trim() : null;
      return { baslik, fiyatHam };
    });

    if (!veri.fiyatHam) {
      console.log(' Fiyat etiketi sayfada bulunamadı! Selector değişmiş olabilir.');
      return;
    }

    const guncelFiyat = fiyatiSayiyaCevir(veri.fiyatHam);
    console.log(`Ürün: &#36;{veri.baslik}`);
    console.log(`Güncel Fiyat: &#36;{guncelFiyat} TL | Hedef: &#36;{HEDEF_FIYAT} TL`);

    // FİYAT DÜŞTÜ MÜ KONTROLÜ
    if (guncelFiyat &amp;&amp; guncelFiyat &lt;= HEDEF_FIYAT) {
      const alarmMesaji = `
? &lt;b&gt;İNDİRİM ALARMI! FİYAT DÜŞTÜ&lt;/b&gt; ?
━━━━━━━━━━━━━━━━━━━━
? &lt;b&gt;Ürün:&lt;/b&gt; &#36;{veri.baslik}
? &lt;b&gt;Eski / Hedef Fiyat:&lt;/b&gt; &#36;{HEDEF_FIYAT} TL
? &lt;b&gt;GÜNCEL FİYAT:&lt;/b&gt; &lt;b&gt;&#36;{guncelFiyat} TL&lt;/b&gt;
⏰ &lt;b&gt;Zaman:&lt;/b&gt; &#36;{new Date().toLocaleTimeString('tr-TR')}
━━━━━━━━━━━━━━━━━━━━
? &lt;a href="&#36;{URUN_URL}"&gt;Ürüne Gitmek İçin Hemen Tıklayın&lt;/a&gt;
      `;

      await telegramBildir(alarmMesaji);
    } else {
      console.log(' Fiyat henüz hedef seviyeye düşmedi.');
    }

  } catch (hata) {
    console.error('Bot çalışma hatası:', hata.message);
  } finally {
    if (browser) {
      await browser.close();
    }
  }
}

// Botu hemen bir kez çalıştır
fiyatiKontrolEt();

// Belirlenen dakika aralığıyla döngüye sok
setInterval(fiyatiKontrolEt, KONTROL_PERIYODU_DAKIKA * 60 * 1000);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">3. Hedef Sitenin Fiyat Selector'ı Nasıl Bulunur?</span></span><br />
<br />
Her sitenin fiyat alanı farklıdır. Kendi takip etmek istediğiniz sitede doğru yeri yakalamak için:<br />
<ol type="1" class="mycode_list"><li>Ürün sayfasına gidin, fiyatın üzerine <span style="font-weight: bold;" class="mycode_b">Sağ Tık &gt; İncele (Inspect)</span> deyin.<br />
</li>
<li>Açılan kod penceresinde fiyatı barındıran etiketin <span style="font-weight: bold;" class="mycode_b">class</span> veya <span style="font-weight: bold;" class="mycode_b">id</span> değerine bakın (Örn: <span style="font-style: italic;" class="mycode_i">class="price-value"</span>).<br />
</li>
<li>Koddaki <span style="font-weight: bold;" class="mycode_b">document.querySelector('.price')</span> alanına o sınıfı yazmanız yeterlidir.<br />
</li>
</ol>
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">4. Arka Planda 7/24 Kesintisiz Çalıştırma (PM2 Taktigi)</span></span><br />
<br />
Terminali kapattığınızda botun durmasını istemiyorsanız, küresel olarak <span style="font-weight: bold;" class="mycode_b">PM2</span> sürec yöneticisini kurup botu arka plana atabilirsiniz:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>npm install -g pm2
pm2 start fiyat_takip.js --name "fiyat-botu"</code></div></div><br />
Artık bilgisayarınız veya sunucunuz açık olduğu sürece terminal penceresi kapalı olsa bile bot sessizce 30 dakikada bir kontrolü yapar, fiyat düştüğü anda telefonunuzu çaldırır.<br />
<br />
<blockquote class="mycode_quote"><cite>Alıntı:</cite><span style="font-weight: bold;" class="mycode_b">Geliştirme Önerisi:</span> Birden fazla ürünü takip etmek isterseniz kodun başındaki <span style="font-weight: bold;" class="mycode_b">URUN_URL</span> alanını bir dizi (array) haline getirip sırayla tüm linkleri döngüyle gezdirebilirsiniz.</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">Takip etmek istediğiniz sitede fiyatı yakalayamadığınız veya selector seçemediğiniz durumlar olursa sayfa linkini bu başlık altından paylaşın, birlikte bakalım!</span>]]></content:encoded>
		</item>
	</channel>
</rss>