无法让 querySelectorAll 与 puppeteer 一起工作(returns 未定义)

Cannot get querySelectorAll to work with puppeteer (returns undefined)

我正在尝试使用超市的价格进行网络抓取。它与 node.js 和木偶操纵者一起使用。我可以通过接受 cookie 并单击“加载更多按钮”开始浏览网站。但是当我尝试阅读包含带有 querySelectorAll 的产品的 div 时,我卡住了。它 returns 未定义,即使我等待特定的 div 出现。我错过了什么?

问题出在代码块的末尾。

const { product } = require("puppeteer");

const scraperObjectAll = {
    url: 'https://www.bilkatogo.dk/s/?query=',
    async scraper(browser) {
        let page = await browser.newPage();
        console.log(`Navigating to ${this.url}`);
        await page.goto(this.url);

        // accept cookies
        await page.evaluate(_ => {
            CookieInformation.submitAllCategories();
        });

        var productsRead = 0;
        var productsTotal = Number.MAX_VALUE;

        while (productsRead < 100) {
            // Wait for the required DOM to be rendered
            await page.waitForSelector('button.btn.btn-dark.border-radius.my-3');
            // Click button to read more products
            await page.evaluate(_ => {
                document.querySelector("button.btn.btn-dark.border-radius.my-3").click()
            });
            // Wait for it to load the new products
            await page.waitForSelector('div.col-10.col-sm-4.col-lg-2.text-center.mt-4.text-secondary');
            // Get number of products read and total
            const loadProducts = await page.evaluate(_ => {
                let p = document.querySelector("div.col-10.col-sm-4.col-lg-2").innerText.replace("INDLÆS FLERE", "").replace("Du har set ","").replace(" ", "").replace(/(\r\n|\n|\r)/gm,"").split("af ");
                return p;
            });

            console.log("Products (read/total): " + loadProducts);
            productsRead = loadProducts[0];
            productsTotal = loadProducts[1];

            // Now waiting for a div element
            await page.waitForSelector('div[data-productid]');

            const getProducts = await page.evaluate(_ => {
                return document.querySelectorAll('div');
            });

            // PROBLEM HERE!
            // Cannot convert undefined or null to object
            console.log("LENGTH: " + Array.from(getProducts).length);
        }

传递给 page.evaluate 的回调在 模拟页面 上下文中运行,不在 节点脚本的标准范围内.如果没有仔细考虑,表达式不能在页面和 Node 脚本之间传递:最重要的是,如果某些东西不可序列化(转换为普通 JSON),它就不能被传输。

querySelectorAll returns一个NodeList,NodeList只存在于前端,不存在于后端。同样,NodeLists包含HTMLElements,同样只存在于前端。

将所有需要使用仅存在于前端的数据的逻辑放在.evaluate回调中,例如:

const numberOfDivs = await page.evaluate(_ => {
  return document.querySelectorAll('div').length;
});

const firstDivText = await page.evaluate(_ => {
  return document.querySelector('div').textContent;
});