2

I am trying to use jQuery on the pages I load with puppeteer and I wanted to know how I can do the same? My code structure is like:

const puppeteer = require('puppeteer');
let browser = null;
async function getSelectors() {
        try{
            browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']});
            const page = await browser.newPage();
            await page.setViewport({width: 1024, height: 1080});
            await page.goto('https://www.google.com/');
            await page.addScriptTag({url: 'https://code.jquery.com/jquery-3.2.1.min.js'});
            var button = $('h1').text();
            console.log(button);
        } catch (e) {
            console.log(e);
        }
}
getSelectors();

Also I will be navigating to many pages within puppeteer so is there a way I can just add jQuery once and then use it throughout? A local jquery file implementation would be helpful as well.

I tried implementing the answers from inject jquery into puppeteer page but couldn't get my code to work. I will be doing much more complex stuff than the one illustrated above so I need jQuery and not vanilla JS solutions.

Nagarjun Prasad
  • 802
  • 3
  • 17
  • 31
  • 2
    `var button = $('h1').text();` your calling this in the context of node.js, not the instance inside puppeteer. try placing inside a `page.evaluate`.. – Keith Mar 09 '18 at 11:15
  • @Keith thank you, that seemed to do the trick, is there any way I can add a local copy of jQuery? Also how can I make it so that I can use jQuery with all the pages I navigate to within puppeteer instead of injecting the script to each page. – Nagarjun Prasad Mar 09 '18 at 11:22
  • No, there isn't a way to inject a "local" copy of jQuery, since the code (in case of Puppeteer) is evaluated in the context of the browser. See https://github.com/cheeriojs/cheerio for a Node.js alternative. – Gajus Dec 26 '18 at 21:27
  • @Keith Sorry, just realised you basically answered this in your comment. You remind me of my Maths teacher who skipped the crucial lines that he assumed I could figure out without being told. The Puppeteer documentation for page.evaluate doesn't make sense to me and your quick comment wasn't enough to help me get this point. I wish you'd written it in an answer. You would definitely have got an upvote from me. – DavidHyogo Aug 12 '20 at 04:26
  • 1
    @DavidHyogo. I often reply on mobile, so sometimes my responses might be short. Hopefully my comments help push the OP in the right direction. But if clarification is needed I will usually give more detail if the OP requests it. – Keith Aug 12 '20 at 08:09

1 Answers1

2

I finally got a tip from How to scrape that web page with Node.js and puppeteer which helped me understand that the Puppeteer page.evaluate function gives you direct access to the DOM of the page you've just launched in Puppeteer. To get the following code to work, you should know I'm running this test in Jest. Also, you need a suitable URL to a page that has a table element with an ID. Obviously, you can change the details of both the page and the jQuery function you want to try out. I was in the middle of a jQuery Datatables project so I needed to make sure I had a table element and that jQuery could find it. The nice thing about this environment is that the browser is quite simply a real browser, so if I add a script tag to the actual HTML page instead of adding it via Puppeteer, it works just the same.

test('Check jQuery datatables', async () => {
   const puppeteer = require('puppeteer');
   let browser = await puppeteer.launch();
   let page = await browser.newPage();
   await page.goto('http://localhost/jest/table.html');
   await page.addScriptTag({url: 'https://code.jquery.com/jquery-3.3.1.slim.min.js'});
   const result = await page.evaluate(() => {
       try {
           var table = $("table").attr("id");
           return table;
       } catch (e) {
           return e.message;
       }
   });
   await console.log("result", result);
   await browser.close();
});

The key discovery for me: within the page.evaluate function, your JavaScript code runs in the familiar context of the page you've just opened in the browser. I've moved on to create tests for complex objects created using jQuery plugins and within page.evaluate they behave as expected. Trying to use JSDOM was driving me crazy because it behaved a bit like a browser, but was different with regard to the key points I was using to test my application.

DavidHyogo
  • 2,838
  • 4
  • 31
  • 48