Saltar al contenido
Empezar gratis
Volver al blog

Tutorial de Python de Nodriver: Extracción de datos de navegadores de forma sigilosa, desde el primer script hasta la puesta en producción

Suciu DanÚltima actualización el 15 min read
Tutorial de Python de Nodriver: Extracción de datos de navegadores de forma sigilosa, desde el primer script hasta la puesta en producción
En resumen: Nodriver es una biblioteca asíncrona de Python que controla Chromium mediante el Chrome DevTools Protocol, sin Selenium ni el binario chromedriver. Úsala cuando un navegador sigiloso autoalojado, más parecido a una sesión real de Chrome, sea mejor opción que una pila WebDriver, pero ten en cuenta que por sí sola no elimina los riesgos de IP, TLS o comportamiento. Este tutorial va desde un primer script hasta la producción en contenedores y una Browser API alojada.

Nodriver es una biblioteca asíncrona de Python que controla Chromium a través del protocolo Chrome DevTools, sin necesidad de Selenium ni del binario chromedriver. Recurre a ella cuando un navegador oculto autohospedado, que se asemeja más a una sesión real de Chrome, supera a una pila clásica de WebDriver. Esta guía comienza con un rastreador operativo en un entorno de pruebas público, pasa por un entorno de producción en contenedor y termina explicando cuándo ese mismo flujo debe ejecutarse en una API de navegador alojada.

Puntos clave

  • Nodriver se comunica directamente con el CDP; por sí solo, no elimina los riesgos relacionados con la IP, el TLS ni el comportamiento.
  • Fija la versión. En la 0.50.3 + Chrome 154 (06/10/2026), select devuelve None en caso de fallo, wait_for genera un error y xpath falló con DOM.enable falta.
  • Prefiero uc.loop() a asyncio.run para un apagado limpio; browser.stop() es «sync».
  • Para trabajos en los que la discreción es importante, es preferible utilizar Chrome con interfaz gráfica bajo Xvfb: la versión sin interfaz gráfica sigue pudiendo anunciarse HeadlessChrome en el UA.
  • La producción es donde fallan los rastreadores: contenedores, concurrencia limitada, reintentos, comprobaciones de IP de salida y validación de resultados.
  • Asigna las esperas y acciones a los parámetros de la API del navegador (wait_for_css, wait_until, js_instructions, …) cuando el autoalojamiento se te quede pequeño.

Qué es nodriver (y qué no es)

CDP directo frente a WebDriver

Ruta clásica de Selenium:

Your script  →  WebDriver protocol  →  chromedriver  →  Chrome

Ruta de Nodriver:

Your script  →  Chrome DevTools Protocol (websockets)  →  Chrome

Al prescindir del binario del controlador, se eliminan los marcadores de automatización específicos de WebDriver y toda una clase de fallos debidos a discrepancias entre versiones. No convierte tu IP en residencial, ni hace que tu pila TLS sea única, ni que la sincronización de tus clics sea humana.

Linaje de undetected-chromedriver

Nodriver es el sucesor asíncrono y centrado en CDP, procedente del mismo linaje de autores que undetected-chromedriver. El modelo pasa de «parchear el controlador» a «no utilizar nunca el controlador». Solo para navegadores de la familia Chromium; API exclusivamente asíncrona.

A qué capas de detección se dirige

Capa

Lo que tienen en cuenta los defensores

Qué cambia Nodriver (modelo)

Entorno JS

navigator.webdriver, peculiaridades del objeto Chrome

Mejora la huella de automatización de JS por defecto frente a WebDriver sin modificar (aún así, hay que verificarlo para cada objetivo)

Protocolo / controlador

Huellas digitales de ChromeDriver

Evita el uso de WebDriver mediante CDP

TLS / HTTP2

Huellas de JA3 / ALPN / HTTP2

No sustituye la pila de red del navegador

IP / ASN / ubicación geográfica

Rangos de centros de datos, reputación

No lo soluciona; requiere proxies / enrutamiento residencial

Comportamiento

Tiempos de respuesta, trayectorias del ratón, patrones de desplazamiento

No simula el comportamiento humano por ti

Señales sin interfaz gráfica

HeadlessChrome UA, plugins que faltan, etc.

Depende del modo; consulta nuestra sección sobre modo sin interfaz gráfica

