<?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 - Portal]]></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 19:06:17 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[Optimizasyon: Fiyat Değişmediğinde JSON Logunu Şişirmeme (Delta Loglama Yöntemi)]]></title>
			<link>https://botbb.tr/showthread.php?tid=49</link>
			<pubDate>Sat, 17 Oct 2026 19:43:33 +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/showthread.php?tid=49</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Optimizasyon: Fiyat Değişmediğinde JSON Logunu Şişirmeme (Delta Loglama Yöntemi)</span></span><br />
<br />
Fiyat takip botları 7/24 çalışırken (örneğin 30 dakikada bir kontrol yaparken), fiyat haftalarca aynı kalabilir. Her kontrolde JSON dosyasına aynı fiyatı yazmak iki büyük soruna yol açar:<br />
<ol type="1" class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Gereksiz Dosya Boyutu:</span> 10 ürün için günde yüzlerce tekrarlanan satır oluşur ve JSON dosyası megabaytlarca şişer.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Grafik ve Analiz Kirliliği:</span> İleride fiyat grafiği çizdirmek istediğinizde aynı fiyatın binlerce kopyası grafiği anlamsız şekilde uzatır.<br />
</li>
</ol>
<br />
Bunun çözümü <span style="font-weight: bold;" class="mycode_b">Delta Loglama (Sadece Değişimleri Kaydetme)</span> mantığıdır: Bot yeni fiyatı aldığında dosyadaki <span style="font-weight: bold;" class="mycode_b">en son kayıtlı fiyata</span> bakar; fiyat kuruşu kuruşuna aynıysa dosyaya dokunmaz, yalnızca fiyat değişmişse (artmış veya azalmışsa) arşive yeni bir satır ekler.<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. Optimize Edilmiş `fiyatKaydet()` Fonksiyonu</span></span><br />
<br />
Mevcut scriptinizdeki `fiyatKaydet` fonksiyonunu aşağıdaki mantıkla güncelleyin:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>/**
 * Yalnızca fiyat değiştiğinde JSON dosyasına log atan optimize fonksiyon
 */
