Ayuda estoy pudiendo hacer descargas pero no logro hacer scroll... me gustaria aprender hacer el scraping evitando el bloqueo de cloudflare.
import os
import re
import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from PIL import Image
from io import BytesIO
import time
import json
def configurar_driver():
"""Configura Chrome para evitar detección"""
chrome_options = Options()
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)
chrome_options.add_argument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
driver = webdriver.Chrome(options=chrome_options)
driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
return driver
def descargar_miniaturas_coleccion(url_coleccion, carpeta_destino="imagenes_hueforge"):
"""
Descarga específicamente las imágenes de portada/miniatura de la colección
"""
os.makedirs(carpeta_destino, exist_ok=True)
driver = configurar_driver()
try:
print("🔗 Accediendo a la página de colección...")
driver.get(url_coleccion)
# Esperar a que cargue
WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.TAG_NAME, "body"))
)
# Scroll para cargar contenido dinámico
print("📜 Cargando todos los elementos...")
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2)
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
break
last_height = new_height
print("🔍 Buscando miniaturas de modelos...")
# Múltiples estrategias para encontrar las tarjetas de modelos
modelos_encontrados = []
# Estrategia 1: Buscar contenedores de modelos
selectores_contenedor = [
"[class*='model-card']",
"[class*='model-item']",
"[class*='card']",
"[data-testid*='model']",
"article",
".grid > div",
"[class*='collection-item']"
]
for selector in selectores_contenedor:
try:
elementos = driver.find_elements(By.CSS_SELECTOR, selector)
print(f"📊 Selector '{selector}': {len(elementos)} elementos")
for elemento in elementos:
try:
# Buscar imagen dentro del contenedor
img = elemento.find_element(By.TAG_NAME, "img")
src = img.get_attribute("src")
# Buscar título del modelo
titulo = None
selectores_titulo = ["h1", "h2", "h3", "h4", "[class*='title']", "[class*='name']", "a"]
for sel_titulo in selectores_titulo:
try:
elem_titulo = elemento.find_element(By.CSS_SELECTOR, sel_titulo)
titulo = elem_titulo.text.strip()
if titulo and len(titulo) > 2:
break
except:
continue
# Si no encuentra título, usar atributo alt de la imagen
if not titulo:
titulo = img.get_attribute("alt") or "modelo_sin_titulo"
if src and titulo:
modelos_encontrados.append({
'src': src,
'titulo': titulo,
'elemento_html': elemento.get_attribute('outerHTML')[:200]
})
except Exception as e:
continue
except Exception as e:
print(f"❌ Error con selector {selector}: {e}")
continue
# Eliminar duplicados por URL de imagen
urls_vistas = set()
modelos_unicos = []
for modelo in modelos_encontrados:
if modelo['src'] not in urls_vistas:
urls_vistas.add(modelo['src'])
modelos_unicos.append(modelo)
print(f"📊 Miniaturas únicas encontradas: {len(modelos_unicos)}")
if len(modelos_unicos) == 0:
print("⚠️ No se encontraron miniaturas. Probando método alternativo...")
# Método alternativo: todas las imágenes de la página
todas_imagenes = driver.find_elements(By.TAG_NAME, "img")
print(f"🖼️ Total de imágenes en la página: {len(todas_imagenes)}")
for i, img in enumerate(todas_imagenes):
src = img.get_attribute("src")
alt = img.get_attribute("alt") or f"imagen_{i}"
# Filtrar imágenes que parezcan miniaturas de modelos
if src and any(keyword in src.lower() for keyword in ['thumb', 'preview', 'model', 'image']):
modelos_unicos.append({
'src': src,
'titulo': alt,
'elemento_html': f"img alt='{alt}'"
})
# Guardar información de debug
with open(os.path.join(carpeta_destino, "debug_modelos.json"), "w", encoding="utf-8") as f:
json.dump(modelos_unicos, f, indent=2, ensure_ascii=False)
# Descargar las miniaturas
exitos = 0
errores = 0
for i, modelo in enumerate(modelos_unicos):
titulo = modelo['titulo']
src = modelo['src']
print(f"⬇️ {i+1}/{len(modelos_unicos)}: {titulo[:50]}...")
try:
# Limpiar nombre del archivo
titulo_limpio = re.sub(r'[<>:"/\\|?*]', '', titulo).strip()
titulo_limpio = re.sub(r'\s+', '_', titulo_limpio)[:100]
if descargar_imagen(src, titulo_limpio, carpeta_destino):
exitos += 1
else:
errores += 1
except Exception as e:
print(f"❌ Error procesando {titulo}: {e}")
errores += 1
print(f"\n📊 RESUMEN:")
print(f"✅ Miniaturas descargadas: {exitos}")
print(f"❌ Errores: {errores}")
print(f"📁 Carpeta: {os.path.abspath(carpeta_destino)}")
print(f"🔍 Ver debug_modelos.json para detalles")
finally:
driver.quit()
def descargar_imagen(url, nombre_archivo, carpeta):
"""Descarga una imagen desde URL"""
try:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Referer": "https://pagina-.com/"
}
response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
# Verificar que es una imagen válida
img = Image.open(BytesIO(response.content))
# Convertir a RGB si es necesario
if img.mode in ('RGBA', 'LA', 'P'):
img = img.convert('RGB')
# Guardar como JPG
ruta_archivo = os.path.join(carpeta, f"{nombre_archivo}.jpg")
img.save(ruta_archivo, "JPEG", quality=90)
print(f"✅ {nombre_archivo}.jpg ({img.size[0]}x{img.size[1]})")
return True
except Exception as e:
print(f"❌ Error descargando {nombre_archivo}: {e}")
return False
def mostrar_instrucciones_manuales():
"""Muestra instrucciones para identificar las miniaturas correctas"""
print("""
🎯 IDENTIFICAR MINIATURAS MANUALMENTE:
1. Abre la colección en tu navegador
2. Presiona F12 → pestaña Elements
3. Click en el selector (flecha) y haz click en una miniatura de reloj
4. Observa el HTML para identificar la estructura
Las miniaturas suelen estar en:
- <img> dentro de contenedores como .model-card, .grid-item, article
- URLs que contienen: thumb, preview, model, small
- Tamaños típicos: 200x200, 300x300, 400x400 píxeles
🔧 Script manual para consola del navegador:
""")
script_manual = '''
// Ejecutar en consola (F12 → Console)
// Buscar todas las imágenes que parezcan miniaturas
let miniaturas = Array.from(document.querySelectorAll('img'))
.filter(img => {
let src = img.src;
let width = img.naturalWidth || img.width;
let height = img.naturalHeight || img.height;
// Filtrar por tamaño y URL
return src &&
(width >= 150 && width <= 500) &&
(height >= 150 && height <= 500) &&
(src.includes('thumb') || src.includes('preview') || src.includes('model'));
});
console.log(`Miniaturas encontradas: ${miniaturas.length}`);
// Mostrar información de cada miniatura
miniaturas.forEach((img, i) => {
console.log(`${i+1}. ${img.alt || 'Sin título'}`);
console.log(` URL: ${img.src}`);
console.log(` Tamaño: ${img.naturalWidth}x${img.naturalHeight}`);
console.log('---');
});
// Descargar automáticamente (puede fallar por seguridad del navegador)
miniaturas.forEach((img, i) => {
let a = document.createElement('a');
a.href = img.src;
a.download = `reloj_${i+1}_${(img.alt || 'modelo').replace(/[^a-zA-Z0-9]/g, '_')}.jpg`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
'''
print(script_manual)
if __name__ == "__main__":
url_coleccion = "https://pagina-.com/collections/1715414-wall-clock-hueforge"
print("🎯 DESCARGADOR DE MINIATURAS DE COLECCIÓN")
print("=" * 50)
print("1. Descargar con Selenium (automático)")
print("2. Mostrar instrucciones manuales")
opcion = input("\nElige opción (1/2): ").strip()
if opcion == "1":
try:
descargar_miniaturas_coleccion(url_coleccion)
except Exception as e:
print(f"❌ Error: {e}")
print("\n💡 Si hay problemas, intenta la opción manual (2)")
elif opcion == "2":
mostrar_instrucciones_manuales()
else:
print("❌ Opción no válida")