¿Debería tu equipo desarrollar en nodriver? (cuadro de decisión)

Comprobado en torno a la preparación de la publicación del 6 de octubre de 2026:

  • Licencia: AGPL-3.0 en el paquete de PyPI que hemos instalado. Esto es importante para los servicios conectados a la red que modifican y ejecutan el código. Esto no constituye asesoramiento jurídico: consulta con un abogado la licencia AGPL si lanzas un SaaS basado en una bifurcación.
  • Estructura de la API: solo asíncrona; navegadores de la familia Chromium.
  • Mantenimiento: la última versión de PyPI comprobada para esta guía es la 0.50.3 (13 de mayo de 2026). Vuelve a comprobar las estrellas, los incidencias y las confirmaciones el día de la publicación antes de comprometerte con una plataforma a largo plazo.
  • Cobertura de pruebas / clasificador alfa: PyPI sigue indicando «Estado de desarrollo :: 3 - Alfa». Prepárate para posibles fallos cuando Chrome cambie.
  • Bifurcaciones: existen Zendriver y otras bifurcaciones de CDP si necesitas una estrategia de mantenimiento diferente; consulta la matriz de herramientas más adelante.

¿Necesitas compatibilidad con varios navegadores (Firefox/WebKit), API de sincronización o una licencia permisiva para un producto comercial sin análisis de la AGPL? Nodriver puede no ser la base adecuada.

Instalación y verificación (fijado)

python3 -m venv venv
source venv/bin/activate
pip install 'nodriver==0.50.3'

Lista de comprobación de la instalación:

  1. Python ≥ 3.9.
  2. Una instalación local de Chrome/Chromium (confirmar con google-chrome --version).
  3. Dependencias de tiempo de ejecución obtenidas automáticamente: websockets>=14 , mss, deprecated.
  4. No le pongas a tu script un nombre nodriver.py (ya que se superpone al paquete).
  5. Prueba básica: abre una página pública y espera a que aparezca un selector (script más abajo).

Tu primer rastreador

Entorno de pruebas para este artículo: quotes.toscrape.com, un objetivo de demostración diferente al sitio web utilizado en varios tutoriales de la competencia.

# 01_first_scraper.py — verified 2026-10-06 on nodriver 0.50.3
import nodriver as uc

async def main():
    browser = None
    try:
        browser = await uc.start(headless=True)
        tab = await browser.get("https://quotes.toscrape.com/")
        await tab.select("div.quote", timeout=15)  # wait for state, not time
        quotes = await tab.select_all("div.quote")
        for q in quotes:
            text_el = await q.query_selector("span.text")
            author_el = await q.query_selector("small.author")
            print((text_el.text or "").strip(), "—", (author_el.text or "").strip())
    finally:
        if browser is not None:
            browser.stop()  # sync on 0.50.3 — do not await

if __name__ == "__main__":
    # Package README recommends uc.loop(); see event-loop notes below
    uc.loop().run_until_complete(main())

Selección y extracción fiables

Tabla de decisión del método de selección (0.50.3)

Necesidad

Método

En caso de fallo (0.50.3, 06/10/2026)

Utilizar cuando

Esperar + CSS

await tab.select(css, timeout=…)

Devuelve None (no genera excepción; la cadena de documentación es incorrecta)

Esperada de disponibilidad por defecto

CSS de un solo uso

await tab.query_selector(css)

Devuelve None

Ya sabes que el DOM está listo

Esperada que debe fallar de forma evidente

await tab.wait_for(selector=…)

Lanza TimeoutError

Barrera insalvable antes de continuar

Búsqueda de texto

await tab.find(text, best_match=True)

Error leve tras varios intentos

Botones/etiquetas sin CSS estable

Muchos nodos

await tab.select_all(css)

Comportamiento similar al de una lista vacía tras varios intentos

Listas/tarjetas

XPath

await tab.xpath(…)

Deja de funcionar en la versión 0.50.3 + Chrome 154 — ProtocolException: 'DOM.enable' wasn't found

Se prefieren los selectores CSS

Ayudas para texto y atributos

def attr_get(el, name: str):
    if el is None:
        return None
    attrs = el.attrs  # ContraDict in nodriver 0.50.3
    if attrs is None:
        return None
    try:
        return attrs.get(name)
    except Exception:
        try:
            return attrs[name]
        except Exception:
            return None

