user1584421
user1584421

Reputation: 3843

Puppeteer - Removing elements by class

I try to remove elements by classname but it doesn't work.

This is the code i used:

await page.screenshot({path: 'pic.png'});   //for testing purposes
    let div_selector_to_remove= ".xj7.Kwh5n";
    var thingToRemove = document.querySelectorAll(div_selector_to_remove);
    var number_of_elements = thingToRemove.length;
    for (var i = 0; i < number_of_elements.length; i++) {
        thingToRemove[i].parentNode.removeChild(thingToRemove);
    }

The browser loads and i get a screenshot with the elements loaded. The nothing happens. The elements remain there

Upvotes: 17

Views: 25682

Answers (4)

ggorlen
ggorlen

Reputation: 56895

Probably easier than the accepted answer, which isn't idiomatic...

Remove the first node matching selector:

await page.$eval(selector, el => el.remove());

Remove all nodes matching selector:

await page.$$eval(selector, els => els.forEach(el => el.remove()));

Wait for a selector, then remove it:

const el = await page.waitForSelector(selector);
await el.evaluate(el => el.remove());

If for some reason you need to select and remove in console browser-land:

const selector = ".foo";

// single
await page.evaluate(`
  document.querySelector("${selector}").remove()
`);

// multiple
await page.evaluate(selector =>
  document.querySelectorAll(selector).forEach(el => el.remove()),
  selector
);

You can hardcode the selector into the eval string/function as well but I figured it'd be useful to show it coming from a variable in two different ways just in case.

As with anything in Puppeteer, understanding which code runs in Node/Puppeteer-land and which code runs in browser/console-land is extremely important. The rule of thumb is: if it's a callback or stringified function body, it's in the browser and you can only use browser/DOM concepts like HTMLElement.remove(), window and document, otherwise it runs in Node and you can only call Puppeteer API functions. In OP's case, it looks like we're outside of a callback in Node-land, so document isn't a thing, only Puppeteer page. functions.

Upvotes: 7

Aymen Jarouih
Aymen Jarouih

Reputation: 514

    //Wait for the element with id="xe7COe" to show up
    await page.waitForSelector('#xe7COe');
    //delete the element with id="xe7COe"  
    await page.evaluate(() => document.querySelector('#xe7COe').remove());

Upvotes: 1

Tripti Rawat
Tripti Rawat

Reputation: 671

Run document.querySelector inside page.evaluate. Here's my answer:

await page.goto('<url_here>');
let div_selector_to_remove= ".xj7.Kwh5n";
await page.evaluate((sel) => {
    var elements = document.querySelectorAll(sel);
    for(var i=0; i< elements.length; i++){
        elements[i].parentNode.removeChild(elements[i]);
    }
}, div_selector_to_remove)

Upvotes: 33

hong4rc
hong4rc

Reputation: 4103

First, number_of_elements is number.

But you call number_of_elements.length.

Next, thingToRemove[i].parentNode.removeChild(thingToRemove), thingToRemove[i].parentNode is parent of thingToRemove[i], not thingToRemove,

so you can't remove thingToRemove from thingToRemove[i].parentNode.

I think this code may be useful.

await page.screenshot({path: 'pic.png'});   //for testing purposes
let div_selector_to_remove= ".xj7.Kwh5n";
var thingToRemove = document.querySelectorAll(div_selector_to_remove);
var number_of_elements = thingToRemove.length;
for (var i = 0; i < number_of_elements; i++) {
    thingToRemove[i].parentNode.removeChild(thingToRemove[i]);
}

Upvotes: 1

Related Questions