使用Puppeteer,如何打开页面,获取数据,然后返回上一页以获取列表中的下一页?

The*_*mer 0 javascript node.js puppeteer

情况:

这是我想做的:

1)我加载页面0。页面0包含指向不同页面的可点击链接。我想加载所有这些页面的内容。所以:

2)点击第一个链接。加载页面1.获取数据。返回上一页(第0页)

3)单击第二个链接,该链接加载第2页。等等,直到所有链接都被单击为止。

在我当前的代码中,第0页加载,然后单击第一个链接并加载第1页,然后出现崩溃并显示以下错误:

(node:2629) UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Execution context was destroyed.
Run Code Online (Sandbox Code Playgroud)

题:

我在做什么错?如何使脚本按预期方式运行?


码:

const puppeteer = require('puppeteer');
const fs = require('fs');

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

    await page.goto('url', { waitUntil: 'networkidle2' });
    await page.setViewport({width: ..., height:...});

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

        for (const element of elements) {

            element.click();
            await new Promise((resolve) => setTimeout(resolve, 2000));

            // GETTING THE DATA THEN PUSHING IT INTO THE DATA ARRAY

            await page.goBack();
        }

        return data; // Return our data array

    });

    browser.close();
    return result; // Return the data
};
Run Code Online (Sandbox Code Playgroud)

Gra*_*ler 7

与其来回导航以单击第一页中的下一个链接,不如将第一页中的链接存储到一个数组中,然后使用page.goto().

换句话说,您可以使用以下示例完成此任务:

await page.goto('https://example.com/page-1');

const urls = await page.evaluate(() => Array.from(document.querySelectorAll('.link'), element => element.href));

for (let i = 0, total_urls = urls.length; i < total_urls; i++) {
  await page.goto(urls[i]);

  // Get the data ...
}
Run Code Online (Sandbox Code Playgroud)


AJC*_*C24 5

好,这是我的看法。首先,您使用的evaluate方法不正确。主要是因为您实际上并不需要它,还因为您要它执行它无法执行的操作。仅说明一下:该evaluate方法仅在您的网页上下文中运行。它几乎只允许您在远程浏览器的当前页面上直接执行Javascript指令。它没有在该函数的外部声明的变量的概念-因此,在这种情况下,执行此操作时:

await page.goBack();
Run Code Online (Sandbox Code Playgroud)

evaluate方法不知道是什么page,也不知道如何使用。现在有多种方法可以注入pageevaluate方法,但也无法解决您的问题。Puppeteer API调用根本无法在evaluate方法内部工作(我自己尝试过此方法,它始终会返回异常)。

因此,现在让我们回到您确实遇到的问题- evaluate函数中正在执行的操作是使用class检索一个UI元素,.items然后使用class 搜索该UI元素中的每个UI元素.item。然后,您将遍历所有找到的UI元素,单击每个UI元素,获取某种数据,然后返回以单击下一个。

您无需使用evaluate方法即可实现所有这些目的,而是使用Puppeteer API调用,如下所示:

const itemsList = await page.$('.items'); // Using '.$' is the puppeteer equivalent of 'querySelector'
const elements = await itemsList.$$('.item'); // Using '.$$' is the puppeteer equivalent of 'querySelectorAll'

const data = [];
elements.forEach(async (element) => {
  await element.click();
  // Get the data you want here and push it into the data array
  await page.goBack();
});
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助你!