# Observed: element.text and element.text_all both return usable strings

Estado de XPath en la versión 0.50.3 + Chrome 154

Falló en Chrome 154 + nodriver 0.50.3 (06/10/2026) al llamar a DOM.enable. No se deben distribuir rastreadores que dependan de XPath en esta combinación sin una nueva verificación.

Páginas dinámicas

A la espera de un estado, no de tiempo

Esperar a un selector, texto o a que la red esté inactiva. Solucionado sleep es para casos excepcionales de depuración visual, no para rastreadores definitivos. Prefiere select / wait_for en lugar de tab.sleep en las rutas de producción.

Paginación que se mantiene tras la navegación

Al hacer clic en «Siguiente», los identificadores de los elementos anteriores pueden desvincularse. Vuelve a consultar el control en cada intento; espera a que cambie la URL o a que aparezca un nuevo selector de contenido.

# Pagination retry pattern for quotes.toscrape.com-style next links
async def click_next_with_retry(tab, max_attempts=3) -> bool:
    for _ in range(max_attempts):
        next_link = await tab.select("li.next > a", timeout=5)
        if next_link is None:
            return False
        before = tab.url
        try:
            await next_link.click()
        except Exception:
            continue
        for _ in range(20):
            await tab.sleep(0.25)
            await tab.select("div.quote", timeout=2)
            if tab.url != before:
                return True
        if tab.url != before:
            return True
    return False

Páginas 1→2→3 avanzadas; los autores han cambiado según lo esperado.

Desplazamiento infinito con condiciones de parada

Para las páginas sin un control de enlace «Siguiente», desplázate hasta una condición de parada: un marcador de fin, un recuento máximo o el número máximo de rondas.

async def scroll_until_plateau(tab, max_rounds=20):
    history = []
    plateau = 0
    for round_i in range(1, max_rounds + 1):
        items = await tab.select_all("div.item")
        count = len(items)
        end = await tab.query_selector("#end-marker")
        history.append(count)
        if end is not None:
            return {"reason": "end_marker", "count": count}
        if len(history) >= 2 and history[-1] == history[-2]:
            plateau += 1
        else:
            plateau = 0
        if plateau >= 2:
            return {"reason": "count_plateau", "count": count}
        await tab.evaluate("window.scrollTo(0, document.body.scrollHeight)")
        await tab.sleep(0.4)
    return {"reason": "max_rounds", "count": history[-1] if history else 0}

Se detuvo en end_marker en 40 elementos tras 4 rondas.

Clics, pestañas, iframes y evaluate (breve)

  • Nueva pestaña/ventana: browser.get(url, new_tab=True) / new_window=True (API del paquete).
  • tab.evaluate(expr) para sondas de desplazamiento/DOM: utiliza selectores siempre que puedas.
  • Cookies: trata los archivos JAR como información confidencial; ocúltalos en los registros (nota de seguridad, no es un tutorial exhaustivo sobre cookies).
  • Capturas de pantalla: await tab.save_screenshot(...) funcionaron en nuestra ejecución de diagnóstico.

Identidad: agente de usuario, modo sin interfaz gráfica y Xvfb

Una identidad constante frente a la rotación

Haz que el agente de usuario coincida con la versión de Chrome que realmente ejecutas. Una rotación aleatoria que no coincida con Chrome/154 (o lo que sea que ejecutes) es un indicio fácil de detectar. Es preferible utilizar una identidad de escritorio estable por cada perfil de trabajador.

Señales de modo sin interfaz gráfica en Chrome 154 (06/10/2026)

Solo frente a páginas de diagnóstico públicas (bot.sannysoft.com; areyouheadless se devolvió un 502 en ambos modos):

Modo

navigator.userAgent

navigator.webdriver

headless=True

contiene HeadlessChrome/154.0.0.0

False

headless=False en Xvfb

contiene Chrome/154.0.0.0 (sin Headless)

False

El 154.0.0.0 textos mencionados son la forma abreviada del agente de usuario de Chrome, no un error tipográfico respecto a la 154.0.8037.57 . Nodriver puede borrar navigator.webdriver en ambos modos, mientras que el modo sin interfaz gráfica sigue identificándose a sí mismo a través de la cadena de agente de usuario. Eso por sí solo es suficiente para muchas comprobaciones sencillas.

