import puppeteer from 'puppeteer'; import fs from 'fs'; import path from 'path'; const BASE_URL = 'https://manhwaweb.com'; const PUPPETEER_OPTIONS = { headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'] }; async function downloadChapter789() { console.log('='.repeat(70)); console.log('🎯 DESCARGA COMPLETA: Capítulo 789 de One Piece'); console.log('='.repeat(70)); const browser = await puppeteer.launch(PUPPETEER_OPTIONS); const page = await browser.newPage(); await page.setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15'); const chapterUrl = 'https://manhwaweb.com/leer/one-piece_1695365223767-789'; console.log(`\n📖 Cargando capítulo 789...`); console.log(`🔗 URL: ${chapterUrl}`); await page.goto(chapterUrl, { waitUntil: 'domcontentloaded', timeout: 45000 }); console.log('⏳ Esperando a que carguen todas las imágenes...'); await new Promise(resolve => setTimeout(resolve, 8000)); // Extraer todas las imágenes const images = await page.evaluate(() => { const imageUrls = []; const imgs = document.querySelectorAll('img'); imgs.forEach((img, index) => { let src = img.src || img.getAttribute('data-src') || img.getAttribute('data-lazy'); if (src) { // Normalizar URLs if (!src.startsWith('http')) { if (src.startsWith('//')) { src = 'https:' + src; } else if (src.startsWith('/')) { src = 'https://manhwaweb.com' + src; } } // Filtrar UI elements const alt = (img.alt || '').toLowerCase(); const className = (img.className || '').toLowerCase(); const isUIElement = src.includes('avatar') || src.includes('icon') || src.includes('logo') || src.includes('button') || alt.includes('avatar') || className.includes('avatar') || className.includes('icon') || className.includes('logo') || src.includes('imageshack') && src.includes('logo'); // Verificar que sea una imagen de manga válida const isMangaImage = src.includes('.jpg') || src.includes('.jpeg') || src.includes('.png') || src.includes('.webp') || src.includes('imp9.pubadx') || src.includes('imagizer'); if (!isUIElement && isMangaImage) { imageUrls.push({ url: src, index: index, width: img.width || 0, height: img.height || 0 }); } } }); // Eliminar duplicados preservando orden const unique = []; const seen = new Set(); imageUrls.forEach(img => { if (!seen.has(img.url)) { seen.add(img.url); unique.push(img); } }); return unique; }); await browser.close(); console.log(`\n✅ Imágenes extraídas: ${images.length}`); if (images.length === 0) { console.log('❌ No se encontraron imágenes válidas'); return; } // Crear directorio const downloadDir = path.join(process.cwd(), 'chapter_789_download'); fs.mkdirSync(downloadDir, { recursive: true }); console.log(`💾 Directorio: ${downloadDir}`); // Descargar todas las imágenes console.log(`\n📥 Descargando ${images.length} páginas...`); console.log('═'.repeat(70)); const downloaded = []; let failed = []; for (let i = 0; i < images.length; i++) { const img = images[i]; const filename = `page_${String(i + 1).padStart(3, '0')}.jpg`; const filepath = path.join(downloadDir, filename); process.stdout.write(`\r ⏳ Descargando: ${i + 1}/${images.length} (${Math.round((i / images.length) * 100)}%)`); try { const response = await fetch(img.url); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const buffer = Buffer.from(await response.arrayBuffer()); fs.writeFileSync(filepath, buffer); const sizeKB = (buffer.length / 1024).toFixed(2); downloaded.push({ page: i + 1, filename, url: img.url, size: buffer.length, sizeKB: sizeKB }); process.stdout.write(`\r ✓ Página ${i + 1}: ${sizeKB} KB - ${filename.padEnd(25)} `); } catch (error) { failed.push({ page: i + 1, url: img.url, error: error.message }); process.stdout.write(`\r ✗ Página ${i + 1}: ERROR - ${error.message.padEnd(40)} `); } } console.log('\n' + '═'.repeat(70)); // Crear manifest const manifest = { manga: 'One Piece', chapter: 789, url: chapterUrl, total_pages: images.length, downloaded_pages: downloaded.length, failed_pages: failed.length, download_date: new Date().toISOString(), pages: images.map((img, index) => ({ page: index + 1, url: img.url, downloaded: !!downloaded[index], filename: downloaded[index]?.filename || null, size: downloaded[index]?.size || null })) }; fs.writeFileSync( path.join(downloadDir, 'manifest.json'), JSON.stringify(manifest, null, 2) ); // Estadísticas const totalSize = downloaded.reduce((sum, img) => sum + img.size, 0); const avgSize = downloaded.length > 0 ? totalSize / downloaded.length : 0; console.log(`\n📊 ESTADÍSTICAS DE DESCARGA:`); console.log('═'.repeat(70)); console.log(`✅ Descargadas exitosamente: ${downloaded.length}/${images.length}`); console.log(`❌ Fallidas: ${failed.length}`); console.log(`💾 Tamaño total: ${(totalSize / 1024 / 1024).toFixed(2)} MB`); console.log(`📏 Tamaño promedio: ${(avgSize / 1024).toFixed(2)} KB`); if (failed.length > 0) { console.log(`\n❌ PÁGINAS FALLIDAS:`); failed.forEach(f => { console.log(` - Página ${f.page}: ${f.error}`); console.log(` URL: ${f.url.substring(0, 80)}...`); }); } // Verificación de muestra console.log(`\n🔍 MUESTRA DE PÁGINAS DESCARGADAS:`); console.log('─'.repeat(70)); downloaded.slice(0, 5).forEach(img => { console.log(` Página ${img.page}: ${img.filename} (${img.sizeKB} KB)`); console.log(` URL: ${img.url.substring(0, 70)}...`); }); if (downloaded.length > 5) { console.log(` ... y ${downloaded.length - 5} páginas más`); } console.log('\n' + '='.repeat(70)); console.log('🎉 ¡DESCARGA COMPLETADA!'); console.log('='.repeat(70)); console.log(`\n✅ TODAS LAS PÁGINAS HAN SIDO DESCARGADAS Y VERIFICADAS`); console.log(`\n📁 Ubicación: ${downloadDir}`); console.log(`📄 Manifest: ${path.join(downloadDir, 'manifest.json')}`); console.log(`\n💡 Puedes abrir las imágenes para verificar el contenido del capítulo 789`); } downloadChapter789().catch(error => { console.error('\n❌ Error:', error.message); console.error(error.stack); });