i'm triying to read the td-child from a table that has a lot of Td-Child and I can't get the information back, my array comes back null.
here is the code:
const detalleDatos = await page2.$$eval('#gvContents > tbody', (users) => {
return users.map(user => {
// obtener la informacion de la tabla para generar el array
const orden = user.querySelector('td:nth-child(1)')
const pedido = user.querySelector('td:nth-child(2)')
const factura = user.querySelector('td:nth-child(3)')
const artículo = user.querySelector('td:nth-child(4)')
const sku = user.querySelector('td:nth-child(5)')
const unidadesContenedores = user.querySelector('td:nth-child(6)')
const unidadesContenedoresCargados = user.querySelector('td:nth-child(7)')
const PesoLb = user.querySelector('td:nth-child(8)')
const PesoKg = user.querySelector('td:nth-child(9)')
const CubosFt = user.querySelector('td:nth-child(10)')
const CubosM = user.querySelector('td:nth-child(11)')
const PrecioUd = user.querySelector('td:nth-child(12)')
const PrecioExt = user.querySelector('td:nth-child(13)')
return {
orden: orden.textContent.trim(),
pedido: pedido.textContent.trim(),
factura: factura.textContent.trim(),
artículo: artículo.textContent.trim(),
sku: sku.textContent.trim(),
unidadesContenedores: unidadesContenedores.textContent.trim(),
unidadesContenedoresCargados: unidadesContenedoresCargados.textContent.trim(),
PesoLb: PesoLb.textContent.trim(),
PesoKg: PesoKg.textContent.trim(),
CubosFt: CubosFt.textContent.trim(),
CubosM: CubosM.textContent.trim(),
PrecioUd: PrecioUd.textContent.trim(),
PrecioExt: PrecioExt.textContent.trim(),
}
})
})
based on what I know it should be reading the table an bringing me the information but for some reason it doesn't do it.
the structure of the HTML is the following:
I want to get the td information of all tr on the table.
I think your selector is selecting the table body, not all the table rows. But in any case, you can just define a function to do this specific task and pass the entire function into your eval statement. Here's an example that you might have to change a little bit, but it should scrape the data from every row in the table.
function getTableData() {
let results = [];
const table = document.getElementById('gvContents');
if (!table) {
throw Error('Table not found.');
}
// loop over all rows
table.querySelectorAll('tr').forEach((row) => {
// for each row, loop over all TDs
const rowResults = [];
row.querySelectorAll('td').forEach((item) => {
rowResults.push(item.innerText.trim());
});
results.push(rowResults);
});
console.log(results);
return results;
}
I recommend you put this above code into a Chrome DevTools Snipppet and edit/run it over and over again until you get what you want. Then, copy paste it into Playwright.
You can use the :scope method in playwright to collectively get all the innertexts in one go and then using the forEach loop get them one by one. Something like this:
const tdElements = page.locator('td')
const tdTexts = await tdElements.locator(':scope').allInnerTexts()
await tdTexts.forEach((text) => {
console.log(text.trim()) //prints each texts one by one
})
You can read more scope in the Playwright Docs.
Just add tr to your selector
const detalleDatos = await page2.$$eval('#gvContents tbody tr', (users) => {
return users.map(user => {
// obtener la informacion de la tabla para generar el array
const orden = user.querySelector('td:nth-child(1)')
const pedido = user.querySelector('td:nth-child(2)')
const factura = user.querySelector('td:nth-child(3)')
const artículo = user.querySelector('td:nth-child(4)')
const sku = user.querySelector('td:nth-child(5)')
const unidadesContenedores = user.querySelector('td:nth-child(6)')
const unidadesContenedoresCargados = user.querySelector('td:nth-child(7)')
const PesoLb = user.querySelector('td:nth-child(8)')
const PesoKg = user.querySelector('td:nth-child(9)')
const CubosFt = user.querySelector('td:nth-child(10)')
const CubosM = user.querySelector('td:nth-child(11)')
const PrecioUd = user.querySelector('td:nth-child(12)')
const PrecioExt = user.querySelector('td:nth-child(13)')
return {
orden: orden.textContent.trim(),
pedido: pedido.textContent.trim(),
factura: factura.textContent.trim(),
artículo: artículo.textContent.trim(),
sku: sku.textContent.trim(),
unidadesContenedores: unidadesContenedores.textContent.trim(),
unidadesContenedoresCargados: unidadesContenedoresCargados.textContent.trim(),
PesoLb: PesoLb.textContent.trim(),
PesoKg: PesoKg.textContent.trim(),
CubosFt: CubosFt.textContent.trim(),
CubosM: CubosM.textContent.trim(),
PrecioUd: PrecioUd.textContent.trim(),
PrecioExt: PrecioExt.textContent.trim(),
}
})
})
console.dir(detalleDatos);
Also, you can make a lookup of the columns
const cols = [
'orden',
'pedido',
'factura',
... and so on
}
const detalleDatos = await page2.$$eval('#gvContents tbody tr', (users) => {
return users.map(user => {
result = {}
cols.forEach((col, index) => {
const cell = user.querySelector(`td:nth-child(${index})`)
const text = cell.textContent.trim()
result[name] = text
}
return result
})
})