Se ejecuta bajo Xvfb como opción predeterminada para tareas que requieren discreción

En servidores Linux sin pantalla física:

# pattern
xvfb-run -a python your_scraper.py
# or export DISPLAY to a running Xvfb and start(headless=False)

Utiliza el modo sin interfaz gráfica para entornos de pruebas internos y CI. Utiliza el modo con interfaz gráfica + Xvfb cuando el destino detecte las cadenas de agente de usuario del modo sin interfaz gráfica.

Proxies sin filtrar tu IP

Proxies sin autenticación frente a proxies con autenticación

No des por sentado que las configuraciones de Chrome son iguales a las de otros blogs. Antes de automatizar los muros de inicio de sesión detrás de un proxy, comprueba en tu versión de Chrome que la IP de salida del navegador sea la del proxy, y no la de tu host.

Comprueba siempre la IP de salida

# Guard pattern — wire to your proxy stack; always assert exit IP before scraping
async def assert_exit_ip(tab, expected_subnet_prefix: str | None = None):
    tab2 = await tab.browser.get("https://httpbin.org/ip")  # or your IP echo
    await tab2.select("body", timeout=15)
    body = (await tab2.get_content()) if hasattr(tab2, "get_content") else None
    # parse JSON IP; compare to expected proxy IP; fail closed
    return body

Rechaza la tarea si la IP de salida observada es la de tu servidor del centro de datos. Realiza esta comprobación en producción incluso cuando el proxy «parezca estar configurado».

Enrutamiento residencial y geográfico

Cuando el problema sea la reputación de la IP o la afinidad con un país —y no la automatización del DOM—, enruta a través de proxies residenciales o traslada el trabajo del navegador a una solicitud de la API del navegador con country set.

Ejecución de nodriver en entorno de producción

La mayoría de los tutoriales se detienen antes de llegar a este punto. Aquí es donde los rastreadores fracasan.

Receta de contenedor (esquema)

# Outline only — adapt paths and package names for your base image
FROM python:3.13-slim-bookworm
RUN apt-get update && apt-get install -y --no-install-recommends \
    wget gnupg ca-certificates fonts-liberation xvfb \
    && install Google Chrome / Chromium per your distro docs \
    && useradd -m scraper
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
USER scraper
ENV DISPLAY=:99
CMD ["sh", "-c", "Xvfb :99 -screen 0 1920x1080x24 & python worker.py"]

Notas: ejecútalo sin privilegios de root; comprende los indicadores de sandbox de Chrome en contenedores restringidos; guarda los perfiles en un volumen en el que se pueda escribir si reutilizas cookies que te ha costado mucho conseguir; y oculta esas cookies en los registros.

Modelo de concurrencia

Unidad

Aislamiento

Uso típico

Pestañas en un mismo navegador

Proceso compartido/cookies/huella digital

Pasos relacionados en una misma sesión

Varios navegadores

Mejor aislamiento, más RAM

Tareas en paralelo

Múltiples procesos/contenedores

Máximo aislamiento

Flotas de trabajadores

Concurrencia limitada con un asyncio.Semaphore (o trabajadores en cola). Mide el consumo de memoria por navegador en páginas similares a las de producción en tu hardware.

Reintentos, tiempos de espera y recuperación tras fallos

  • Tiempo de espera por navegación con wait_for / select límites.
  • Clasifica los errores: tiempo de espera agotado, ventana vacía, página de verificación, fallo de Chrome.
  • Reinicia el proceso del navegador tras errores de protocolo repetidos, no solo la pestaña.
  • Limitar los reintentos con un retroceso aleatorio.

Observabilidad

  • Métricas: éxito / bloqueo / tiempo de espera / vacío por host.
  • Captura de pantalla en caso de fallo en almacenamiento de objetos.
  • Ocultación de datos en los registros: nombre de usuario/contraseña del proxy, Cookie encabezados y volcados de almacenamiento.

Validación de la salida

Un «éxito» de tipo HTTP en el navegador no es HTML utilizable. Detecta títulos de desafío, plantillas de aplicación vacías y selectores obligatorios que falten antes de escribir en el almacén. Combina esto con la mentalidad de validación de tu pila de scraping más amplia (evita que te bloqueen).