function fiyatKaydet(urunAdi, guncelFiyat) {
  let gecmisVeri = {};

  // 1. Mevcut JSON dosyasını oku
  if (fs.existsSync(LOG_DOSYASI)) {
    try {
      const hamIcerik = fs.readFileSync(LOG_DOSYASI, 'utf8');
      gecmisVeri = hamIcerik ? JSON.parse(hamIcerik) : {};
    } catch (e) {
      gecmisVeri = {};
    }
  }

  // 2. Bu ürünün geçmiş kayıt listesini al (yoksa boş dizi aç)
  if (!gecmisVeri[urunAdi]) {
    gecmisVeri[urunAdi] = [];
  }

  const urunKayitlari = gecmisVeri[urunAdi];

  // 3. KONTROL: Ürünün son kayıtlı fiyatına bak
  if (urunKayitlari.length &gt; 0) {
    const sonKayit = urunKayitlari[urunKayitlari.length - 1];
    
    // Fiyat değişmemişse diske yazma işlemini pas geç
    if (sonKayit.fiyat === guncelFiyat) {
      console.log(`ℹ️ [Fiyat Sabit] &#36;{urunAdi} hala &#36;{guncelFiyat} TL (Log atlanıyor).`);
      return false; // Değişim olmadığını bildirmek için false döner
    }

    // Fiyat değiştiyse konsola ne kadar değiştiğini yazdır
    const fark = (guncelFiyat - sonKayit.fiyat).toFixed(2);
    const durum = fark &gt; 0 ? `+&#36;{fark} TL (Zam)` : `&#36;{fark} TL (İndirim)`;
    console.log(`? [Fiyat Değişti] &#36;{urunAdi}: &#36;{sonKayit.fiyat} TL ➔ &#36;{guncelFiyat} TL (&#36;{durum})`);
  } else {
    // Ürün dosyaya ilk defa ekleniyorsa
    console.log(`? [İlk Kayıt] &#36;{urunAdi} sisteme eklendi: &#36;{guncelFiyat} TL`);
  }

  // 4. Yeni kaydı oluştur ve arşive ekle
  const simdi = new Date();
  const yeniKayit = {
    tarih: simdi.toLocaleDateString('tr-TR'),
    saat: simdi.toLocaleTimeString('tr-TR'),
    fiyat: guncelFiyat
  };

  urunKayitlari.push(yeniKayit);

  // 5. Dosyaya yaz
  fs.writeFileSync(LOG_DOSYASI, JSON.stringify(gecmisVeri, null, 2), 'utf8');
  return true; // Değişim olduğunu bildirmek için true döner
}</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. Elde Ettiğimiz Avantajlar</span></span><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">%95 Disk Tasarrufu:</span> Fiyatı 1 ay boyunca değişmeyen bir ürün için 1440 satır yerine sadece 1 satır veri saklarsınız.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">SSD/Disk Ömrü:</span> Her 30 dakikada bir diske sürekli I/O (yazma) işlemi yapılmaz, sadece piyasa oynadığında diske yazılır.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Net Fiyat Eğrisi:</span> Grafiğe veya Excel'e aktardığınızda her satır gerçek bir piyasa hareketini (zam veya indirim anını) temsil eder.<br />
</li>
</ul>
<br />
<blockquote class="mycode_quote"><cite>Alıntı:</cite><span style="font-weight: bold;" class="mycode_b">İpucu:</span> Bu fonksiyondan dönen `true` veya `false` değerini kullanarak; sadece fiyat gerçekten değiştiğinde Telegram'a <span style="font-style: italic;" class="mycode_i">"X ürününün fiyatı güncellendi!"</span> şeklinde bilgilendirme mesajı da attırabilirsiniz.</blockquote>
]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Optimizasyon: Fiyat Değişmediğinde JSON Logunu Şişirmeme (Delta Loglama Yöntemi)</span></span><br />
<br />
Fiyat takip botları 7/24 çalışırken (örneğin 30 dakikada bir kontrol yaparken), fiyat haftalarca aynı kalabilir. Her kontrolde JSON dosyasına aynı fiyatı yazmak iki büyük soruna yol açar:<br />
<ol type="1" class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Gereksiz Dosya Boyutu:</span> 10 ürün için günde yüzlerce tekrarlanan satır oluşur ve JSON dosyası megabaytlarca şişer.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Grafik ve Analiz Kirliliği:</span> İleride fiyat grafiği çizdirmek istediğinizde aynı fiyatın binlerce kopyası grafiği anlamsız şekilde uzatır.<br />
</li>
</ol>
<br />
Bunun çözümü <span style="font-weight: bold;" class="mycode_b">Delta Loglama (Sadece Değişimleri Kaydetme)</span> mantığıdır: Bot yeni fiyatı aldığında dosyadaki <span style="font-weight: bold;" class="mycode_b">en son kayıtlı fiyata</span> bakar; fiyat kuruşu kuruşuna aynıysa dosyaya dokunmaz, yalnızca fiyat değişmişse (artmış veya azalmışsa) arşive yeni bir satır ekler.<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. Optimize Edilmiş `fiyatKaydet()` Fonksiyonu</span></span><br />
<br />
Mevcut scriptinizdeki `fiyatKaydet` fonksiyonunu aşağıdaki mantıkla güncelleyin:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>/**
 * Yalnızca fiyat değiştiğinde JSON dosyasına log atan optimize fonksiyon
 */
