Cómo raspar iframes con Playwright y Scrapeless
Senior Web Scraping Engineer
TL;DR:
- Un iframe contiene un documento separado que los selectores de la página padre no pueden buscar. Selecciona el marco hijo antes de localizar o extraer sus elementos.
- Playwright expone cada contexto de navegación a través de
page.frames. Identifica el hijo deseado por un nombre estable, patrón de URL o elemento iframe propietario en lugar de depender de la posición en el array. FrameyFrameLocatorsirven a diferentes necesidades de extracción. UsaFramepara el control de metadatos y ciclo de vida; usaFrameLocatorpara acciones concisas de elementos.- Playwright puede automatizar el contenido de iframe de origen cruzado a través del protocolo del navegador. El JavaScript en la página permanece sujeto a la política de mismo origen del navegador.
- La misma lógica de extracción de iframe funciona localmente y a través de Scrapeless. Pasar al Scrapeless Scraping Browser cambia la creación del navegador, no la selección del marco o el código del localizador.
- Gratis para comenzar. Nuevas cuentas de Scrapeless incluyen un tiempo de ejecución gratuito de Scraping Browser—regístrate en app.scrapeless.com.
Introducción: Comienza Con el Documento Correcto
Un iframe es un documento separado con su propia URL, ciclo de vida y DOM. Esta guía utiliza Playwright para enumerar los contextos de navegación en una página real, identifica el hijo deseado por nombre y URL, y extrae un formulario que un selector de la página padre no puede ver. La misma lógica de marco se ejecuta después de conectar Playwright al Scrapeless Scraping Browser.
Por Qué los Iframes Necesitan un Camino de Extracción Diferente
Un <iframe> incrusta otro contexto de navegación dentro de la página padre. El elemento pertenece al DOM padre; el documento cargado pertenece a un marco hijo. Un selector evaluado contra la página padre no busca en ese documento hijo.
La referencia HTML iframe describe ese contexto anidado y su propio historial de sesión. Playwright expone cada contexto como un Frame, mientras que FrameLocator te ofrece una forma concisa de localizar elementos a través del elemento <iframe>.
Por Qué Usar Playwright Con Scrapeless
Playwright puede inspeccionar los metadatos del marco e interactuar con un documento hijo incluso cuando el iframe es de origen cruzado. Ese acceso a nivel de navegador difiere del JavaScript que se ejecuta dentro de la página padre, que está restringido por la política de mismo origen.
El Scrapeless Scraping Browser lleva Chromium a un entorno de detección anti-hospedado mientras mantiene las APIs de marco de Playwright. La conexión utiliza connect_over_cdp; cada línea de extracción después de la creación del navegador permanece como Playwright estándar.
Prerrequisitos
- Python 3.10 o posterior.
playwright1.59.0 o una versión compatible actual.- Chrome/Chromium local para el completo retroceso ejecutable.
- Una cuenta de Scrapeless con fondos y
SCRAPELESS_API_KEYpara la conexión del navegador en la nube. Nuevas sesiones en la cuenta de verificación devolvieron el código 14500, por lo que la conexión en la nube es una brecha de prerrequisitos etiquetada.
Instalación
bash
python -m pip install "playwright==1.59.0"
El ejemplo ejecutable utiliza el /usr/bin/google-chrome del host. Usa un Chromium gestionado por Playwright si así es como tu proyecto proporciona navegadores.
Conectar al Scrapeless Scraping Browser
Nota: Esta conexión necesita un saldo de Scraping Browser con fondos. La cuenta de verificación final devolvió
saldo insuficiente, por favor recarga primero. Usa tu propia clave financiada; la enumeración y extracción de marcos a continuación se ejecutaron completamente en Chrome local.
python
import os
from urllib.parse import urlencode
from playwright.sync_api import sync_playwright
params = urlencode({
"token": os.environ["SCRAPELESS_API_KEY"],
"sessionTTL": 120,
"proxyCountry": "US",
})
cdp_url = f"wss://browser.scrapeless.com/api/v2/browser?{params}"
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(cdp_url)
page = browser.contexts[0].pages[0]
# Continúa con los pasos de marco a continuación.
browser.close()
Utiliza la documentación de desarrolladores de Scrapeless para los parámetros de conexión actuales.
Paso 1 — Abre una Página Con un Marco Hijo Conocido
Selenium mantiene un pequeño fixture de prueba pública. Su página padre tiene un iframe llamado iframe1-name, cuyo src carga formPage.html:
python
TARGET_URL = "https://www.selenium.dev/selenium/web/iframes.html"
page.goto(TARGET_URL, wait_until="domcontentloaded")
page.wait_for_selector("#iframe1")
page.wait_for_timeout(500)
print("título del padre:", page.title())
print("coincidencias de correo del padre:", page.locator("#email").count())
text
título del padre: Esta página tiene iframes
coincidencias de correo del padre: 0
La entrada de correo electrónico existe, pero pertenece al documento del formulario incrustado en lugar del principal.
Paso 2 — Enumerar Marcos Antes de Seleccionar Uno
page.frames contiene el marco principal más cada hijo y descendiente adjunto:
python
print("número de marcos:", len(page.frames))
for index, frame in enumerate(page.frames):
print(index, repr(frame.name), frame.url, frame.title())
text
número de marcos: 2
0 '' https://www.selenium.dev/selenium/web/iframes.html Esta página tiene iframes
1 'iframe1-name' https://www.selenium.dev/selenium/web/formPage.html Salimos de aquí
El índice cero es el documento principal. No hagas del índice uno un contrato permanente: otro anuncio, widget de consentimiento o marco de análisis puede cambiar el orden. El nombre y la URL son mejores pruebas.
Paso 3 — Seleccionar el Marco por Nombre o URL
La configuración te da señales estables:
python
named_frame = page.frame(name="iframe1-name")
url_frame = next(
frame for frame in page.frames
if frame.url.endswith("/formPage.html")
)
assert named_frame is url_frame
print("marco seleccionado:", url_frame.name)
print("título seleccionado:", url_frame.title())
Si los nombres son generados, coincide con un patrón de URL limitado o encuentra el elemento iframe que lo posee y llama a content_frame(). Falla cuando más de un candidato coincide; elegir silenciosamente el primer duplicado produce datos plausibles del widget incorrecto.
Paso 4 — Extraer Datos del Documento Hijo
Una vez que tienes el Frame, su API de localización se comporta como la del página:
python
email = url_frame.locator("#email")
selected = url_frame.locator("#multi option:checked").evaluate_all(
"options => options.map(option => option.value)"
)
record = {
"nombre_del_marco": url_frame.name,
"url_del_marco": url_frame.url,
"título_del_marco": url_frame.title(),
"entradas_de_correo_electrónico": email.count(),
"valores_seleccionados": selected,
}
print("entradas de correo electrónico:", record["entradas_de_correo_electrónico"])
print("valores seleccionados:", record["valores_seleccionados"])
text
entradas de correo electrónico: 1
valores seleccionados: ['huevos', 'salchichas']
La página hija tiene un campo de selección múltiple con esas dos opciones seleccionadas en su fuente. Esta es una verificación más sólida que leer solo un encabezado: prueba que Playwright alcanzó el documento del formulario y evaluó el estado dentro de él.
Paso 5 — Usar FrameLocator para Acciones Directas
Cuando no necesitas metadatos del marco, FrameLocator es más corto:
python
frame_ui = page.frame_locator("#iframe1")
print("correo a través de FrameLocator:", frame_ui.locator("#email").count())
La guía oficial de marcos de Playwright muestra los mismos dos niveles: localizar contenido a través de un elemento iframe, o obtener un objeto Frame por URL/nombre.
¿Listo para ejecutar esos localizadores en un navegador alojado? Crea una cuenta gratuita en Scrapeless y reemplaza solo la creación del navegador.
Script de Verificación Local Completo
python
from playwright.sync_api import sync_playwright
URL_OBJETIVO = "https://www.selenium.dev/selenium/web/iframes.html"
with sync_playwright() as p:
browser = p.chromium.launch(
executable_path="/usr/bin/google-chrome",
headless=True,
)
page = browser.new_page()
page.goto(URL_OBJETIVO, wait_until="domcontentloaded")
page.wait_for_selector("#iframe1")
page.wait_for_timeout(500)
child = next(
frame for frame in page.frames
if frame.url.endswith("/formPage.html")
)
selected = child.locator("#multi option:checked").evaluate_all(
"options => options.map(option => option.value)"
)
frame_locator_count = page.frame_locator("#iframe1").locator("#email").count()
assert page.locator("#email").count() == 0
assert child.name == "iframe1-name"
assert child.locator("#email").count() == 1
assert selected == ["huevos", "salchichas"]
assert frame_locator_count == 1
print("título del padre:", page.title())
print("coincidencias de correo en el padre:", page.locator("#email").count())
print("número de marcos:", len(page.frames))
print("nombre del hijo:", child.name)
print("URL del hijo:", child.url)
print("título del hijo:", child.title())
print("coincidencias de correo en el hijo:", child.locator("#email").count())
print("valores seleccionados:", selected)
print("coincidencias de correo en FrameLocator:", frame_locator_count)
browser.close()
La ejecución completa devuelve dos marcos, cero coincidencias de correo en el padre, una coincidencia de correo en el hijo, el nombre/título/URL del marco esperados, y ['huevos', 'salchichas'] del formulario hijo.
Lo Que Obtienes de Vuelta
El flujo de trabajo verificado devuelve tanto el estado del formulario extraído como suficientes metadatos del marco para identificar su fuente:
json
{
"coincidencias_de_correo_en_el_padre": 0,
"número_de_marcos": 2,
"nombre_del_marco": "iframe1-name",
"url_del_marco": "https://www.selenium.dev/selenium/web/formPage.html",
"título_del_marco": "Salimos de aquí",
"coincidencias_de_correo_en_el_hijo": 1,
"valores_seleccionados": ["huevos", "salchichas"]
}
La salida establece cuatro hechos: el documento principal no puede ver el campo de correo electrónico, el hijo previsto es identificable por nombre y URL, el localizador del hijo encuentra una entrada coincidente, y los valores de formulario seleccionados provienen de dentro de ese marco. Mantenga el nombre y la URL del marco con cada registro extraído cuando una página contenga múltiples documentos incrustados.
## Iframes de origen cruzado y la política de mismo origen
El JavaScript del navegador, como `document.querySelector("iframe").contentDocument`, puede estar bloqueado cuando los orígenes del padre y del hijo difieren. Playwright se comunica con el protocolo de automatización del navegador y expone al hijo como un marco, para que pueda localizar e interactuar con elementos en documentos de origen cruzado.
Eso no elimina todos los límites. Los atributos de sandbox pueden restringir scripts, la navegación puede reemplazar un marco mientras lo estás leyendo, y las extensiones del navegador o los visores de PDF pueden no exponer un documento HTML ordinario. Inspeccione el árbol de marcos real antes de escribir el contrato de extracción.
## Marcos dinámicos y anidados
### Esperar por adjuntos y navegación
Un elemento iframe puede aparecer antes de que su hijo haya alcanzado la URL final. Espere un localizador de hijo o inspeccione los eventos de navegación del marco; el marcador de preparación útil es el elemento que lleva datos, no meramente la etiqueta `<iframe>` padre.
### Esperar desvinculación
Las aplicaciones de una sola página a veces eliminan y recrean iframes. Un objeto Frame guardado puede volverse desvinculado. Resuelva el marco nuevamente desde su nombre estable, URL o elemento propietario después de la transición de la UI en lugar de asumir que el viejo objeto sobrevive.
### Recorrer marcos anidados deliberadamente
Para contextos anidados, inspeccione `frame.child_frames` o encadene FrameLocators. Mantenga la ruta padre-hijo en la procedencia de la salida para que dos widgets con el mismo nombre no puedan confundirse.
## Conclusión
La extracción de iframes comienza eligiendo el documento correcto. Enumere el árbol del marco, seleccione al hijo por nombre o URL estable, espere un elemento dentro de él y mantenga los metadatos del marco con el registro extraído. Use FrameLocator para acciones concisas y objetos Frame cuando necesite identidad, navegación o control de marcos anidados. Mover el flujo de trabajo a Scrapeless cambia la creación del navegador, no la lógica del marco.
## ¿Listo para extraer datos de iframes?
Únase a los desarrolladores que construyen flujos de trabajo de extracción basados en navegador en la comunidad de Scrapeless: [Discord](https://discord.gg/VU2vtbq7Q2) · [Telegram](https://t.me/scrapeless).
[Comience con Scrapeless](https://app.scrapeless.com/passport/login/?utm_source=website&utm_medium=blog&utm_campaign=scrapingbrowser&utm_term=iframe-web-scraping-scraping-browser), revise [precios de Scrapeless](https://www.scrapeless.com/es/pricing?utm_source=website&utm_medium=blog&utm_campaign=scrapingbrowser&utm_term=iframe-web-scraping-scraping-browser), y lea [lo que expone CDP](https://www.scrapeless.com/es/blog/what-is-chrome-devtools-protocol?utm_source=website&utm_medium=blog&utm_campaign=scrapingbrowser&utm_term=iframe-web-scraping-scraping-browser) antes de mover el mismo flujo de trabajo de marco a un navegador alojado.
## Preguntas frecuentes
**P: ¿Por qué la página principal no puede encontrar un elemento dentro de un iframe?**
El iframe posee un documento separado. Los localizadores de la página principal buscan en el contexto de navegación padre; seleccione el marco hijo o use primero un FrameLocator.
**P: ¿Debo seleccionar un marco por índice de matriz?**
No. El orden de los marcos cambia cuando las páginas añaden widgets o anuncios. Prefiera un nombre estable, un patrón de URL, o el elemento iframe propietario y falle en coincidencias ambiguas.
**P: ¿Cuál es la diferencia entre Frame y FrameLocator?**
Un Frame expone la identidad del documento, URL, nombre, ciclo de vida y marcos hijos. FrameLocator proporciona operaciones de localización concisas a través de un elemento iframe específico.
**P: ¿Puede Playwright acceder a un iframe de origen cruzado?**
Sí, Playwright puede automatizar marcos secundarios de origen cruzado a través del protocolo del navegador incluso cuando el JavaScript en la página no puede leer `contentDocument` debido a la política de mismo origen.
**P: ¿Cómo espero un iframe cargado dinámicamente?**
Espere un localizador que lleve datos dentro del marco o una URL final de marco conocida. La sola presencia del elemento iframe no prueba que su documento hijo haya terminado de navegar.
**P: ¿Qué pasa si el marco está desvinculado?**
El Frame guardado ya no representa un documento vivo. Resuelva el marco de reemplazo nuevamente a partir de evidencia estable después de la transición de la página.
**P: ¿Es legal la extracción de iframes?**
La incrustación no cambia los derechos de datos o términos del objetivo. Revise la política del sitio y del proveedor incrustado, honre las <a href="https://datatracker.ietf.org/doc/html/rfc9309" rel="nofollow"><strong>directivas de robots</strong></a> cuando sea aplicable, mantenga el volumen acotado y busque asesoría legal para colecciones sensibles o comerciales.
En Scrapeless, solo accedemos a datos disponibles públicamente y cumplimos estrictamente con las leyes, regulaciones y políticas de privacidad del sitio web aplicables. El contenido de este blog es sólo para fines de demostración y no implica ninguna actividad ilegal o infractora. No ofrecemos garantías y renunciamos a toda responsabilidad por el uso de la información de este blog o enlaces de terceros. Antes de realizar cualquier actividad de scraping, consulte a su asesor legal y revise los términos de servicio del sitio web de destino u obtenga los permisos necesarios.



