Extrayendo información
Clase 12 de 15 • Curso de Automatización de Pruebas con Puppeteer
Contenido del curso
Clase 12 de 15 • Curso de Automatización de Pruebas con Puppeteer
Contenido del curso
Yilmer Ramiro Guativa Rincón
Cristian Adrian Ayala
Irving Juárez
Osmel Jose Vera Isasis
Agustin Cammarota Muti
Hernan Camilo Jimenez Garcia
Javier Fuentes Mora
Javier Fuentes Mora
Julia Gabriela Nieva Paredes
Sergio Daniel Cienfuegos Torres
Andrés Pereira
Julianny Caicedo
Julianny Caicedo
Daniel Verdugo
Javier Fuentes Mora
Ellioth Aguirre Gonzales
David Camilo Salas Muñoz
Jose Rodrigo Ospina Reyes
Osmel Jose Vera Isasis
Mario Alexander Vargas Celis
Eliud Hernandez Loza
Rodwel Polanco Martinez
Samuel Espinoza Figueroa
Rodwel Polanco Martinez
ZANONI ALFREDO SALAS TOBÓN
Alberto Alejandro Foinquinos Benitez
Uno de los problemas que tenia era que cuando fallaba una pruba no cierra el navegador pero con el siguiente codigo me funciona
const puppeteer = require('puppeteer'); describe('Tipos de espera', () => { let browser; beforeAll( async () => { browser = await puppeteer.launch({ headless: false, defaultViewport: null }) }); it('mostrar los tipos de espera', async () => { const page = await browser.newPage() ..... // code }, 20000) afterAll(async () => { await browser.close() }); });
Buen aporte Yilmer, thanks!
El afterAll no necesariamente tiene que ir hasta abajo de tu codigo, de hecho normalmente se ponen hasta arriba.
.
Tu codigo funciona solo si el modo headless esta en false. Una vez que quieras corres tus pruebas sin abrir el navegador te va a salir un error porque se va a querer cerrar un browser que jamas se abrio.
.
Por eso es bueno hacer una validacion para saber si el browser esta abierto, y si sí lo esta, entonces lo cerramos.
.
Para esto primero agregamos un userAgent al browser:
beforeAll(async () => { browser = await puppeteer.launch({ defaultViewport: null, headless: true, args: ["--user-agent=foo"] }) })
Y despues la validacion quedaria de la siguiente manera:
afterAll(async () => { const browserOpen = await page .evaluate(() => navigator.userAgent) if (browserOpen) { browser.close() } }, MAX_TIMEOUT)
BUNEAS COMPARTO UNA SOLUCION AL EXTRAYENDO EN XPATH DEBIDO A QUE EN EL VIDEO YA EL CODIGO NO ES FUNCIONAL PARA EL 2024
Dejo una manera mas optimo de plantearla para no repetir tanto código.
const puppeteer = require('puppeteer'); describe('Extraer informacion', () => { let browser; let page; beforeAll(async () => { browser = await puppeteer.launch({ headless: false, defaultViewport: null }); }); afterAll(async () => { await browser.close(); }); beforeEach(async () => { page = await browser.newPage(); await page.goto('https://platzi.com/', { waitUntil: 'networkidle2', }); }); afterEach(() => { page = ''; }); it('Extraer el contenido del titulo y url', async () => { const title = await page.title(); const url = await page.url(); expect(title).toBe('No importa el reto, prepárate en Platzi'); expect(url).toBe('https://platzi.com/'); }, 5000); it('Extraer informacion del selector - forma 1', async () => { const selector = await page.waitForSelector('#cms-landings > section > section.Hero > div > p.Hero-content-subtitle'); const button = await page.evaluate((name) => name.textContent, selector); console.log(button); expect(button).toBe('La plataforma de aprendizaje en línea donde puedes desarrollar tus habilidades y adaptarte al futuro profesional.'); }, 5000); it('Extraer informacion del selector - forma 2', async () => { await page.waitForSelector('#cms-landings > section > section.Hero > div > p.Hero-content-subtitle'); const button = await page.$eval('#cms-landings > section > section.Hero > div > p.Hero-content-subtitle', (button) => button.textContent); console.log(button); expect(button).toBe('La plataforma de aprendizaje en línea donde puedes desarrollar tus habilidades y adaptarte al futuro profesional.'); }, 5000); it('Constar elementos de una pagina', async () => { // $$eval es un query selector all - trae varios elementos (Array) // ¢eval es un query selector - trae el primer elemento const elementos = await page.$$eval('img', (imagenes) => imagenes.length); expect(elementos).toBe(18); }, 5000) });
Veo qie el profe nunca usa punto y coma después de una instrucción. Es buena práctica usarlas o no tiene absolutamente nada qué ver?
Hola en javascript no es necesario, es a gusto solo hay muy muy pocas veces que puede ser requerido , pero si tu las quieres puedes configurar en el .prettierrc para que se agreguen solitas después de cada linea
no tiene nada que ver es a gusto personal , puedes configurar prettier para que te lo agregue o para que lo quite automaticamente Solo hay muy muy muy pocos casos donde un punto y coma si es necesario pero al menso en la practica nunca lo he necesitado
Muy difícil porque hay que estar investigando las funciones nuevas. Muchas de las que usa el profe ya no existen en el 2024.
a mi me salió "undefined" en el Console.log cuando use:
button.textContent
Pero se puede convertir a HTML agregando un [0]:
button[0].textContent
y ya salió el texto del botón :3
Algunas líneas del código son muy largas, en ese caso resulta conveniente para mejorar la visibilidad activar el Ajuste de palabra (Word Wrap) en VSCode (atajo Alt+Z).
PUPPETER HA TENIDO MUCHAS ACTUALIZACIONES
const puppeteer = require('puppeteer');
describe('Scraping Quotes', () => {
it('Extrae frases y autores', async () => {
const browser = await puppeteer.launch({
headless: false
});
try {
const page = await browser.newPage();
await page.goto('https://quotes.toscrape.com', {
waitUntil: 'domcontentloaded'
});
await page.waitForSelector('.quote');
const quotes = await page.$$eval('.quote', elements =>
elements.map(el => ({
texto: el.querySelector('.text').innerText,
autor: el.querySelector('.author').innerText
}))
);
console.log(quotes);
} finally {
await browser.close();
}
}, 30000);
});
const puppeteer = require('puppeteer');
describe('Extrayendo Información', () => {
it('Extraer el título de la página y la url', async () => {
const browser = await puppeteer.launch({
headless: false,
defaultViewport: null
});
const page = await browser.newPage();
await page.goto('https://www.google.com', {waitUntil: 'networkidle0'});
await new Promise(resolve => setTimeout(resolve, 5000)); // espera 5s entre recargas
const titulo = await page.title()
const url = await page.url()
console.log(Título: ${titulo});
console.log(URL: ${url});
await browser.close();
}, 60000);
});
Voy a extraer información de una web que tiene tablas sin selectores ni estilos, son las puras etiquetas table, tbody y td por esa razón usaré XPath, pero me trae la información de una forma muy rara y en un arreglo. ¿Será que hay que hacer algo más a parte de lo que enseña el profe en el minuto 14:00?
podrías hacer algo como esto:
const tabla = await page.evaluate(() => { const rows = document.querySelectorAll('#tabla-id tr'); return Array.from(rows, row => { const columns = row.querySelectorAll('td'); return Array.from(columns, column => column.innerText); }); }); Te dará un una matriz y podrás acceder a este como si puedan coordenadas console.log(tabla[1][2]);
const puppeteer = require("puppeteer") describe("Extrayendo info", () => { it("Extraer el titulo de la pagina y url", async () => { const browser = await puppeteer.launch({ headless: false, defaultViewport: null, // slowMo: 500 }) const page = await browser.newPage() await page.goto("https://platzi.com", { waitUntil: "networkidle2" }) const title = await page.title() const url = await page.url() console.log("title: ", title) console.log("url: ", url) // Si necesitas seleccionar un elemento por selector CSS: await page.waitForSelector("button[data-id='atomic-ui-button-layout']") // si necesitas acceder al texto: const button = await page.$eval("button[data-id='atomic-ui-button-layout']", (btn) => btn.textContent) console.log("button", button) // Si necesitas seleccionar un elemento por XPath: const button2 = await page.waitForSelector("::-p-xpath(/html/body/main/header/div/div[2]/div[2]/div[2]/button)") const buttonText = await page.evaluate((name) => name.textContent, button2) console.log("buttonText", buttonText) // Y si necesitas seleccionar varios elementos por XPath: const allButtons = await page.$$("::-p-xpath(//button)") console.log("allButtons", allButtons.length) await browser.close() }, 35000) }) ```El codigo 2025:
Deben actualizar el código
Me sale un error al utilizar "page.$x" dice, no es una función, alguno le paso ?
HOLA AMIGO DEJE UNA SOLUCION ARRIBA EN LOS COMENTARIOS MAS RECIENTES
const puppeteer = require("puppeteer") describe("Extrayendo informacion",()=>{ it("Extraer el titulo de la pagina y url", async()=>{ const browser = await puppeteer.launch({ headless:false, defaultViewport: null, //slowMo: 500 }); const page = await browser.newPage(); await page.goto("https://platzi.com", {waitUntil: "networkidle2"}); const titulo = await page.title(); const url = await page.url(); console.log("titulo", titulo); console.log("url", url); //await new Promise((resolve) => setTimeout(resolve, 3000)); await browser.close(); }, 35000); it("Extraer la información d eun elemento", async()=>{ const browser = await puppeteer.launch({ headless:false, defaultViewport: null, //slowMo: 500 }); const page = await browser.newPage(); await page.goto("https://platzi.com", {waitUntil: "networkidle2"}); await page.waitForSelector("body > main > header > div > nav > ul > li:nth-child(4) > a"); const nombreBoton = await page.$eval("body > main > header > div > nav > ul > li:nth-child(4) > a", (button) => button.textContent); const [button] = await page.$x("/html/body/main/section[1]/a/div/div[2]/div[2]/button"); const propiedad = await button.getProperty("textContent"); const texto = await propiedad.jsonValue(); //console.log("texto", texto); //Segunda Forma const texto2 = await page.evaluate((name)=>name.testContent, button); const button3 = await page.waitForXPath("/html/body/main/section[1]/a/div/div[2]/div[2]/button"); const texto3 = await page.evaluate((name)=>name.testContent, button3); console.log("texto3", texto3); await browser.close(); }, 35000); it("Contar los elementos d euna pagina", async()=>{ const browser = await puppeteer.launch({ headless:false, defaultViewport: null, //slowMo: 500 }); const page = await browser.newPage(); await page.goto("https://platzi.com", {waitUntil: "networkidle2"}); const images = await page.$$eval("img",(imagenes) => imagenes.length); console.log("images", images) await browser.close(); }, 50000); }) ```const puppeteer = require("puppeteer") describe("Extrayendo informacion",()=>{   it("Extraer el titulo de la pagina y url", async()=>{   const browser = await puppeteer.launch({   headless:false,   defaultViewport: null,    //slowMo: 500   });   const page = await browser.newPage();   await page.goto("https://platzi.com", {waitUntil: "networkidle2"});   const titulo = await page.title();   const url = await page.url();   console.log("titulo", titulo);   console.log("url", url);       //await new Promise((resolve) => setTimeout(resolve, 3000));   await browser.close();   }, 35000);   it("Extraer la información d eun elemento", async()=>{   const browser = await puppeteer.launch({   headless:false,   defaultViewport: null,    //slowMo: 500   });   const page = await browser.newPage();   await page.goto("https://platzi.com", {waitUntil: "networkidle2"});   await page.waitForSelector("body > main > header > div > nav > ul > li:nth-child(4) > a");   const nombreBoton = await page.$eval("body > main > header > div > nav > ul > li:nth-child(4) > a", (button) => button.textContent);   const \[button] = await page.$x("/html/body/main/section\[1]/a/div/div\[2]/div\[2]/button");   const propiedad = await button.getProperty("textContent");   const texto = await propiedad.jsonValue();   //console.log("texto", texto);   //Segunda Forma   const texto2 = await page.evaluate((name)=>name.testContent, button);   const button3 = await page.waitForXPath("/html/body/main/section\[1]/a/div/div\[2]/div\[2]/button");   const texto3 = await page.evaluate((name)=>name.testContent, button3);   console.log("texto3", texto3);   await browser.close();   }, 35000);     it("Contar los elementos d euna pagina", async()=>{   const browser = await puppeteer.launch({   headless:false,   defaultViewport: null,    //slowMo: 500   });   const page = await browser.newPage();   await page.goto("https://platzi.com", {waitUntil: "networkidle2"});       const images = await page.$$eval("img",(imagenes) => imagenes.length);   console.log("images", images)   await browser.close();   }, 50000); })
Me marca error al intentar utilizar la función page.$x(''), al parecer ya no sirve esa función o algo
Page.$() method | Puppeteer (pptr.dev) Esta es la documentacion de page.
Probablemente lo que estas usando ya no es soportado por la libreria.
TimeoutError: Navigation timeout of 30000 ms exceededJest He estado batallando con este error, si a alguien mas lo tiene y ya lo soluciono les agradeceria que me ayudaran
Ayudaria saber la linea de codigo donde te da el error.
const puppeteer = require('puppeteer'); describe('Tipos de espera', () => { let browser; let page; // Configuración: se ejecuta antes de todas las pruebas beforeAll(async () => { // Iniciar el navegador de Puppeteer con opciones browser = await puppeteer.launch({ headless: false, // Ejecución con interfaz gráfica (para depuración) defaultViewport: null // Permitir que la página se adapte al tamaño del navegador }); }); // Prueba: Mostrar los tipos de espera it('Mostrar los tipos de espera', async () => { // Crear una nueva página del navegador para cada prueba page = await browser.newPage(); // Navegar a la página deseada await page.goto('tu_url_aqui'); // Esperar a que el botón se cargue usando XPath const buttonXPath = "//*[@id='material-view']/div[2]/div[2]/div/div[1]/div/form/div[2]/button"; const button = await page.waitForXPath(buttonXPath); // Extraer el texto del botón usando evaluate const texto2 = await page.evaluate((element) => element.textContent, button); console.log(`Texto del botón: ${texto2}`); // Cerrar la página después de la prueba await page.close(); }, 20000); // Limpieza: se ejecuta después de todas las pruebas afterAll(async () => { // Cerrar el navegador después de todas las pruebas await browser.close(); }); });
Encontre esta manera de sacar el texto del boton con xpath
const [button] = await page.$x('//*[@id="Header-v2"]/nav/div[5]/div/a'); console.log("boton login: ", await(await button.getProperty('textContent')).jsonValue());
Pero no me termina de convencer ni esta ni la que esta en el video, a alguien se le ocurre otra?