function fiyatKaydet(urunAdi, guncelFiyat) {
  let gecmisVeri = {};

  // 1. Mevcut JSON dosyasını oku
  if (fs.existsSync(LOG_DOSYASI)) {
    try {
      const hamIcerik = fs.readFileSync(LOG_DOSYASI, 'utf8');
      gecmisVeri = hamIcerik ? JSON.parse(hamIcerik) : {};
    } catch (e) {
      gecmisVeri = {};
    }
  }

  // 2. Bu ürünün geçmiş kayıt listesini al (yoksa boş dizi aç)
  if (!gecmisVeri[urunAdi]) {
    gecmisVeri[urunAdi] = [];
  }

  const urunKayitlari = gecmisVeri[urunAdi];

  // 3. KONTROL: Ürünün son kayıtlı fiyatına bak
  if (urunKayitlari.length &gt; 0) {
    const sonKayit = urunKayitlari[urunKayitlari.length - 1];
    
    // Fiyat değişmemişse diske yazma işlemini pas geç
    if (sonKayit.fiyat === guncelFiyat) {
      console.log(`ℹ️ [Fiyat Sabit] &#36;{urunAdi} hala &#36;{guncelFiyat} TL (Log atlanıyor).`);
      return false; // Değişim olmadığını bildirmek için false döner
    }

    // Fiyat değiştiyse konsola ne kadar değiştiğini yazdır
    const fark = (guncelFiyat - sonKayit.fiyat).toFixed(2);
    const durum = fark &gt; 0 ? `+&#36;{fark} TL (Zam)` : `&#36;{fark} TL (İndirim)`;
    console.log(`? [Fiyat Değişti] &#36;{urunAdi}: &#36;{sonKayit.fiyat} TL ➔ &#36;{guncelFiyat} TL (&#36;{durum})`);
  } else {
    // Ürün dosyaya ilk defa ekleniyorsa
    console.log(`? [İlk Kayıt] &#36;{urunAdi} sisteme eklendi: &#36;{guncelFiyat} TL`);
  }

  // 4. Yeni kaydı oluştur ve arşive ekle
  const simdi = new Date();
  const yeniKayit = {
    tarih: simdi.toLocaleDateString('tr-TR'),
    saat: simdi.toLocaleTimeString('tr-TR'),
    fiyat: guncelFiyat
  };

  urunKayitlari.push(yeniKayit);

  // 5. Dosyaya yaz
  fs.writeFileSync(LOG_DOSYASI, JSON.stringify(gecmisVeri, null, 2), 'utf8');
  return true; // Değişim olduğunu bildirmek için true döner
}</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. Elde Ettiğimiz Avantajlar</span></span><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">%95 Disk Tasarrufu:</span> Fiyatı 1 ay boyunca değişmeyen bir ürün için 1440 satır yerine sadece 1 satır veri saklarsınız.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">SSD/Disk Ömrü:</span> Her 30 dakikada bir diske sürekli I/O (yazma) işlemi yapılmaz, sadece piyasa oynadığında diske yazılır.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Net Fiyat Eğrisi:</span> Grafiğe veya Excel'e aktardığınızda her satır gerçek bir piyasa hareketini (zam veya indirim anını) temsil eder.<br />
</li>
</ul>
<br />
<blockquote class="mycode_quote"><cite>Alıntı:</cite><span style="font-weight: bold;" class="mycode_b">İpucu:</span> Bu fonksiyondan dönen `true` veya `false` değerini kullanarak; sadece fiyat gerçekten değiştiğinde Telegram'a <span style="font-style: italic;" class="mycode_i">"X ürününün fiyatı güncellendi!"</span> şeklinde bilgilendirme mesajı da attırabilirsiniz.</blockquote>
]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Hazır Kod: Fiyat Takip Botuna JSON Veri Loglama (Fiyat Geçmişi Ekleme)]]></title>
			<link>https://botbb.tr/showthread.php?tid=48</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/showthread.php?tid=48</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/showthread.php?tid=47</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/showthread.php?tid=47</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/showthread.php?tid=46</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/showthread.php?tid=46</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>
		<item>
			<title><![CDATA[Node.js ile 3 Dakikada Cep Telefonunuza Telegram Bildirim Botu Kurun]]></title>
			<link>https://botbb.tr/showthread.php?tid=45</link>
			<pubDate>Sat, 17 Oct 2026 19:32:43 +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/showthread.php?tid=45</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Hazır Script: Node.js ile 3 Dakikada Cep Telefonunuza Telegram Bildirim Botu Kurun (Tek Tıkla Çalışır)</span></span><br />
