Estoy tratando de obtener el contenido completo de una página con titiritero, esto funciona bien con páginas normales, pero si hace una redirección de window.location de ventana, quiero bloquear esa redirección y solo obtener el contenido original:
Ex. Si https://example.com/thisredirects devuelve
<html> <body> <p>Page not found - Please wait while we redirect you home...</p> <script type="text/javascript" language="javascript"> window.location = "//example.com"; </script> </body> </html> Quiero obtener ese html y bloquear la redirección de ubicación. Si trato de bloquear/abortar el cambio de ubicación con setRequestInterception , la respuesta devuelve nulo y en realidad no bloquea por completo la redirección (funciona para un código de estado de redirección, pero no para una página que devuelve 200 y luego redirige con window.location ):
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch({ headless: false }); const pageUrl = "https://example.com/thisredirects"; const page = await browser.newPage(); await page.setCacheEnabled(false); await page.setRequestInterception(true); const requests = []; page.on('request', async request => { let isNavRequest = request.isNavigationRequest() && request.frame() === page.mainFrame(); if (!isNavRequest) { request.continue(); return; } requests.push(request); if (requests.length == 1) { console.log("Load initial page: " + request.url()); request.continue(); return; } console.log("Block redirect to: " + request.url()); request.abort(); }); let response; try { console.log(`Request: ${pageUrl}`); response = await page.goto(pageUrl, { waitUntil: 'domcontentloaded' }); const content = await response.text(); console.log(content); await page.close(); await browser.close(); } catch (err) { console.log(err); } })() ¿Hay alguna manera de bloquear la ubicación de la window.location y obtener el HTML original (como se indica arriba) sin deshabilitar por completo javascript?
Incluso si escucho todas las respuestas:
page.on('response', async response => { if (response.ok && response.url() === pageUrl) { console.log(await response.text()); } }); No puede obtener el HTML original. Lanza Could not load body for this request. This might happen if the request is a preflight request. .
La sugerencia de @GrafiCode sobre page.setJavascriptEnabled(false) es buena: más adelante, puede revertirla configurando su valor en true .
Para solucionar el problema, puede seguir esto:
window.location se reasigne inmediatamente<script> que intentan manipular la ubicación ( page.$$eval o page.evaluate métodos de titiritero se pueden usar para ejecutar Element.remove() )page.content ).page.setContent )response.text() de la misma manera que lo intentó anteriormente (ya que setContent regresa de manera diferente a goto), pero puede usar page.$eval en el innerText de <body> const page = await browser.newPage() await page.setJavaScriptEnabled(false) await page.goto(pageUrl) await page.$$eval('script', scripts => scripts.forEach(src => { if (src.innerHTML.includes('window.location')) src.remove() }) ) const html = await page.content() await page.setJavaScriptEnabled(true) await page.setContent(html) const text = await page.$eval('body', el => el.innerText) console.log(text) Salida (el contenido de <p> ):
Page not found - Please wait while we redirect you home...No me di cuenta de que envié un código de error diferente ( aborted ) a request.abort le permite acceder a las solicitudes anteriores. Con eso pude acceder al texto de la respuesta original:
const page = await browser.newPage(); await page.setCacheEnabled(false); await page.setRequestInterception(true); const requests = []; let redirectBlocked = false; page.on('request', async request => { let isNavRequest = request.isNavigationRequest() && request.frame() === page.mainFrame(); if (!isNavRequest) { request.continue(); return; } requests.push(request); if (requests.length == 1) { request.continue(); return; } // *snip* more here to detect legitimate redirects... redirectBlocked = true; request.abort('aborted'); let originalResponse = await requests[0].response(); console.log(await originalResponse.text()); }); const response = await page.goto(pageUrl, { waitUntil: 'domcontentloaded' }); if (!redirectBlocked) console.log(await response.text());