Comprobación de la realidad anti-bot

Ámbito (06-10-2026): solo páginas públicas de huellas digitales y diagnóstico. No se incluyen objetivos comerciales de Cloudflare ni DataDome (según la política editorial de este artículo).

Objetivo

Resultado

bot.sannysoft.com

Cargado; útil para comparar el UA y el webdriver

arh.antoinevastel.com/bots/areyouheadless

502 Bad Gateway — no concluyente

Páginas comerciales de Cloudflare / DataDome / Turnstile

No se trata en esta guía

Tab.verify_cf ayuda

Presente en la versión 0.50.3; considéralo opcional y compruébalo en tus objetivos

Considera cualquier afirmación del tipo «nodriver elude X» que no vaya acompañada de una prueba con fecha y alcance definido como mera estrategia de marketing. Para objetivos reforzados, consulta también cómo eludir Cloudflare en la guía del producto.

Elige tu herramienta (matriz por restricción)

Versiones comprobadas a través del índice PyPI el 6 de octubre de 2026. La postura de sigilo es cualitativa, no una puntuación.

Herramienta

Idioma

Navegadores

Sincrónico/asíncrono

Licencia (señal de PyPI)

Postura de sigilo

Carga operativa

nodriver 0.50.3

Python

Familia Chromium

asíncrono

AGPL-3.0

CDP, sin WebDriver

Ejecutas Chrome + pantalla

Zendriver 0.17.1

Python

Familia Chromium

asíncrono

AGPL

Bifurcación del linaje de nodriver

Similar

Playwright 1.63.0

muchos

Chromium, Firefox, WebKit

ambos

Apache-2.0 (proyecto)

Automatización sólida, más fácil de detectar tal cual

Gestión de controladores más ligera

Patchright 1.63.0

Python

Canal Chromium/Chrome

ambos

consulta la LICENCIA

Playwright parcheado

Similar a Playwright

Camoufox 0.5.7

Python

Firefox (personalizado)

ambos

MIT (PyPI)

Ángulo de huella digital de Firefox

Operaciones binarias del navegador

SeleniumBase 4.55.1 (modo CDP)

Python

Chromium

ambos

MIT

Opción de modo CDP

Peso del marco

API del navegador alojado

cualquiera (HTTP)

gestionado

n/a

comercial

Gestionado por el proveedor

Mínimo de operaciones locales

Elección en función de las restricciones: licencia, motor del navegador, necesidades de sincronización y quién es responsable del tiempo de actividad.

Desarrollar o comprar: nodriver autohospedado o un navegador alojado

Qué factores influyen en el coste

  • Pantallas / Xvfb / peculiaridades de la GPU en máquinas virtuales en la nube
  • RAM y CPU por sesión simultánea de Chrome
  • Proxies residenciales o móviles
  • Tiempo de desarrollo para actualizaciones de Chrome y selectores defectuosos
  • Gestión de bloqueos y servicio de guardia
  • Almacenamiento de capturas de pantalla y supresión de datos personales
  • Revisión del cumplimiento de la AGPL

Alójalo tú mismo cuando necesites sesiones interactivas prolongadas, extensiones personalizadas o una estrecha integración con redes internas. Cómpralo cuando quieras liberarte de las responsabilidades relacionadas con los SLA de solicitud/respuesta, la geolocalización y el mantenimiento del navegador.

Nodriver → Tabla de traducción de la API del navegador

La API del navegador es una llamada REST a https://api.webscrapingapi.com/v1—no un socket CDP en tiempo real (confirmación del producto). Nombres de parámetros verificados en los parámetros de la API el 6 de octubre de 2026:

Patrón de Nodriver

Parámetro de la API del navegador

Esperar a CSS (select / wait_for)

wait_for_css

Preparación del ciclo de vida

wait_until (domcontentloaded, load, networkidle0, networkidle2)

Retardo adicional

wait_for (ms)

Secuencias de clics, desplazamientos y pulsaciones

js_instructions

Captura de pantalla

screenshot=1 (+ screenshot_options)

Extracción de campos

extract_rules

Contexto geográfico

country

Dispositivo / ventana gráfica