<br />
Otomasyon projelerinde (fiyat takibi, bilet yakalama, sunucu kontrolü veya dosya indirme) en büyük ihtiyaç, işlem bittiğinde veya kritik bir olay yaşandığında anında haberdar olmaktır. Bilgisayar başında saatlerce ekran beklemek yerine, sistemin doğrudan <span style="font-weight: bold;" class="mycode_b">cep telefonunuza Telegram üzerinden bildirim göndermesi</span> en pratik çözümdür.<br />
<br />
Bu rehberde sıfırdan Telegram botu açıp, sadece 15 satırlık hafif bir Node.js koduyla telefonunuza nasıl anlık alarm/bildirim göndereceğinizi adım adım 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">Adım 1: 1 Dakikada Telegram Botu ve Chat ID Alma</span></span><br />
<br />
<ol type="1" class="mycode_list"><li>Telegram arama kutusuna <span style="font-weight: bold;" class="mycode_b">@BotFather</span> yazın ve resmi onaylı bota girin.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">/newbot</span> komutunu gönderin.<br />
</li>
<li>Botunuz için bir isim (Örn: <span style="font-style: italic;" class="mycode_i">Benim Alarm Botum</span>) ve ardından sonu "bot" ile biten bir kullanıcı adı (Örn: <span style="font-style: italic;" class="mycode_i">otomasyon_alarm_bot</span>) belirleyin.<br />
</li>
<li>BotFather size <span style="font-weight: bold;" class="mycode_b">HTTP API Token</span> verecektir. Bu token anahtarınızı bir yere not edin (Örn: <span style="font-style: italic;" class="mycode_i">712345678:AAH...</span>).<br />
</li>
<li>Arama kutusuna az önce açtığınız botun adını yazın ve bota girip <span style="font-weight: bold;" class="mycode_b">/start</span> butonuna basın (Mesaj atabilmesi için bu şarttır).<br />
</li>
<li>Kendi kullanıcı ID numaranızı öğrenmek için Telegram'da <span style="font-weight: bold;" class="mycode_b">@userinfobot</span> hesabını aratıp <span style="font-weight: bold;" class="mycode_b">/start</span> deyin; size <span style="font-weight: bold;" class="mycode_b">Id</span> numaranızı (Örn: <span style="font-style: italic;" class="mycode_i">123456789</span>) verecektir.<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">Adım 2: Gerekli Tek Kütüphaneyi Kurun</span></span><br />
<br />
Bilgisayarınızda veya sunucunuzda boş bir klasör açın, terminali (CMD) açıp şu hafif kütüphaneyi yükleyin:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>npm install 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">Adım 3: Çalışan Hazır Kod (telegram_alarm.js)</span></span><br />
<br />
Klasörünüzde <span style="font-weight: bold;" class="mycode_b">telegram_alarm.js</span> adında bir dosya 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 1. Adımda aldığınız bilgileri yazın:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>const axios = require('axios');

// 1. Adımda aldığınız bilgileri buraya girin
const BOT_TOKEN = 'BURAYA_BOT_TOKEN_GELECEK';
const CHAT_ID = 'BURAYA_CHAT_ID_GELECEK';

/**
 * Telegram'a formatlı mesaj gönderen pratik fonksiyon
 * @param {string} mesaj - Gönderilecek metin (HTML etiketleri destekler)
 */
async function bildirimGonder(mesaj) {
  const url = `https://api.telegram.org/bot&#36;{BOT_TOKEN}/sendMessage`;

  try {
    const response = await axios.post(url, {
      chat_id: CHAT_ID,
      text: mesaj,
      parse_mode: 'HTML' // Kalın, italik ve link desteği için
    });

    if (response.data.ok) {
      console.log('Bildirim telefona başarıyla iletildi!');
    }
  } catch (error) {
    console.error('Telegram hatası:', error.response ? error.response.data.description : error.message);
  }
}

