javascript - 如何点击所有元素并等待每个元素完成 AJAX 请求以抓取数据? (AJAX每次都加载到同一个元素中)

标签 javascript node.js puppeteer

情况:

我目前正在学习使用 puppeteer 进行抓取。

由于某种原因,我当前的代码给出了这个错误:

“UnhandledPromiseRejectionWarning:错误:评估失败:ReferenceError:页面未定义”

(编辑)

问题是,当页面加载并单击每个项目时,数据不会被抓取,因为代码似乎没有在单击每个项目后等待它加载。

以下是代码应该执行的操作:

  1. 加载网页(确定)

  2. 点击每个项目(确定)

  3. 每次单击某个项目时,都会在左侧的 div 中加载一些数据,这就是我要抓取的数据。 (目前不会发生)

  4. 为了实现这一点,我让代码在单击后等待 2 秒以加载数据。 (目前不会发生)


问题:

我该如何解决这个问题并适本地抓取所述数据?


代码:

const puppeteer = require('puppeteer');

let scrape = async () => {
    const browser = await puppeteer.launch({headless: false});
    const page = await browser.newPage();

    await page.goto('https://website.com');
    await page.setViewport({width: ..., height: ...});

    const result = await page.evaluate(() => {
        let data = []; 
        let elements = document.querySelector('.class1').querySelectorAll('.class2'); 

        for (var element of elements){
            page.click(element);
            page.waitFor(2000);
            let 1 = document.querySelector('.class0').querySelector('.class3').getAttribute("data-1");
            let 2 = document.querySelector('.class0').querySelector('.class4').innerText;
            let 3 = document.querySelector('.class0').querySelector('.class5').innerText;
            let 4 = document.querySelector('.class0').querySelector('.class6').innerText;
            data.push({1: 1, 2: 2, 3: 3, 4: 4}); // Push an object with the data onto our array
        }

        return data; // Return our data array
    });

    browser.close();
    return result; // Return the data
};

scrape().then((value) => {
    console.log(value); // Success!
});

最佳答案

此代码存在一些问题:

  • 12 等不是有效的标识符(不过我猜这只是为了示例)
  • .click().waitFor() 会返回 Promise,您不会等待,但无论如何......
  • 您传递给 evaluate 的函数是在页面上下文中计算的,而不是 Node.JS 代码,因此 page 不存在

相反,您可以直接在函数中与页面交互,就像您已经做的那样:

const puppeteer = require('puppeteer');

let scrape = async () => {
    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();

    await page.goto('https://website.com');
    await page.setViewport({ width: ..., height: ... });

    const result = await page.evaluate(async () => {
        const data = [];
        const elements = document.querySelector('.class1').querySelectorAll('.class2');

        for (const element of elements) {
            element.click();
            await new Promise((resolve) => setTimeout(resolve, 2000));
            const one = document.querySelector('.class0').querySelector('.class3').getAttribute("data-1");
            const two = document.querySelector('.class0').querySelector('.class4').innerText;
            const three = document.querySelector('.class0').querySelector('.class5').innerText;
            const four = document.querySelector('.class0').querySelector('.class6').innerText;
            data.push({ 1: 1, 2: 2, 3: 3, 4: 4 }); // Push an object with the data onto our array
        }

        return data; // Return our data array
    });

    browser.close();
    return result; // Return the data
};

scrape().then((value) => {
    console.log(value); // Success!
});

关于javascript - 如何点击所有元素并等待每个元素完成 AJAX 请求以抓取数据? (AJAX每次都加载到同一个元素中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51448914/

相关文章:

javascript - 等待使用 puppeteer 显示 Google Captcha

node.js - 页面在继续之前不会等待另一个页面完成其任务

javascript - 数据未通过 MongoDB 集合

Javascript:如何按数组中的对象值对数组进行排序?

mysql - 带有 Typescript 的 NodeJS MySQL 中的数据库 Controller

javascript - 在nodejs上连接4个不同的redis服务器createClient(不使用集群)

javascript - 如何阻止我的 Facebook 共享窗口被弹出窗口拦截程序拦截?

javascript - angularjs - 表单和验证

Javascript在try block 内设置const变量

javascript - Puppeteer:从使用延迟加载的页面中抓取整个 html