device, window_width, window_height

Documentación: solicitud GET, renderización de JavaScript.

Cuando la API de Scraper ( render_js=1 ) es suficiente

render_js=1) es suficiente

Si solo necesitas una instantánea HTML renderizada sin un script de interacción de varios pasos, empieza con la API de Scraper y el renderizado en JS. Pasa a la API del navegador cuando necesites acciones ordenadas, esperas de selectores, capturas de pantalla o reglas de extracción en una sola solicitud. Compara las opciones en «API de acceso web».

Solución de problemas (síntoma → causa → solución)

A partir de los errores que reproducimos el 6 de octubre de 2026:

Síntoma

Causa probable

Solución

select devuelve None tras el tiempo de espera

Selector incorrecto o contenido que nunca se ha renderizado

Corrige el selector; comprueba con wait_for si necesitas un fallo definitivo

TimeoutError de wait_for

Esperado — fallo tras agotarse el presupuesto

Amplía el tiempo de espera o publica una captura de pantalla

ProtocolException: 'DOM.enable' wasn't found

xpath ruta en nuestro Chrome 154 + 0.50.3

Utiliza CSS; vuelve a probar el XPath tras las actualizaciones

UA contiene HeadlessChrome

headless=True

Ejecutar bajo Xvfb para objetivos sensibles

Tareas pendientes / Event loop is closed tras el script

asyncio.run Apagado frente a los oyentes de nodriver

Preferir uc.loop(); asegúrate de browser.stop() en finally

Lista de citas vacía tras «éxito»

Navegación prematura / página incorrecta

Volver a esperar en el selector de contenido; validar el recuento

Paginación atascada

Manejo del enlace siguiente obsoleto

Volver aselect control «siguiente» en cada intento

El proxy «funciona», pero el sitio detecta la IP de origen

Configuración incorrecta de autenticación/proxy

Protección de la IP de salida antes del rastreo

Uso responsable

Extrae solo páginas públicas elegibles, respeta los robots/Términos de servicio y la legislación aplicable, minimiza los datos personales y protege las credenciales. Lee «Datos web responsables». Para un contexto «headless» más amplio, consulta «Navegador headless en Python».

Preguntas frecuentes

¿Qué es nodriver?

Una biblioteca asíncrona de Python que controla Chromium a través de CDP sin necesidad de Selenium ni Chromedriver. Esta guía utiliza la versión 0.50.3 (comprobada el 6 de octubre de 2026).

¿En qué se diferencia nodriver de undetected-chromedriver y de Selenium?

Selenium utiliza WebDriver + un binario de controlador. Undetected-chromedriver aplica parches a esa ruta. Nodriver omite WebDriver y se comunica con CDP de forma asíncrona.

¿Es detectable nodriver?

Elimina algunas señales de automatización, pero no borra las fugas de IP, TLS, comportamiento o UA en modo headless. En nuestra prueba, navigator.webdriver no False, pero el modo sin interfaz gráfica seguía expuesto HeadlessChrome en el UA.

¿Funciona nodriver en modo sin interfaz gráfica?

Sí, para el scraping funcional en nuestro entorno de pruebas. Para objetivos en los que el sigilo es importante, es preferible el modo con interfaz gráfica + Xvfb, según la diferencia en el UA que hemos medido.

¿Cómo puedo utilizar un proxy autenticado con nodriver sin revelar mi IP?

Configura el proxy para tu versión de Chrome y, a continuación, comprueba siempre la IP de salida antes de iniciar el trabajo.

¿Puede nodriver eludir Cloudflare o DataDome?

No generalices a partir de páginas de diagnóstico para productos comerciales de bots. Si utilizas verify_cf la versión 0.50.3, compruébalo en tus propios objetivos antes de confiar en ello.

Nodriver, Playwright o Zendriver: ¿cuál debería utilizar?

Elige según la licencia, el motor del navegador, las necesidades de sincronización/asincronización y quién se encarga de las operaciones; consulta la matriz anterior. Playwright destaca en el ámbito multimotor; nodriver y zendriver están optimizados para un enfoque sigiloso de CDP con licencia AGPL; la API de navegador alojada es la mejor opción cuando no quieres flotas de Chrome.

¿Cómo ejecuto Nodriver en Docker o en un servidor Linux?

