• Bugün, 11:11:36
    #1
    Merhaba.

    ekran görüntüsünde paylaştığım sitedeki tüm pdf'leri toplu olarak nasıl indirebilirim?

  • Bugün, 11:20:08
    #2
    en temizi wget hocam, tek komutla sitedeki bütün pdfleri çeker

    1) terminali açıp şunu çalıştır

    wget -r -np -A.pdf https://site-adresi.com/
    2) linkler js ile yükleniyorsa jdownloader kullan, otomatik yakalıyor
  • Bugün, 11:26:54
    #3
    Bu cevap, konu sahibi tarafından kabul edilebilir bir cevap olarak işaretlendi.
    Selam,

    console'a yazacağımız basit bir kodla yapabiliriz.
    F12'ye basın. --> Console kısmına gelin. --> Aşağıdaki kodu yapıştırın. !! "Allow pasting" uyarısı alırsanız kodu yapıştırmadan önce "allow pasting" yazıp enter'a basın.
    Açılan ekranda Küb ve Kt kısımlarının ineceği yeri seçin. --> Bu yoruma beğeni atın ve yorumun sağ altındaki doğru cevap düğmesine basın
    Belki farklı yerlere indirmeniz gerekiyor diye farklı kaydetme yerleri var. İsterseniz aynı yere kaydedin. Size kalmış.
    Ayrıca "bekleme süresi" de var. Bunu da ayarlayabilirsiniz.
    Ai'nin de yardımıyla yapıldı... işinize yarar umarım.

    https://i.ibb.co/Z62SYCSt/image.png

    Kod :

    /*
     * TİTCK KÜB / KT toplu PDF indirici
     * Kullanım: [url]https://titck.gov.tr/kubkt[/url] sayfasında F12 > Console'a tamamını yapıştırın.
     * Chrome / Microsoft Edge (File System Access API) gerekir.
     * Dosyalar seçilen ana klasörün KUB ve KT alt klasörlerine ayrı ayrı kaydedilir.
     */
    (() => {
      'use strict';
    
      if (window.__TITCK_PDF_TOPLU__?.panel?.isConnected) {
        window.__TITCK_PDF_TOPLU__.panel.style.display = 'block';
        console.info('TİTCK indirme paneli zaten açık.');
        return;
      }
    
      if (location.hostname !== 'titck.gov.tr' || location.pathname.replace(/\/$/, '') !== '/kubkt') {
        alert('Önce [url]https://titck.gov.tr/kubkt[/url] adresini açın.');
        return;
      }
      if (!('showDirectoryPicker' in window)) {
        alert('Klasör seçerek kaydetme için güncel Chrome veya Microsoft Edge kullanmalısınız.');
        return;
      }
    
      const table = document.querySelector('#posts');
      const $jq = window.jQuery;
      if (!table || !$jq?.fn?.dataTable?.isDataTable(table)) {
        alert('DataTables tablosu hazır değil. Sayfa tam yüklendikten sonra tekrar deneyin.');
        return;
      }
      const dt = $jq(table).DataTable();
      let rootFolder = null;
      let kubFolder = null;
      let ktFolder = null;
      let running = false;
      let paused = false;
      let stopRequested = false;
      let activeController = null;
      let currentPage = 1;
      let stats = { saved: 0, skipped: 0, failed: 0, missing: 0, rows: 0 };
    
      const style = document.createElement('style');
      style.id = 'titck-pdf-panel-style';
      style.textContent = `
        #titck-pdf-panel { all: initial; position:fixed; top:18px; right:18px; width:370px;
          max-width:calc(100vw - 36px); max-height:calc(100vh - 36px); overflow:auto;
          z-index:2147483647; background:#111827; color:#f9fafb; border:1px solid #4b5563;
          border-radius:14px; box-shadow:0 18px 55px #0009; font:13px/1.5 Arial,sans-serif;
          box-sizing:border-box; padding:18px; }
        #titck-pdf-panel * { box-sizing:border-box; font-family:Arial,sans-serif; }
        #titck-pdf-panel h2 { margin:0 0 8px; font-size:18px; color:#fff; }
        #titck-pdf-panel p { margin:7px 0 12px; font-size:12px; color:#cbd5e1; }
        #titck-pdf-panel .trow { display:grid; grid-template-columns:1fr 1fr; gap:9px; margin:10px 0; }
        #titck-pdf-panel label { display:block; font-size:12px; color:#e2e8f0; }
        #titck-pdf-panel input { display:block; width:100%; margin-top:4px; padding:8px 7px;
          font-size:13px; color:#111827; background:#fff; border:1px solid #9ca3af; border-radius:7px; }
        #titck-pdf-panel button { border:0; border-radius:8px; background:#374151; color:white;
          font-size:12px; font-weight:bold; padding:10px 9px; cursor:pointer; }
        #titck-pdf-panel button:hover { filter:brightness(1.18); }
        #titck-pdf-panel button:disabled { opacity:.45; cursor:not-allowed; }
        #titck-pdf-panel .full { width:100%; }
        #titck-pdf-panel .action { display:grid; grid-template-columns:1fr 1fr 1fr; gap:7px; margin:12px 0; }
        #titck-pdf-panel #titck-start { background:#047857; }
        #titck-pdf-panel #titck-pause { background:#b45309; }
        #titck-pdf-panel #titck-stop { background:#b91c1c; }
        #titck-pdf-panel #titck-folder { background:#1d4ed8; }
        #titck-pdf-panel #titck-log { background:#030712; border:1px solid #374151;
          min-height:90px; max-height:180px; overflow:auto; white-space:pre-wrap; overflow-wrap:anywhere;
          color:#d1d5db; font:11px/1.5 Consolas,monospace; padding:8px; border-radius:7px; }
        #titck-pdf-panel #titck-stats { white-space:pre-line; margin:10px 0;
          font:12px/1.6 Consolas,monospace; color:#bfdbfe; }
        #titck-pdf-panel #titck-status { color:#fef08a; font-weight:700; margin:7px 0; }
      `;
      document.head.appendChild(style);
    
      const panel = document.createElement('section');
      panel.id = 'titck-pdf-panel';
      panel.innerHTML = `
        <h2>📥 TİTCK KÜB / KT İndirici</h2>
        <p>Seçtiğiniz klasöre <b>KUB/</b> ve <b>KT/</b> alt klasörleri oluşturulur. Her ilaç için iki ayrı PDF indirilir (sitede varsa).</p>
        <button type="button" class="full" id="titck-folder">📁 Kayıt klasörünü seç</button>
        <p id="titck-folder-label">Henüz klasör seçilmedi.</p>
        <div class="trow">
          <label>Başlangıç sayfası<input id="titck-first" type="number" min="1" step="1" value="1"></label>
          <label>Bitiş sayfası<input id="titck-last" type="number" min="1" step="1" value="1"></label>
        </div>
        <div class="trow">
          <label>PDF arası bekleme (ms)<input id="titck-pdf-delay" type="number" min="0" step="100" value="1000"></label>
          <label>Sayfa arası bekleme (ms)<input id="titck-page-delay" type="number" min="0" step="100" value="1500"></label>
        </div>
        <div class="trow">
          <label>PDF zaman aşımı (sn)<input id="titck-timeout" type="number" min="10" step="10" value="120"></label>
          <label>Hata sonrası ek deneme<input id="titck-retries" type="number" min="0" max="8" step="1" value="2"></label>
        </div>
        <div class="action">
          <button type="button" id="titck-start">▶ Başlat</button>
          <button type="button" id="titck-pause" disabled>⏸ Duraklat</button>
          <button type="button" id="titck-stop" disabled>■ Durdur</button>
        </div>
        <div id="titck-status">Hazır</div>
        <div id="titck-stats"></div>
        <div id="titck-log" aria-live="polite"></div>
        <p>Not: Sekmeyi kapatmayın. Durdurup yeniden başlattığınızda aynı isimdeki mevcut PDF'ler atlanır.</p>
      `;
      document.body.appendChild(panel);
      const el = id => panel.querySelector('#' + id);
      const setStatus = s => { el('titck-status').textContent = s; };
      const n = (id, fallback = 0) => {
        const v = Number(el(id).value);
        return Number.isFinite(v) ? v : fallback;
      };
      const maxPages = () => Math.max(1, dt.page.info().pages || 1);
      el('titck-last').value = maxPages();
    
      const log = message => {
        const now = new Date().toLocaleTimeString('tr-TR');
        const node = document.createElement('div');
        node.textContent = `[${now}] ${message}`;
        el('titck-log').appendChild(node);
        while (el('titck-log').childNodes.length > 180) el('titck-log').firstChild.remove();
        el('titck-log').scrollTop = el('titck-log').scrollHeight;
        console.log('[TİTCK]', message);
      };
      const updateStats = () => {
        el('titck-stats').textContent =
          `Sayfa: ${currentPage}/${maxPages()}\n` +
          `İncelenen ilaç: ${stats.rows}\n` +
          `Kaydedilen PDF: ${stats.saved} | Atlanan: ${stats.skipped}\n` +
          `Eksik bağlantı: ${stats.missing} | Başarısız: ${stats.failed}`;
      };
      const updateButtons = () => {
        el('titck-start').disabled = running;
        el('titck-folder').disabled = running;
        el('titck-pause').disabled = !running;
        el('titck-stop').disabled = !running;
        el('titck-pause').textContent = paused ? '▶ Devam et' : '⏸ Duraklat';
      };
      updateStats();
    
      el('titck-folder').addEventListener('click', async () => {
        try {
          rootFolder = await window.showDirectoryPicker({ mode: 'readwrite', id: 'titck-kub-kt' });
          kubFolder = await rootFolder.getDirectoryHandle('KUB', { create: true });
          ktFolder = await rootFolder.getDirectoryHandle('KT', { create: true });
          el('titck-folder-label').textContent = `Seçili klasör: ${rootFolder.name} → KUB / KT`;
          log('Kayıt klasörü seçildi: ' + rootFolder.name);
        } catch (err) {
          if (err.name !== 'AbortError') log('Klasör seçilemedi: ' + err.message);
        }
      });
    
      function stoppedError() {
        const error = new Error('İşlem durduruldu');
        error.name = 'StoppedError';
        return error;
      }
      async function checkPauseAndStop() {
        if (stopRequested) throw stoppedError();
        while (paused && !stopRequested) {
          await new Promise(resolve => setTimeout(resolve, 200));
        }
        if (stopRequested) throw stoppedError();
      }
      async function waitMs(ms) {
        const until = performance.now() + Math.max(0, ms);
        do {
          await checkPauseAndStop();
          const left = until - performance.now();
          if (left <= 0) break;
          await new Promise(resolve => setTimeout(resolve, Math.min(200, left)));
        } while (true);
      }
    
      async function gotoPage(zeroBasedPage) {
        await checkPauseAndStop();
        if (dt.page.info().page === zeroBasedPage) return;
        await new Promise((resolve, reject) => {
          const timer = setTimeout(() => {
            cleanup();
            reject(new Error('Tablonun sayfa değiştirmesi zaman aşımına uğradı (60 sn)'));
          }, 60000);
          function cleanup() {
            clearTimeout(timer);
            $jq(table).off('draw.dt.titckbulk', onDraw);
          }
          function onDraw() {
            if (dt.page.info().page === zeroBasedPage) {
              cleanup();
              resolve();
            }
          }
          $jq(table).on('draw.dt.titckbulk', onDraw);
          try { dt.page(zeroBasedPage).draw('page'); }
          catch (err) { cleanup(); reject(err); }
        });
      }
    
      function safeFileName(str) {
        return String(str || 'Bilinmeyen_ilac')
          .normalize('NFC')
          .replace(/[\\/:*?"<>|\x00-\x1f]/g, '_')
          .replace(/\s+/g, ' ')
          .replace(/[. ]+$/g, '')
          .slice(0, 105) || 'Bilinmeyen_ilac';
      }
      function shortHash(str) {
        let h = 2166136261;
        for (let i = 0; i < str.length; i++) {
          h ^= str.charCodeAt(i);
          h = Math.imul(h, 16777619);
        }
        return (h >>> 0).toString(16).padStart(8, '0');
      }
      function jobsOnCurrentPage() {
        const trList = Array.from(table.tBodies[0]?.querySelectorAll('tr') || []);
        const jobs = [];
        for (const tr of trList) {
          const cells = tr.cells;
          if (cells.length < 7) continue;
          const drug = cells[0].textContent.trim() || 'Bilinmeyen_ilac';
          stats.rows++;
          for (const [col, type] of [[5, 'KUB'], [6, 'KT']]) {
            const anchor = cells[col].querySelector('a[href]');
            if (!anchor) { stats.missing++; continue; }
            try {
              const url = new URL(anchor.getAttribute('href'), location.href);
              if (url.origin !== location.origin || !url.pathname.toLowerCase().endsWith('.pdf')) {
                stats.missing++;
                log(`PDF bağlantısı desteklenmiyor: ${drug} (${type})`);
                continue;
              }
              const name = `${safeFileName(drug)}_${shortHash(url.href)}.pdf`;
              jobs.push({ type, drug, name, url: url.href });
            } catch (_) {
              stats.missing++;
            }
          }
        }
        return jobs;
      }
    
      // Büyük PDF'leri RAM'e yüklemeden parça parça dosyaya yazar.
      async function fetchAndSave(job, folder) {
        const controller = new AbortController();
        activeController = controller;
        const timeoutMs = Math.max(10, n('titck-timeout', 120)) * 1000;
        const timer = setTimeout(() => controller.abort(), timeoutMs);
        let writer = null;
        let fileWasCreated = false;
        let reader = null;
        try {
          const response = await fetch(job.url, {
            method: 'GET', credentials: 'same-origin', mode: 'same-origin',
            cache: 'no-store', signal: controller.signal
          });
          if (!response.ok) {
            const error = new Error(`HTTP ${response.status}`);
            error.httpStatus = response.status;
            throw error;
          }
          if (!response.body) throw new Error('Sunucu PDF veri akışı döndürmedi');
          reader = response.body.getReader();
    
          // Hata / giriş / HTML sayfasını yanlışlıkla .pdf olarak kaydetmeyelim.
          const headChunks = [];
          let headSize = 0;
          while (headSize < 1024) {
            const part = await reader.read();
            if (part.done) break;
            headChunks.push(part.value);
            headSize += part.value.byteLength;
          }
          const prefix = new Uint8Array(Math.min(headSize, 1024));
          let offset = 0;
          for (const piece of headChunks) {
            if (offset >= prefix.length) break;
            const chunk = piece.subarray(0, prefix.length - offset);
            prefix.set(chunk, offset);
            offset += chunk.length;
          }
          if (!new TextDecoder('latin1').decode(prefix).includes('%PDF-')) {
            throw new Error('Gelen içerik PDF değil (HTML/hata yanıtı olabilir)');
          }
    
          const file = await folder.getFileHandle(job.name, { create: true });
          fileWasCreated = true;
          writer = await file.createWritable();
          for (const piece of headChunks) await writer.write(piece);
          while (true) {
            const { value, done } = await reader.read();
            if (done) break;
            await writer.write(value);
          }
          await writer.close();
          writer = null;
        } catch (err) {
          if (reader) { try { await reader.cancel(); } catch (_) {} }
          if (writer) { try { await writer.abort(); } catch (_) {} }
          if (fileWasCreated) {
            try { await folder.removeEntry(job.name); } catch (_) {}
          }
          throw err;
        } finally {
          clearTimeout(timer);
          if (activeController === controller) activeController = null;
        }
      }
    
      async function saveJob(job) {
        const folder = job.type === 'KUB' ? kubFolder : ktFolder;
        try {
          const existing = await folder.getFileHandle(job.name, { create: false });
          if ((await existing.getFile()).size > 0) {
            stats.skipped++;
            updateStats();
            return;
          }
        } catch (err) {
          if (err.name !== 'NotFoundError') throw err;
        }
        const retries = Math.min(8, Math.max(0, Math.floor(n('titck-retries', 2))));
        for (let attempt = 0; attempt <= retries; attempt++) {
          await checkPauseAndStop();
          try {
            await fetchAndSave(job, folder);
            stats.saved++;
            updateStats();
            return;
          } catch (err) {
            if (stopRequested) throw stoppedError();
            const permanent = [400, 401, 403, 404, 410].includes(err.httpStatus);
            if (attempt < retries && !permanent) {
              const retryWait = err.httpStatus === 429 ? 30000 : 2500 * (attempt + 1);
              log(`${job.type} deneme ${attempt + 1} başarısız: ${job.drug} (${err.message}), ${retryWait / 1000} sn sonra tekrar...`);
              await waitMs(retryWait);
            } else {
              stats.failed++;
              log(`BAŞARISIZ [${job.type}]: ${job.drug} — ${err.message}`);
              updateStats();
              return;
            }
          }
        }
      }
    
      el('titck-pause').addEventListener('click', () => {
        if (!running) return;
        paused = !paused;
        setStatus(paused ? 'Duraklatıldı (aktif PDF bitince)' : 'Çalışıyor');
        updateButtons();
      });
      el('titck-stop').addEventListener('click', () => {
        stopRequested = true;
        paused = false;
        if (activeController) activeController.abort();
        setStatus('Durduruluyor...');
        updateButtons();
      });
    
      el('titck-start').addEventListener('click', async () => {
        if (running) return;
        if (!rootFolder || !kubFolder || !ktFolder) {
          alert('Önce kayıt klasörünü seçin.');
          return;
        }
        const totalPages = maxPages();
        const first = Math.floor(n('titck-first', 1));
        const last = Math.floor(n('titck-last', totalPages));
        if (first < 1 || last < first || last > totalPages) {
          alert(`Sayfa aralığı 1-${totalPages} arasında olmalı.`);
          return;
        }
        if (n('titck-pdf-delay') < 0 || n('titck-page-delay') < 0) {
          alert('Bekleme süreleri negatif olamaz.');
          return;
        }
    
        running = true;
        paused = false;
        stopRequested = false;
        stats = { saved: 0, skipped: 0, failed: 0, missing: 0, rows: 0 };
        currentPage = first;
        updateButtons();
        updateStats();
        log(`Başladı: ${first}-${last}. sayfalar, PDF bekleme ${n('titck-pdf-delay')} ms.`);
        try {
          for (let page = first; page <= last; page++) {
            await checkPauseAndStop();
            currentPage = page;
            setStatus(`Sayfa yükleniyor: ${page}/${last}`);
            await gotoPage(page - 1);
            await checkPauseAndStop();
            const jobs = jobsOnCurrentPage();
            log(`Sayfa ${page}/${last}: ${jobs.length} PDF bağlantısı bulundu.`);
            updateStats();
            for (const job of jobs) {
              await checkPauseAndStop();
              setStatus(`Sayfa ${page}/${last}: ${job.type} → ${job.drug.slice(0, 45)}`);
              const before = stats.skipped;
              await saveJob(job);
              if (before === stats.skipped) await waitMs(n('titck-pdf-delay', 1000));
            }
            // Elle devam etmek için başlangıç sayfasını hazır tut.
            el('titck-first').value = Math.min(page + 1, last);
            if (page < last) await waitMs(n('titck-page-delay', 1500));
          }
          setStatus(`Tamamlandı. Kaydedilen: ${stats.saved} | Hata: ${stats.failed}`);
          log('BİTTİ. Toplam kaydedilen PDF: ' + stats.saved);
        } catch (err) {
          if (err.name === 'StoppedError' || stopRequested) {
            el('titck-first').value = currentPage;
            setStatus(`Durduruldu. ${currentPage}. sayfadan yeniden başlayabilirsiniz.`);
            log(`Durduruldu. ${currentPage}. sayfadan devam edebilirsiniz; mevcut dosyalar atlanır.`);
          } else {
            el('titck-first').value = currentPage;
            setStatus('Hata oluştu: ' + err.message);
            log(`GENEL HATA: ${err.stack || err.message}`);
          }
        } finally {
          running = false;
          paused = false;
          stopRequested = false;
          updateButtons();
          updateStats();
        }
      });
    
      window.__TITCK_PDF_TOPLU__ = { panel, getStats: () => ({ ...stats }), stop: () => el('titck-stop').click() };
      log(`Panel hazır. Sitede ${maxPages()} sayfa algılandı.`);
      console.info('TİTCK KÜB / KT indirme paneli sayfanın sağ üstünde açıldı.');
    })();
  • Bugün, 11:30:16
    #4
    BUYRUN HOCAM

    https://www.mediafire.com/file/miga6..._urls.csv/file



    ikare adlı üyeden alıntı: mesajı görüntüle
    Merhaba.

    ekran görüntüsünde paylaştığım sitedeki tüm pdf'leri toplu olarak nasıl indirebilirim?

  • Bugün, 11:53:44
    #5
    cevaplar için teşekkürler.
    bahsedilen yöntemler KÜB Dokümanını da indiriyor mu yoksa yalnızca KT Dokümanını mı indiriyor?
    Her ikisini de indiriyorsa sonradan bunları ayrıştırmak zor olabilir.
  • Bugün, 11:54:28
    #6
    linklerde hepsi var hocam
    ikare adlı üyeden alıntı: mesajı görüntüle
    cevaplar için teşekkürler.
    bahsedilen yöntemler KÜB Dokümanını da indiriyor mu yoksa yalnızca KT Dokümanını mı indiriyor?
    Her ikisini de indiriyorsa sonradan bunları ayrıştırmak zor olabilir.
  • Bugün, 11:56:02
    #7
    https://www.mediafire.com/file/1bcqc...tap1.xlsx/file BUnu indirin daha düzenli diğeri csv İDİ
  • Bugün, 12:05:05
    #8
    newQne adlı üyeden alıntı: mesajı görüntüle
    https://www.mediafire.com/file/1bcqc...tap1.xlsx/file BUnu indirin daha düzenli diğeri csv İDİ
    hocam desteğiniz için teşekkürler. sadece linkler var excel'de. doğru değil mi?
  • Bugün, 12:10:21
    #9
    ikare adlı üyeden alıntı: mesajı görüntüle
    hocam desteğiniz için teşekkürler. sadece linkler var excel'de. doğru değil mi?

    evet hocam o liste doğru, linkleri tek tek indirmene gerek yok. exceldeki adresleri düz metin dosyasına kaydedip şunu çalıştır

    wget -i linkler.txt
    bu hepsini toplu çeker valla, takılan olursa jdownloader linki yapıştır alır