Contenido del curso
Introducción a la Automatización WEB
Introducción a Puppeteer
Conociendo Puppeteer
Conclusión del curso
Extrayendo información
Contenido del curso
Extrayendo información
Yilmer Ramiro Guativa Rincón
EstudianteCristian Adrian Ayala
EstudianteIrving Juárez
EstudianteOsmel Jose Vera Isasis
EstudianteAgustin Cammarota Muti
EstudianteHernan Camilo Jimenez Garcia
EstudianteJavier Fuentes Mora
ProfesorJavier Fuentes Mora
ProfesorJulia Gabriela Nieva Paredes
EstudianteSergio Daniel Cienfuegos Torres
EstudianteAndrés Pereira
EstudianteJulianny Caicedo
EstudianteJulianny Caicedo
EstudianteDaniel Verdugo
EstudianteJavier Fuentes Mora
ProfesorEllioth Aguirre Gonzales
EstudianteDavid Camilo Salas Muñoz
EstudianteJose Rodrigo Ospina Reyes
EstudianteOsmel Jose Vera Isasis
EstudianteMario Alexander Vargas Celis
EstudianteEliud Hernandez Loza
EstudianteRodwel Polanco Martinez
EstudianteSamuel Espinoza Figueroa
EstudianteRodwel Polanco Martinez
EstudianteZANONI ALFREDO SALAS TOBÓN
EstudianteAlberto Alejandro Foinquinos Benitez
EstudianteUno 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?