Instala Chrome, ejecútalo en modo «headed» bajo Xvfb (o acepta las limitaciones del modo «headless»), como usuario no root y con trabajadores limitados. Utiliza el esquema del Dockerfile como punto de partida y valida la imagen en tu entorno.

¿Cuántos navegadores de nodriver puedo ejecutar en paralelo?

Compruébalo en tu hardware y con las páginas de destino. No te fíes de las afirmaciones sobre concurrencia sin tus propias cifras.

¿Es seguro utilizar nodriver con fines comerciales (licencia)?

El paquete que hemos instalado está bajo licencia AGPL-3.0. Consulta con un asesor legal antes de integrarlo en un servicio de red. Esto no constituye asesoramiento jurídico.

¿Cuándo debería utilizar una API de navegador alojada en lugar de nodriver?

Cuando quieras esperas/acciones/datos geográficos REST sin tener que ejecutar Chrome, o cuando los costes de proxy y mantenimiento sean predominantes. Convierte tus esperas de nodriver en wait_for_css / js_instructions y compara una solicitud.

Siguiente paso

Elige una página que tu script de nodriver ya gestione y envíala mediante una única solicitud de la API del navegador con wait_for_css (y js_instructions si te desplazas o haces clic). Compara el tiempo de desarrollo, los modos de fallo y el formato de los resultados. Para grandes volúmenes, datos geográficos o entregas gestionadas, ponte en contacto con el equipo de WebScrapingAPI.


Acerca del autor

Suciu Dan, Cofundador @ WebScrapingAPI

Suciu Dan

Cofundador

Suciu Dan es cofundador de WebScrapingAPI y escribe guías prácticas dirigidas a desarrolladores sobre el scraping web con Python, el scraping web con Ruby y las infraestructuras de proxy.

Cómo gestionar las URL de redireccionamiento de Google /goto y los tokens CAES en un rastreador de SERP
La ciencia del web scraping

Cómo gestionar las URL de redireccionamiento de Google /goto y los tokens CAES en un rastreador de SERP

TL;DR: En resumen: Las URL /goto de Google con un token CAES, y los envoltorios /url más antiguos, son capas de redirección, no destinos, así que un scraper de SERP que trata cada href como final rompe el seguimiento de posiciones y los almacenes de enlaces. Prefiere una API de SERP estructurada cuando devuelva los enlaces de destino. Si tienes que analizar HTML, clasifica cada href, elimina redirecciones duplicadas y resuélvelas con un GET simple. No descifres CAES.

Suciu Dan13 min read
Leer artículo
Cabeceras de Respuesta HTTP en cURL: Cada Bandera, Técnica y Receta de Scripting
La ciencia del web scraping

Cabeceras de Respuesta HTTP en cURL: Cada Bandera, Técnica y Receta de Scripting

TL;DR: cURL oculta las cabeceras de respuesta por defecto. Utilice -i para ver las cabeceras junto con el cuerpo, -I para una solicitud HEAD que sólo devuelva cabeceras, -v para una depuración completa de solicitud/respuesta y -D para guardar las cabeceras en un archivo. Para scripts modernos, cURL 7.83+ le permite extraer cabeceras individuales o volcarlas todas como JSON con la opción -w write-out.

Suciu Dan13 min read
Leer artículo
¿Qué es un Headless Browser? Arquitectura, casos de uso y principales herramientas
La ciencia del web scraping

¿Qué es un Headless Browser? Arquitectura, casos de uso y principales herramientas

TL;DR: Un navegador sin cabeza es un navegador web que se ejecuta sin una interfaz gráfica visible, controlado enteramente a través de código o instrucciones de línea de comandos. Los desarrolladores utilizan los navegadores sin cabeza para pruebas automatizadas, web scraping, monitorización del rendimiento y, cada vez más, para potenciar agentes de IA. Esta guía explica cómo funcionan internamente, cuándo elegir uno en lugar de un navegador normal y qué frameworks merecen la pena.

Suciu Dan16 min read
Leer artículo

Empieza a crear

¿Estás listo para ampliar tu recopilación de datos?

Únete a más de 2000 empresas que utilizan WebScrapingAPI para extraer datos de la web a escala empresarial sin ningún gasto de infraestructura.