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)
与其来回导航以单击第一页中的下一个链接,不如将第一页中的链接存储到一个数组中,然后使用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)
好,这是我的看法。首先,您使用的evaluate方法不正确。主要是因为您实际上并不需要它,还因为您要它执行它无法执行的操作。仅说明一下:该evaluate方法仅在您的网页上下文中运行。它几乎只允许您在远程浏览器的当前页面上直接执行Javascript指令。它没有在该函数的外部声明的变量的概念-因此,在这种情况下,执行此操作时:
await page.goBack();
Run Code Online (Sandbox Code Playgroud)
该evaluate方法不知道是什么page,也不知道如何使用。现在有多种方法可以注入page该evaluate方法,但也无法解决您的问题。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)
希望这可以帮助你!
| 归档时间: |
|
| 查看次数: |
2780 次 |
| 最近记录: |