| name | scrapling-scraper |
| description | Web scraping con Scrapling — bypass anti-bot automático (Cloudflare, 403, WAF). Selecciona el fetcher correcto según el sitio, extrae datos con CSS/XPath, descarga archivos. Úsalo cuando requests/httpx fallen con 403 o cuando el sitio tenga protección anti-bot. |
| version | 1.0.0 |
| platforms | ["linux","macos","windows"] |
| metadata | {"hermes":{"tags":["scraping","web","automation","anti-bot","cloudflare","mercadolibre","requests"],"category":"web","fallback_for_toolsets":[],"requires_toolsets":["terminal"]}} |
Scrapling Scraper
When to Use
Activá esta skill cuando:
- Una URL devuelve 403, 401, o bloqueo anti-bot
- Necesitás scrape de MercadoLibre, Cloudflare-protected sites, o cualquier sitio con WAF
requests o httpx fallan pero el sitio carga bien en el navegador
- Necesitás extraer datos de páginas con JavaScript dinámico
- Querés descargar imágenes o archivos en bulk desde resultados de búsqueda
Fetcher Decision Tree
¿El sitio tiene Cloudflare Turnstile o WAF?
└─ SÍ → StealthyFetcher (Camoufox headless)
└─ NO → ¿Necesita JS para renderizar contenido?
└─ SÍ → DynamicFetcher (Playwright)
└─ NO → Fetcher (HTTP rápido, TLS fingerprint)
Regla práctica:
Fetcher → APIs públicas, sitios estáticos
StealthyFetcher → MercadoLibre, e-commerce, cualquier 403
DynamicFetcher → SPAs, contenido que aparece después de scroll/click
Installation
pip install "scrapling[fetchers]"
scrapling install
Procedure
1. Scrape básico con bypass anti-bot
from scrapling.fetchers import StealthyFetcher
page = StealthyFetcher.fetch('https://sitio.com/busqueda', headless=True, network_idle=True)
items = page.css('li.resultado')
for item in items:
titulo = item.css('h2::text').get()
precio = item.css('.precio::text').get()
imagen = item.css('img').attrib.get('data-src') or item.css('img').attrib.get('src')
print(titulo, precio, imagen)
2. Scrape de MercadoLibre (caso probado)
from scrapling.fetchers import StealthyFetcher
from urllib.parse import quote_plus
import time
def buscar_en_ml(query, max_resultados=6):
url = f"https://listado.mercadolibre.com.ar/{quote_plus(query)}"
page = StealthyFetcher.fetch(url, headless=True, network_idle=True)
resultados = []
items = page.css('li.ui-search-layout__item')
if not items:
items = page.css('.ui-search-result')
for item in items[:max_resultados]:
titulo_el = item.css('h2.poly-box a, .poly-component__title, h2 a')
img_el = item.css('img.poly-component__picture, img.ui-search-result-image__element, img')
link_el = item.css('a.poly-component__anchor, a.ui-search-result__image-anchor, a')
titulo = titulo_el[0].text.strip() if titulo_el else ""
img_url = ""
if img_el:
img_url = img_el[0].attrib.get('data-src') or img_el[0].attrib.get('src', '')
import re
img_url = re.sub(r'-[A-Z]\.(?:jpg|webp|png)', '-O.jpg', img_url)
permalink = link_el[0].attrib.get('href', '') if link_el else ""
if titulo:
resultados.append({'titulo': titulo, 'imagen': img_url, 'url': permalink})
return resultados
3. Sesión persistente (múltiples páginas)
from scrapling.fetchers import StealthyFetcher
import time
queries = ["horno electrico 30 litros", "freidora de aire 7 litros"]
for query in queries:
resultados = buscar_en_ml(query)
print(f"{query}: {len(resultados)} resultados")
time.sleep(3)
4. Descargar imágenes encontradas
import requests
import os
def descargar_imagen(url, filepath):
if not url:
return False
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
r = requests.get(url, timeout=15, headers=headers)
if r.status_code == 200:
with open(filepath, "wb") as f:
f.write(r.content)
return True
return False
os.makedirs("imagenes", exist_ok=True)
for item in resultados:
nombre = item['titulo'][:30].replace(' ', '_') + '.jpg'
descargar_imagen(item['imagen'], f"imagenes/{nombre}")
Pitfalls
configure(headless=True) no funciona en v0.4.x — siempre pasá headless=True directo en .fetch()
- No usar context manager (
with StealthyFetcher() as f) — v0.4.x usa llamadas estáticas
- Las imágenes de CDN no necesitan StealthyFetcher — usá
requests normal para descargar una vez que tenés la URL
- ML lazy-load: las imágenes de ML usan
data-src antes que src — siempre revisar ambos atributos
- Pausa entre requests: ML bloquea si hacés requests muy rápido — mínimo 2-3 segundos entre llamadas
- Error de browsers no instalados: si aparece el mensaje de Playwright, correr
scrapling install o playwright install
Verification
from scrapling.fetchers import StealthyFetcher
page = StealthyFetcher.fetch('https://httpbin.org/headers', headless=True)
print(page.status)
Match Quality (para casos de búsqueda con fuzzy matching)
from difflib import SequenceMatcher
def similitud(a, b):
return SequenceMatcher(None, str(a).upper(), str(b).upper()).ratio()
Ver references/api-quick-ref.md para referencia completa de selectores CSS/XPath.