// TEST KULLANIMI:
const testMesaji = `
? &lt;b&gt;Otomasyon Alarmı!&lt;/b&gt;
━━━━━━━━━━━━━━━━━━
? &lt;b&gt;Ürün:&lt;/b&gt; Takip Edilen Ekran Kartı
? &lt;b&gt;Fiyat:&lt;/b&gt; 14.500 TL (Hedef Fiyatın Altına Düştü!)
⏱ &lt;b&gt;Zaman:&lt;/b&gt; &#36;{new Date().toLocaleTimeString('tr-TR')}
? &lt;a href="https://example.com"&gt;Ürüne Gitmek İçin Tıklayın&lt;/a&gt;
`;

bildirimGonder(testMesaji);</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">Adım 4: Tek Tıkla Çalıştırma (Masaüstü Kısayolu)</span></span><br />
<br />
Her seferinde terminal açmakla uğraşmak istemiyorsanız, aynı klasörün içine <span style="font-weight: bold;" class="mycode_b">calistir.bat</span> adında bir metin dosyası açıp içine şu tek satırı yazın:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>node telegram_alarm.js
pause</code></div></div><br />
Artık bu <span style="font-weight: bold;" class="mycode_b">.bat</span> dosyasına çift tıkladığınız an arka planda komut çalışır ve saniyesinde telefonunuza bildirim sesiyle birlikte mesajınız düşer.<br />
<br />
<blockquote class="mycode_quote"><cite>Alıntı:</cite><span style="font-weight: bold;" class="mycode_b">Nerede Kullanabilirsiniz?</span><br />
Bu fonksiyonu yazdığınız herhangi bir scraping (fiyat/stok) botunun içine, Puppeteer senaryolarının sonuna veya sunucunuzdaki yedekleme scriptlerinin bitişine ekleyerek tüm süreçleri cebinizden anlık izleyebilirsiniz.</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">Takıldığınız veya Telegram API'sinden hata aldığınız bir adım olursa chat ID veya token bilgilerinizi gizleyerek bu başlık altından sorabilirsiniz!</span>]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Hazır Script: Node.js ile 3 Dakikada Cep Telefonunuza Telegram Bildirim Botu Kurun (Tek Tıkla Çalışır)</span></span><br />
<br />
Otomasyon projelerinde (fiyat takibi, bilet yakalama, sunucu kontrolü veya dosya indirme) en büyük ihtiyaç, işlem bittiğinde veya kritik bir olay yaşandığında anında haberdar olmaktır. Bilgisayar başında saatlerce ekran beklemek yerine, sistemin doğrudan <span style="font-weight: bold;" class="mycode_b">cep telefonunuza Telegram üzerinden bildirim göndermesi</span> en pratik çözümdür.<br />
<br />
Bu rehberde sıfırdan Telegram botu açıp, sadece 15 satırlık hafif bir Node.js koduyla telefonunuza nasıl anlık alarm/bildirim göndereceğinizi adım adım 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">Adım 1: 1 Dakikada Telegram Botu ve Chat ID Alma</span></span><br />
<br />
<ol type="1" class="mycode_list"><li>Telegram arama kutusuna <span style="font-weight: bold;" class="mycode_b">@BotFather</span> yazın ve resmi onaylı bota girin.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">/newbot</span> komutunu gönderin.<br />
</li>
<li>Botunuz için bir isim (Örn: <span style="font-style: italic;" class="mycode_i">Benim Alarm Botum</span>) ve ardından sonu "bot" ile biten bir kullanıcı adı (Örn: <span style="font-style: italic;" class="mycode_i">otomasyon_alarm_bot</span>) belirleyin.<br />
</li>
<li>BotFather size <span style="font-weight: bold;" class="mycode_b">HTTP API Token</span> verecektir. Bu token anahtarınızı bir yere not edin (Örn: <span style="font-style: italic;" class="mycode_i">712345678:AAH...</span>).<br />
</li>
<li>Arama kutusuna az önce açtığınız botun adını yazın ve bota girip <span style="font-weight: bold;" class="mycode_b">/start</span> butonuna basın (Mesaj atabilmesi için bu şarttır).<br />
</li>
<li>Kendi kullanıcı ID numaranızı öğrenmek için Telegram'da <span style="font-weight: bold;" class="mycode_b">@userinfobot</span> hesabını aratıp <span style="font-weight: bold;" class="mycode_b">/start</span> deyin; size <span style="font-weight: bold;" class="mycode_b">Id</span> numaranızı (Örn: <span style="font-style: italic;" class="mycode_i">123456789</span>) verecektir.<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">Adım 2: Gerekli Tek Kütüphaneyi Kurun</span></span><br />
<br />
Bilgisayarınızda veya sunucunuzda boş bir klasör açın, terminali (CMD) açıp şu hafif kütüphaneyi yükleyin:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>npm install 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">Adım 3: Çalışan Hazır Kod (telegram_alarm.js)</span></span><br />
<br />
Klasörünüzde <span style="font-weight: bold;" class="mycode_b">telegram_alarm.js</span> adında bir dosya 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 1. Adımda aldığınız bilgileri yazın:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>const axios = require('axios');

// 1. Adımda aldığınız bilgileri buraya girin
const BOT_TOKEN = 'BURAYA_BOT_TOKEN_GELECEK';
const CHAT_ID = 'BURAYA_CHAT_ID_GELECEK';

/**
 * Telegram'a formatlı mesaj gönderen pratik fonksiyon
 * @param {string} mesaj - Gönderilecek metin (HTML etiketleri destekler)
 */
async function bildirimGonder(mesaj) {
  const url = `https://api.telegram.org/bot&#36;{BOT_TOKEN}/sendMessage`;

  try {
    const response = await axios.post(url, {
      chat_id: CHAT_ID,
      text: mesaj,
      parse_mode: 'HTML' // Kalın, italik ve link desteği için
    });

    if (response.data.ok) {
      console.log('Bildirim telefona başarıyla iletildi!');
    }
  } catch (error) {
    console.error('Telegram hatası:', error.response ? error.response.data.description : error.message);
  }
}

// TEST KULLANIMI:
const testMesaji = `
? &lt;b&gt;Otomasyon Alarmı!&lt;/b&gt;
━━━━━━━━━━━━━━━━━━
? &lt;b&gt;Ürün:&lt;/b&gt; Takip Edilen Ekran Kartı
? &lt;b&gt;Fiyat:&lt;/b&gt; 14.500 TL (Hedef Fiyatın Altına Düştü!)
⏱ &lt;b&gt;Zaman:&lt;/b&gt; &#36;{new Date().toLocaleTimeString('tr-TR')}
? &lt;a href="https://example.com"&gt;Ürüne Gitmek İçin Tıklayın&lt;/a&gt;
`;

bildirimGonder(testMesaji);</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">Adım 4: Tek Tıkla Çalıştırma (Masaüstü Kısayolu)</span></span><br />
<br />
Her seferinde terminal açmakla uğraşmak istemiyorsanız, aynı klasörün içine <span style="font-weight: bold;" class="mycode_b">calistir.bat</span> adında bir metin dosyası açıp içine şu tek satırı yazın:<br />
<br />
<div class="codeblock"><div class="title">Kod:</div><div class="body" dir="ltr"><code>node telegram_alarm.js
pause</code></div></div><br />
Artık bu <span style="font-weight: bold;" class="mycode_b">.bat</span> dosyasına çift tıkladığınız an arka planda komut çalışır ve saniyesinde telefonunuza bildirim sesiyle birlikte mesajınız düşer.<br />
<br />
<blockquote class="mycode_quote"><cite>Alıntı:</cite><span style="font-weight: bold;" class="mycode_b">Nerede Kullanabilirsiniz?</span><br />
Bu fonksiyonu yazdığınız herhangi bir scraping (fiyat/stok) botunun içine, Puppeteer senaryolarının sonuna veya sunucunuzdaki yedekleme scriptlerinin bitişine ekleyerek tüm süreçleri cebinizden anlık izleyebilirsiniz.</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">Takıldığınız veya Telegram API'sinden hata aldığınız bir adım olursa chat ID veya token bilgilerinizi gizleyerek bu başlık altından sorabilirsiniz!</span>]]></content:encoded>
		</item>
	</channel>
</rss>